 Rem File: Dndsub1 for Dndbbs Version v5.0a Release r2.0
 Rem $Include: 'dndbbs.inc'

Function ValidFormat$(V$)
 On Local Error Goto ErrTrapXX
 ValidFormat$=Format$(Now,V$)
ErrResumeXX:
 Exit Function
ErrTrapXX:
 ValidFormat$="<error>"
 Resume ErrResumeXX
End Function

Sub Modem.Status
 On Local Error Goto ErrTrap1
 If Bypass.Screen Then
    Exit Sub
 Endif
 Out3=Strng
 If Blank.Screen Then
    Blank.Screen=False
    Call Opening.Screen
 Endif
 Call ScreenANSI(4,37,0)
 Call ScreenANSI(4,44,31)
 Call ScreenANSI(2,23,10)
 Strng=Out3
 VarZ=Local.Mode
 Local.Mode=True
 Call Convert.ANSI(False,VarQ,VarR) ' convert prefixes
 Local.Mode=VarZ
 Out3=Strng
 Out3=Left$(Out3,14)
 Out3=Out3+Space$(14-Len(Out3))
 Call Scrn(Out3)
 Call Display.Time
 Strng=Out3
ErrResume1:
 Exit Sub
ErrTrap1:
 Resume ErrResume1
End Sub

Sub Display.Time
 On Local Error Goto ErrTrap2
 If Blank.Screen Then
    Exit Sub
 Endif
 Gosub Get.ConfigX
 Call ScreenANSI(4,37,0)
 Call ScreenANSI(4,44,31)
 Call ScreenANSI(2,23,50)
 Strng=D1$
 VarZ=Local.Mode
 Local.Mode=True
 Call Convert.ANSI(False,VarQ,VarR) ' convert prefixes
 D1$=Strng
 Strng=ValidFormat$(D1$)
 Call Scrn(Strng)
 Call ScreenANSI(4,37,0)
 Call ScreenANSI(4,44,31)
 Call ScreenANSI(2,23,61)
 Strng=T1$
 Call Convert.ANSI(False,VarQ,VarR) ' convert prefixes
 Local.Mode=VarZ
 T1$=Strng
 Strng=ValidFormat$(T1$)
 Tmp1=Len(Strng)
 Call Scrn(Strng)
 Locate 23,61+Tmp1,1
 Exit Sub
Get.ConfigX:
 VarX=0
 D1$="ddd dd mmm"
 T1$="hh:mm:ssa/p"
 Do
    VarX=VarX+1
    If VarX>Options.Lines Then
       Exit Do
    Endif
    Var$=Ltrim$(Rtrim$(Options.Array(VarX)))
    If Ucase$(Var$)="[DNDBBS]" Then
       Do
          VarX=VarX+1
          If VarX>Options.Lines Then
             Exit Do
          Endif
          Var$=Ltrim$(Rtrim$(Options.Array(VarX)))
          If Ucase$(Var$)="[END]" Then
             Exit Do
          Endif
          Var=Instr(Var$,"=")
          If Var Then
             Var2$=Lcase$(Ltrim$(Rtrim$(Left$(Var$,Var-1))))
             Var3$=Ltrim$(Rtrim$(Mid$(Var$,Var+1)))
             If Var2$="date.display" Then
                If Len(Var3$) Then
                   If Left$(Var3$,1)=Chr$(34) And Right$(Var3$,1)=Chr$(34) Then
                      Var3$=Left$(Var3$,Len(Var3$)-1) : Var3$=Mid$(Var3$,2)
                   Endif
                   Var3$=Ltrim$(Rtrim$(Var3$))
                   If Len(Var3$) Then
                      D1$=Var3$
                   Endif
                Endif
             Endif
             If Var2$="time.display" Then
                If Len(Var3$) Then
                   If Left$(Var3$,1)=Chr$(34) And Right$(Var3$,1)=Chr$(34) Then
                      Var3$=Left$(Var3$,Len(Var3$)-1) : Var3$=Mid$(Var3$,2)
                   Endif
                   Var3$=Ltrim$(Rtrim$(Var3$))
                   If Len(Var3$) Then
                      T1$=Var3$
                   Endif
                Endif
             Endif
          Endif
       Loop
    Endif
 Loop
 Return
ErrResume2:
 Exit Sub
ErrTrap2:
 Resume ErrResume2
End Sub

Sub Opening.Screen
 On Local Error Goto ErrTrap3
 Dim Menu.Array(1 To 6) As Integer
 Gosub Get.Config2
 Filename=DND.Path+"FREEDISK.OUT"
 If Dir$(Filename)="" Then
    Filename=DND.Path+"BYTEFREE.EXE"
    Call Shell.Program("BYTEFREE.EXE","")
 Endif
 Var2$="256.00 MB"
 Temp#=0#
 Filename=DND.Path+"FREEDISK.OUT"
 If Dir$(Filename)<>"" Then
    Close #TempFile1
    Open Filename For Input As #TempFile1
    If Eof(TempFile1)=0 Then
       Line Input #TempFile1,Strng2
       Temp#=Int(Val(Strng2))
       Call Make.Format(Temp#)
       Var2$=Strng
    Endif
 Endif
 Call Playwav(1)
 If Bypass.Screen=False Then
    If Config2(106) Then
       Def Seg=False
       Poke &H0417,0
       Def Seg
    Endif
 Endif
 Selection=1
 Call ScreenANSI(4,37,0)
 Call ScreenANSI(4,44,31)
 Call ScreenANSI(3,0,0)
 If Max.Row=43 Then
    Width 80,Max.Row
    Locate Max.Row,1,1
    Call Shell.Program("ANSI.EXE","43")
    Locate ,,0
 Endif
 If Max.Row=50 Then
    Width 80,Max.Row
    Locate Max.Row,1,1
    Call Shell.Program("ANSI.EXE","50")
    Locate ,,0
 Endif
 Call ScreenANSI(2,24,1)
 Call ScreenANSI(4,33,0)
 Call ScreenANSI(4,44,30)
 Call ScreenANSI(2,2,3)
 If Border.Off=0 Then
    If Border.Char=0 Then
       Strng=Chr$(201)
       Call Scrn(Strng)
       Strng=String$(74,205)
       Call Scrn(Strng)
       Strng=Chr$(187)
       Call Scrn(Strng)
    Else
       Strng="+"
       Call Scrn(Strng)
       Strng=String$(74,"-")
       Call Scrn(Strng)
       Strng="+"
       Call Scrn(Strng)
    Endif
 Endif
 Redim Temp.ArrayS(1 To 12) As String
 Filename$=DND.Path+"copyrite.dat"
 If Dir$(Filename$)<>Nul Then
    Close TempFile1
    Open FileName For Input Shared As #TempFile1
    VarX=0
    Do Until Eof(TempFile1)
       Line Input #TempFile1,Var$
       Var$=Ltrim$(Var$)
       If Len(Var$) Then
          If Left$(Var$,1)=Chr$(34) And Right$(Var$,1)=Chr$(34) Then
             Var$=Left$(Var$,Len(Var$)-1) : Var$=Mid$(Var$,2)
          Endif
          If Left$(Var$,1)<>";" Then
             VarX=VarX+1
             If VarX>=7 And VarX<=12 Then
                If Left$(Lcase$(Var$),4)="alt-" Then
                   VarQ$=Lcase$(Rtrim$(Mid$(Var$,5,1)))
                   If Len(VarQ$)=1 Then
                      VarQ=Instr("dpwxyz",VarQ$)
                      If VarQ Then
                         If Menu.Array(VarQ) Then
                            Var$=Var$+"  <n/a>"
                         Endif
                      Endif
                   Endif
                Endif
             Endif
             If VarX>=1 And VarX<=12 Then
                Temp.ArrayS(VarX)=Var$
             Endif
          Endif
       Endif
    Loop
 Endif
 Temp1=1
 For Temp5=3 To 24
    Call ScreenANSI(4,33,0)
    Call ScreenANSI(4,44,30)
    Call ScreenANSI(2,Temp5,3)
    If Border.Off=0 Then
       If Border.Char=0 Then
          Strng=Chr$(186)
       Else
          Strng="|"
       Endif
       Call Scrn(Strng)
    Endif
    Select Case Temp5
    Case 5 To 16
       Strng=Rtrim$(Temp.ArrayS(Temp5-4))
       If Len(Strng) Then
          Mid$(Strng,1,1)=Ucase$(Mid$(Strng,1,1))
       Endif
    End Select
    Select Case Temp5
    Case 5 To 10
       Call ScreenANSI(4,37,0)
       Call ScreenANSI(4,44,31)
    Case 11 To 16
       Call ScreenANSI(4,33,0)
       Call ScreenANSI(4,44,30)
    End Select
    Select Case Temp5
    Case 5
       Call ScreenANSI(2,4,10)
       Call Scrn(Strng)
    Case 6
       Call ScreenANSI(2,6,10)
       Strng="Version v"+Version$+" r"+Release$+" ("+YearRelease$+")"
       Call Scrn(Strng)
       Call Copyright(-2)
       Call Amount2(Run.Number,Var$)
       Strng="Run: "+RunMode$+Var$
       Temp=74-Len(Strng)
       Call ScreenANSI(2,6,Temp)
       Call Scrn(Strng)
    Case 8 To 16
       VarQ1=True
       If (Bypass.Splash And 1)=1 Then
          If Temp5>=11 Then
             VarQ1=False
          Endif
       Endif
       If (Bypass.Splash And 2)=2 Then
          If Temp5<11 Then
             VarQ1=False
          Endif
       Endif
       If (Bypass.Splash And 1)=1 Then
          If (Bypass.Splash And 2)=0 Then
             If Temp5=11 Then
                VarQ1=True
                Strng=Rtrim$(GuestRecord.SysopEmail)
                If Strng=Nul Then
                   Strng="dndbbs@gmail.com"
                Endif
             Endif
          Endif
       Endif
       If VarQ1 Then
          Call ScreenANSI(2,Temp5,28)
          If Right$(Rtrim$(Strng),5)="<n/a>" Then
             Var$=Left$(Strng,Len(Strng)-6)
             Call Scrn(Var$)
             Call ScreenANSI(4,37,0)
             Call ScreenANSI(4,44,31)
             Call ScreenANSI(2,Temp5,28+Len(Var$))
             Strng="<n/a>"
          Endif
          Call Scrn(Strng)
       Endif
    End Select
    If Temp1<6 Then
       If Temp5=Menu2(Temp1,1) Then
          Call ScreenANSI(4,33,0)
          Call ScreenANSI(4,44,30)
	  Var1=Menu2(Temp1,1)
	  Var2=Menu2(Temp1,2)
          Call ScreenANSI(2,Var1,Var2)
	  Strng="F"+Mid$(Str$(Temp1),2)+" "
	  Call Scrn(Strng)
          Call ScreenANSI(4,37,0)
          Call ScreenANSI(4,44,31)
          Strng=Left$(Menu1(Temp1),1)
	  Call Scrn(Strng)
          Call ScreenANSI(4,33,0)
          Call ScreenANSI(4,44,30)
          Strng=Mid$(Menu1(Temp1),2)
	  Strng=Rtrim$(Strng)
          VarZ=Local.Mode
          Local.Mode=True
          Call Convert.String ' convert macros
          Call Convert.ANSI(False,VarQ,VarR) ' convert prefixes
          Local.Mode=VarZ
	  Call Scrn(Strng)
          Call ScreenANSI(4,33,0)
          Call ScreenANSI(4,44,30)
	  Var1=Menu2(Temp1+5,1)
	  Var2=Menu2(Temp1+5,2)
          Call ScreenANSI(2,Var1,Var2)
          Strng="F"+Mid$(Str$(Temp1+5),2)+" "
	  Call Scrn(Strng)
          Call ScreenANSI(4,37,0)
          Call ScreenANSI(4,44,31)
          Strng=Left$(Menu1(Temp1+5),1)
	  Call Scrn(Strng)
          Call ScreenANSI(4,33,0)
          Call ScreenANSI(4,44,30)
          Strng=Mid$(Menu1(Temp1+5),2)
	  Strng=Rtrim$(Strng)
          VarZ=Local.Mode
          Local.Mode=True
          Call Convert.String ' convert macros
          Call Convert.ANSI(False,VarQ,VarR) ' convert prefixes
          Local.Mode=VarZ
	  Call Scrn(Strng)
	  Temp1=Temp1+1
       Endif
    Endif
    Select Case Temp5
    Case 18
       Call ScreenANSI(4,36,0)
       Call ScreenANSI(4,44,27)
       Call ScreenANSI(2,18,10)
       Strng="Ansi"
       Call Scrn(Strng)
       Call ScreenANSI(2,18,24)
       Strng="Avatar"
       Call Scrn(Strng)
       Call ScreenANSI(2,18,36)
       Strng="Share"
       Call Scrn(Strng)
       Call ScreenANSI(2,18,50)
       Strng="Fossil"
       Call Scrn(Strng)
       Call ScreenANSI(2,18,61)
       Strng="Port"
       Call Scrn(Strng)
       Call ScreenANSI(2,18,71)
       Strng="Disk"
       Call Scrn(Strng)
       Call ScreenANSI(4,37,0)
       Call ScreenANSI(4,44,31)
       Call ScreenANSI(2,19,10)
       If Local.ANSI.Color Then
	  Strng="Yes"
       Else
	  Strng="No"
       Endif
       Call Scrn(Strng)
       Call ScreenANSI(2,19,24)
       If Local.Avatar.Color Then
	  Strng="Yes"
       Else
	  Strng="No"
       Endif
       Call Scrn(Strng)
       Call ScreenANSI(2,19,36)
       If Share.Installed Then
	  Strng="Yes"
       Else
	  Strng="No"
       Endif
       Call Scrn(Strng)
       Call ScreenANSI(2,19,50)
       If Local.Mode Then
          Strng="<n/a>"
       Else
          If Fossil.Active Then
             Strng="Yes"
             If Fossil.Version=1 Then
                Strng=Strng+": X00"
             Endif
          Else
             Strng="No"
          Endif
       Endif
       Call Scrn(Strng)
       Call ScreenANSI(2,19,60)
       If Port<0 Then
          Strng=" -"
       Else
          Strng=Str$(Port)
          Strng=Strng+" ("+Hex$(Base.Address)+")"
       Endif
       Call Scrn(Strng)
       Call ScreenANSI(2,19,71)
       If Disk.Log Then
          Strng="Yes"
       Else
          Strng="No "
       Endif
       Call Scrn(Strng)
    Case 20
       Call ScreenANSI(4,36,0)
       Call ScreenANSI(4,44,27)
       Call ScreenANSI(2,20,10)
       Strng="Boot Type"
       Call Scrn(Strng)
       Call ScreenANSI(2,20,24)
       Strng="Mouse"
       Call Scrn(Strng)
       Call ScreenANSI(2,20,36)
       Strng="Disk Space"
       Call Scrn(Strng)
       Call ScreenANSI(2,20,50)
       Strng="System"
       Call Scrn(Strng)
       Call ScreenANSI(2,20,61)
       Strng="Node"
       Call Scrn(Strng)
       Call ScreenANSI(2,20,71)
       Strng="Print"
       Call Scrn(Strng)
       Call ScreenANSI(4,37,0)
       Call ScreenANSI(4,44,31)
       Call ScreenANSI(2,21,10)
       If Local.Mode Then
	  Strng="Local"
       Else
          Strng="BBS"
          Strng=Strng+" ("+Ltrim$(Str$(Modem.Baud))+")"
       Endif
       Call Scrn(Strng)
       Call ScreenANSI(2,21,24)
       If Mouse.Present Then
	  Strng="Yes"
       Else
	  Strng="No"
       Endif
       Call Scrn(Strng)
       Call ScreenANSI(2,21,36)
       Call Scrn(Var2$)
       Call ScreenANSI(2,21,50)
       Call System.Type
       Strng=Left$(Strng,10)
       Call Scrn(Strng)
       Call ScreenANSI(2,21,60)
       If Rtrim$(NodeX)=Nul Then
          Strng=" -"
       Else
          Strng=" "+NodeX
       Endif
       Call Scrn(Strng)
       Call ScreenANSI(2,21,71)
       If Print.Log Then
          Strng="Yes"
       Else
          Strng="No "
       Endif
       Call Scrn(Strng)
    Case 22
       Call ScreenANSI(4,36,0)
       Call ScreenANSI(4,44,27)
       Call ScreenANSI(2,22,10)
       Strng="Status"
       Call Scrn(Strng)
       Call ScreenANSI(2,22,24)
       Strng="Free Memory"
       Call Scrn(Strng)
       Call ScreenANSI(2,22,36)
       Strng="Version"
       Call Scrn(Strng)
       Call ScreenANSI(2,22,50)
       Strng="Date"
       Call Scrn(Strng)
       Call ScreenANSI(2,22,61)
       Strng="Time"
       Call Scrn(Strng)
       Call ScreenANSI(2,22,71)
       Strng="Debug"
       Call Scrn(Strng)
       Call ScreenANSI(4,37,0)
       Call ScreenANSI(4,44,31)
       Call ScreenANSI(2,23,24)
       Call Get.Free.Memory
       Call Scrn(Strng)
       Call ScreenANSI(2,23,36)
       Strng="v"+Version$+" r"+Release$
       Call Scrn(Strng)
       Call ScreenANSI(2,23,71)
       If Debug.Mode Then
          Strng="(on)"
       Else
          Strng="(off)"
       Endif
       Call Scrn(Strng)
    End Select
    Call ScreenANSI(4,33,0)
    Call ScreenANSI(4,44,30)
    Call ScreenANSI(2,Temp5,78)
    If Border.Off=0 Then
       If Border.Char=0 Then
          Strng=Chr$(186)
       Else
          Strng="|"
       Endif
       Call Put.Screen(Strng)
    Endif
 Next
 Erase Temp.ArrayS
 Call ScreenANSI(2,24,3)
 If Border.Off=0 Then
    If Border.Char=0 Then
       Strng=Chr$(200)
       Call Scrn(Strng)
       Strng=String$(74,205)
       Call Scrn(Strng)
       Strng=Chr$(188)
       Call Put.Screen(Strng)
    Else
       Strng="+"
       Call Scrn(Strng)
       Strng=String$(74,"-")
       Call Scrn(Strng)
       Strng="+"
       Call Put.Screen(Strng)
    Endif
 Endif
 If Max.Row=25 Then
    If Debug.Mode Then
       Call Display25row
    Endif
 Endif
 Next.Field=Init.Field
 Call Show.Field
 If Mouse.Present Then
    Call Mouse.Function(1,0)
 Endif
 Exit Sub
Get.Config2:
 VarX=0
 Init.Field=1
 Do
    VarX=VarX+1
    If VarX>Options.Lines Then
       Exit Do
    Endif
    Var$=Ltrim$(Rtrim$(Options.Array(VarX)))
    If Ucase$(Var$)="[DNDBBS]" Then
       Do
          VarX=VarX+1
          If VarX>Options.Lines Then
             Exit Do
          Endif
          Var$=Ltrim$(Rtrim$(Options.Array(VarX)))
          If Ucase$(Var$)="[END]" Then
             Exit Do
          Endif
          Var=Instr(Var$,"=")
          If Var Then
             Var2$=Lcase$(Ltrim$(Rtrim$(Left$(Var$,Var-1))))
             Var3$=Lcase$(Ltrim$(Rtrim$(Mid$(Var$,Var+1))))
             If Var2$="init.field" Then
                If (Var3$>="a" And Var3$<="z") Or Var3$="*" Then
                   VarX$=Nul
                   For VarZ=1 To 10
                      VarZ$=Menu1(VarZ)
                      VarZ$=Rtrim$(VarZ$)
                      If VarZ$="" Then
                         VarX$=VarX$+"*"
                      Else
                         VarX$=VarX$+Left$(VarZ$,1)
                      Endif
                   Next
                   VarX$=Lcase$(VarX$)
                   If Instr(VarX$,Var3$) Then
                      Init.Field=Instr(VarX$,Var3$)
                   Endif
                Endif
                If Int(Val(Var3$))>=1 And Int(Val(Var3$))<=10 Then
                   Init.Field=Int(Val(Var3$))
                Endif
             Endif
             If Var2$="border" Then
                Select Case Var3$
                Case "0", "false", "off"
                   Border.Off=True
                End Select
             Endif
             If Var2$="borderchar" Then
                Select Case Var3$
                Case "0", "false", "off"
                   Border.Char=True
                End Select
             Endif
             If Left$(Var2$,4)="alt-" Then
                VarQ$=Mid$(Var2$,5)
                If Len(VarQ$)=1 Then
                   VarQ=Instr("dpwxyz",VarQ$)
                   If VarQ Then
                      Select Case Var3$
                      Case "0", "false", "off"
                         Menu.Array(VarQ)=-1
                      End Select
                   Endif
                Endif
             Endif
          Endif
       Loop
    Endif
 Loop
 VarX$=Ucase$(Environ$("BLIND"))
 If VarX$="ON" Or VarX$="-1" Or VarX$="TRUE" Then
    Border.Off=True
 Endif
 VarX$=Ucase$(Environ$("BLINDCHAR"))
 If VarX$="ON" Or VarX$="-1" Or VarX$="TRUE" Then
    Border.Char=-1
 Endif
 Return
ErrResume3:
 Exit Sub
ErrTrap3:
 Resume ErrResume3
End Sub

Sub Display25row
 If Port<0 Then
    Strng=" -"
 Else
    Strng=Str$(Port)
 Endif
 Strng="Debug : port"+Strng
 Strng=Strng+" : modem baud"+Str$(Modem.Baud)
 Strng=Strng+" : base address 0x"+Hex$(Base.Address)
 If Local.Mode Then
    Strng=Strng+" : Local Mode"
 Else
    If Fossil.Active = 0 Then
       Strng=Strng+" : BBS Mode"
    Else
       If Fossil.Version = 1 Then
          Strng=Strng+" : X00 Mode"
       Endif
       If Fossil.Version = 2 Then
          Strng=Strng+" : Fossil Mode"
       Endif
    Endif
 Endif
 Call ScreenANSI(4,37,0)
 Call ScreenANSI(4,44,31)

 Call ScreenANSI(2,25,3)
 Var$=Space$(77)
 Call Put.Screen(Var$)

 Call ScreenANSI(2,25,3)
 Strng=Left$(Strng,77)
 Call Put.Screen(Strng)
End Sub

Sub Get.Command
 On Local Error Goto Boot.Error
 ' init startup variables
 Gosub Get.Config3
 Local.Mode=False
 Low.Mem.Use=False
 Node=False
 NodeX=Nul
 Call Read.Rows(Max.Row)
 MaxRow.Override=False
 Port.Override=False
 Time.Override=False

 User.PageLength=25
 User.LineLength=80

 Call VideoInt(15,0)
 Video.Page=OutregsX.BX

 ' parse command line
 Command.Line$=Ucase$(Command$)
 Command.Line$=Ltrim$(Rtrim$(Command$))
 Select Case Command.Line$
 Case "/?", "-?", "?"
    Goto Boot.Usage
 End Select

 ' get command line from file
 If Instr(Command.Line$,"/")=0 Then
    If Left$(Command.Line$,1)="@" Then
       If Instr(Command.Line$,"\") Then Goto Boot.Error
       If Instr(Command.Line$,":") Then Goto Boot.Error
       DND.Path=Environ$("DNDBBS")
       If DND.Path<>Nul Then
          If Right$(DND.Path,1)<>"\" Then
             DND.Path=DND.Path+"\"
          Endif
       Endif
       Filename$=Mid$(Command.Line$,2)
       Filename$=Ltrim$(Rtrim$(Filename$))
       If Left$(Filename$,1)=Chr$(34) Then
          Filename$=Mid$(Filename$,2)
          If Right$(Filename$,1)=Chr$(34) Then
             Filename$=Left$(Filename$,Len(Filename$)-1)
          Else
             Goto Boot.Error
          Endif
       Endif
       Filename$=DND.Path+Filename$
       If Dir$(Filename$)<>"" Then
          Close #TempFile1
          Open Filename$ For Input Shared As #TempFile1
          If Eof(TempFile1)=0 Then
             Line Input #TempFile1,Command.Line$
             Command.Line$=Ucase$(Command.Line$)
          Else
             Goto Boot.Error
          Endif
          Close #TempFile1
       Else
          Goto Boot.Error
       Endif
    Endif
 Endif

 ' remove spaces from command line
 Var1=Instr(Command.Line$," ")
 While Var1
    Command.Line$=Left$(Command.Line$,Var1-1)+Mid$(Command.Line$,Var1+1)
    Var1=Instr(Command.Line$," ")
 Wend

 ' login name override
 Var1=Instr(Command.Line$,"/N:"+Chr$(34))
 If Var1 Then
    Var2=Instr(Var1+4,Command.Line$,Chr$(34))
    If Var2 Then
       Temp$=Mid$(Command.Line$,Var1+4,Var2-Var1-4)
       Command.Line$=Left$(Command.Line$,Var1-1)+Mid$(Command.Line$,Var2+1)
       If Temp$=Nul Then
          Goto Boot.Usage
       Endif
       Bypass.CodeName=Temp$
       Bypass.Login=True
    Endif
 Endif

 ' time cold boot
 Var1=Instr(Command.Line$,"/S:"+Chr$(34))
 If Var1 Then
    Var2=Instr(Var1+4,Command.Line$,Chr$(34))
    If Var2 Then
       Temp$=Mid$(Command.Line$,Var1+4,Var2-Var1-4)
       Command.Line$=Left$(Command.Line$,Var1-1)+Mid$(Command.Line$,Var2+1)
       If Temp$=Nul Then
          Goto Boot.Usage
       Endif
       MidnightX$=Temp$
    Endif
 Endif

 ' modem base address
 Var1=Instr(Command.Line$,"/A:"+Chr$(34))
 If Var1 Then
    Var2=Instr(Var1+4,Command.Line$,Chr$(34))
    If Var2 Then
       Temp$=Mid$(Command.Line$,Var1+4,Var2-Var1-4)
       Command.Line$=Left$(Command.Line$,Var1-1)+Mid$(Command.Line$,Var2+1)
       If Temp$=Nul Then
          Goto Boot.Usage
       Endif
       VarX=ValidHex(Temp$)
       If VarX=0 Then
          Goto Boot.Usage
       Endif
       Temp$="&H"+Temp$
       If Int(Val(Temp$))>=1 And Int(Val(Temp$))<=MaxInt Then
          Base.Address=Int(Val(Temp$))
       Else
          Goto Boot.Usage
       Endif
    Endif
 Endif

 ' override os
 Out2="/OSX"
 Gosub Get.Switch
 If Var1 Then
    DOS.Major=30
    DOS.Minor=0
 Endif

 ' override os
 Out2="/OS2"
 Gosub Get.Switch
 If Var1 Then
    OS2.Detected=True
    DOS.Major=10
    DOS.Minor=0
 Endif

 ' override os
 Out2="/OS"
 Gosub Get.Switch
 If Var1 Then
    Windows.Detected=-1
    Win.Major=5
    Win.Minor=0
 Endif

 ' detect remaining switches
 Out2="/BY" ' bypass
 Gosub Get.Switch
 Bypass.Screen=Var1
 Out2="/DO" ' door
 Gosub Get.Switch
 BBS.Mode=Var1
 Out2="/TN" ' telnet
 Gosub Get.Switch
 If Var1 Then
    BBS.Mode=-2
 Endif
 Out2="/LC"
 Gosub Get.Switch
 Local.Mode=Var1
 If Modem.Baud=0 Then
    Modem.Baud=9600!
 Endif
 If Base.Address=0 Then
    Base.Address=&H3F8
 Endif
 ' debug switches
 Out2="/D:1"
 Gosub Get.Switch
 If Var1 Then
    Bypass.Splash=Bypass.Splash Or 1
 Endif
 Out2="/D:2"
 Gosub Get.Switch
 If Var1 Then
    Bypass.Splash=Bypass.Splash Or 2
 Endif
 Out2="/D:3"
 Gosub Get.Switch
 If Var1 Then
    Debug.Pack=True
 Endif
 Out2="/D:4"
 Gosub Get.Switch
 If Var1 Then
    Low.Mem.Use=True
 Endif
 Out2="/D:5"
 Gosub Get.Switch
 If Var1 Then
    Disable.Share=True
 Endif
 Out2="/D:6"
 Gosub Get.Switch
 If Var1 Then
    Debug.Mode=True
 Endif

 ' fossil version override switches
 Out2="/F:0" ' off
 Gosub Get.Switch
 If Var1 Then
    Fossil.Mode=-1
 Endif
 Out2="/F:1" ' v1
 Gosub Get.Switch
 If Var1 Then
    Fossil.Mode=1
 Endif
 Out2="/F:2" ' v2
 Gosub Get.Switch
 If Var1 Then
    Fossil.Mode=2
 Endif

 ' max rows override
 Var1=Instr(Command.Line$,"/M:")
 If Var1 Then
    Temp$=Left$(Command.Line$,Var1-1)
    Command.Line$=Mid$(Command.Line$,Var1+3)
    Gosub Get.Numeric
    Command.Line$=Temp$+Command.Line$
    Temp=Int(Val(TempA$))
    Select Case Temp
    Case 25, 43, 50
       MaxRow.Override=Temp
    Case Else
       Goto Boot.Usage
    End Select
 Endif
 If MaxRow.Override=False Then
    Call Read.Rows(Max.Row)
 Else
    Max.Row=MaxRow.Override
 Endif

 ' modem base address
 Var1=Instr(Command.Line$,"/A:")
 If Var1 Then
    Temp$=Left$(Command.Line$,Var1-1)
    Command.Line$=Mid$(Command.Line$,Var1+3)
    Gosub Get.Numeric3
    Command.Line$=Temp$+Command.Line$
    Temp=Int(Val("&H"+TempA$))
    If Temp>=1 And Temp<=MaxInt Then
       Base.Address=Temp
    Else
       Goto Boot.Usage
    Endif
 Endif

 ' modem base address
 Var1=Instr(Command.Line$,"/A")
 If Var1 Then
    Temp$=Left$(Command.Line$,Var1-1)
    Command.Line$=Mid$(Command.Line$,Var1+2)
    Gosub Get.Numeric3
    Command.Line$=Temp$+Command.Line$
    Temp=Int(Val("&H"+TempA$))
    If Temp>=1 And Temp<=MaxInt Then
       Base.Address=Temp
    Else
       Goto Boot.Usage
    Endif
 Endif

 ' port number override
 Var1=Instr(Command.Line$,"/P:")
 If Var1 Then
    Temp$=Left$(Command.Line$,Var1-1)
    Command.Line$=Mid$(Command.Line$,Var1+3)
    Gosub Get.Numeric
    Command.Line$=Temp$+Command.Line$
    Temp=Int(Val(TempA$))
    If Temp>=1 And Temp<=MaxPorts Then
       Port.Override=Temp
    Endif
    If Port.Override=False Then
       Goto Boot.Usage
    Endif
 Endif

 ' port number override
 Var1=Instr(Command.Line$,"/P")
 If Var1 Then
    Temp$=Left$(Command.Line$,Var1-1)
    Command.Line$=Mid$(Command.Line$,Var1+2)
    Gosub Get.Numeric
    Command.Line$=Temp$+Command.Line$
    Temp=Int(Val(TempA$))
    If Temp>=1 And Temp<=MaxPorts Then
       Port.Override=Temp
    Endif
    If Port.Override=False Then
       Goto Boot.Usage
    Endif
 Endif

 ' port baud override
 Var1=Instr(Command.Line$,"/B:")
 If Var1 Then
    Temp$=Left$(Command.Line$,Var1-1)
    Command.Line$=Mid$(Command.Line$,Var1+3)
    Gosub Get.Numeric2
    Command.Line$=Temp$+Command.Line$
    Temp!=Csng(Int(Val(TempA$)))
    Call Set.Baud(Temp!)
    If Modem.Baud=False Then
       Goto Boot.Error2
    Endif
 Endif

 ' port baud override
 Var1=Instr(Command.Line$,"/B")
 If Var1 Then
    Temp$=Left$(Command.Line$,Var1-1)
    Command.Line$=Mid$(Command.Line$,Var1+2)
    Gosub Get.Numeric2
    Command.Line$=Temp$+Command.Line$
    Temp!=Csng(Int(Val(TempA$)))
    Call Set.Baud(Temp!)
    If Modem.Baud=False Then
       Goto Boot.Error2
    Endif
 Endif

 ' cold reboot switch
 VarQ=0
 Out2="/R:1"
 Gosub Get.Switch
 If Var1 Then
    VarQ=1
 Endif

 ' warm reboot switch
 Out2="/R:2"
 Gosub Get.Switch
 If Var1 Then
    VarQ=2
 Endif

 ' midnight reboot cold switch
 Out2="/R:3"
 Gosub Get.Switch
 If Var1 Then
    Midnight.Reboot=True
 Endif

 ' midnight reboot warm switch
 Out2="/R:4"
 Gosub Get.Switch
 If Var1 Then
    Midnight.Reboot=-2
 Endif

 ' ram drive letter
 Var1=Instr(Command.Line$,"/R:")
 If Var1 Then
    TempA$=Mid$(Command.Line$,Var1+3,1)
    Command.Line$=Left$(Command.Line$,Var1-1)+Mid$(Command.Line$,Var1+4)
    Temp=Asc(TempA$)
    If Temp>=65 And Temp<=90 Then
       Drive.Override=Temp
    Endif
    If Drive.Override=False Then
       Goto Boot.Usage
    Endif
 Endif

 ' time override
 Var1=Instr(Command.Line$,"/T:")
 If Var1 Then
    Temp$=Left$(Command.Line$,Var1-1)
    Command.Line$=Mid$(Command.Line$,Var1+3)
    Gosub Get.Numeric
    Command.Line$=Temp$+Command.Line$
    Temp=Int(Val(TempA$))
    If Temp>=1 And Temp<=MaxInt Then
       Time.Override=Temp
    Endif
    If Time.Override=False Then
       Goto Boot.Usage
    Endif
 Endif

 ' optional node switch
 If Left$(Command.Line$,1)="/" Then
    Select Case Len(Command.Line$)
    Case 1 ' no node
       Node=0
       NodeX=""
       Command.Line$=Nul
    Case 2 ' single char
       Command.Line$=Mid$(Command.Line$,2)
       Select Case Ucase$(Command.Line$)
       Case "0" To "9" ' 1-10
          Node=Val(Command.Line$)+1
          NodeX=Command.Line$
          Command.Line$=Nul
       Case "A" To "Z" ' 11-36
          Node=Asc(Ucase$(Command.Line$))-54
          NodeX=Ucase$(Command.Line$)
          Command.Line$=Nul
       End Select
    Case 3 ' double char
       Command.Line$=Mid$(Command.Line$,2)
       VarX=Int(Val(Command.Line$))
       If VarX>=10 And VarX<=99 Then
          Node=VarX+27 ' 37-126
          NodeX=Mid$(Str$(VarX),2) ' 10-99
          Command.Line$=Nul
       Endif
    End Select
 Endif

 ' recheck remaining command line
 If Command.Line$<>Nul Then
    Goto Boot.Usage
 Endif

 If VarQ=1 Then
    ' cold boot
    Out2="Now exiting the Dndbbs Adventure System.."
    Out3="Reason: Command line cold boot. "+Fclock$
    Strng1="Terminated program."
    Strng2="Reason: Command line cold boot."
    Strng3=Nul
    Call Write.Logfile(True)
    Close #TempFile1
    DEF SEG = &HFFFF
    CALL Absolute(0)
    DEF SEG
    Call Terminate.Program
    End 0
 Endif
 If VarQ=2 Then
    ' warm boot
    Out2="Now exiting the Dndbbs Adventure System.."
    Out3="Reason: Command line warm boot. "+Fclock$
    Strng1="Terminated program."
    Strng2="Reason: Command line warm boot."
    Strng3=Nul
    Call Write.Logfile(True)
    Close #TempFile1
    OUT &H64, &HF0
    Call Terminate.Program
    End 0
 Endif

 ' check local mode override
 If Local.Mode Then
    MessWorkRecord1.PortNumber=0
    VarX2=Node+1
    Call Write.Message.Record(MessWorkFile1,VarX2)
 Endif

 ' store variables and exit
 NodeX=Rtrim$(NodeX)
 Width 80,Max.Row
 Locate Max.Row,1,1
 Exit Sub

' scan for a switch in command line
Get.Switch:
 Var1=False
 VarX=Instr(Command.Line$,Out2)
 If VarX Then
    Var1=True
    Command.Line$=Left$(Command.Line$,VarX-1)+Mid$(Command.Line$,VarX+Len(Out2))
 Endif
 Return

' scan for a value in command line
Get.Numeric:
 TempA$=Nul
 Do
    TempY$=Left$(Command.Line$,1)
    If TempY$>="0" And TempY$<="9" Then
       TempA$=TempA$+TempY$
       Command.Line$=Mid$(Command.Line$,2)
    Else
       Exit Do
    Endif
 Loop
 Return

' scan for a value in command line
'  including a . character..
Get.Numeric2:
 TempA$=Nul
 Do
    TempY$=Left$(Command.Line$,1)
    If (TempY$>="0" And TempY$<="9") Or TempY$="." Then
       TempA$=TempA$+TempY$
       Command.Line$=Mid$(Command.Line$,2)
    Else
       Exit Do
    Endif
 Loop
 Return

' scan for a hex value in command line
Get.Numeric3:
 TempA$=Nul
 Do
    TempY$=Left$(Command.Line$,1)
    Select Case TempY$
    Case "0" To "9", "A" To "F"
       TempA$=TempA$+TempY$
       Command.Line$=Mid$(Command.Line$,2)
    Case Else
       Exit Do
    End Select
 Loop
 Return

' display boot usage for command line
Boot.Usage:
 Call Read.Rows(Max.Row)
 Locate Max.Row-1,1,1

 ANSIPrefixChar="{"
 Local.Mode=True
 Port=True

 DND.Path=Environ$("DNDBBS")
 If DND.Path<>Nul Then
    If Right$(DND.Path,1)<>"\" Then
       DND.Path=DND.Path+"\"
    Endif
 Endif

 Filename=DND.Path+"bootkey1.txt"
 If Dir$(FileName)<>Nul Then
    Call Out.File(FileName)
 Endif

 If Instr(Command$,"/HELP") Then
    Filename=DND.Path+"bootkey2.txt"
    If Dir$(FileName)<>Nul Then
       Call Out.File(FileName)
    Endif
 Endif
 Call Exit.To.DOS
 Color 7,0
 End 0

' trap and display any error processing command line
Boot.Error:
 Call Read.Rows(Max.Row)
 Locate Max.Row-1,1,1
 Color 14,0
 Print "Dndbbs v"+Version$+" r"+Release$+" boot error."
 Color 15,0
 Print " Error reading the command line. Check the command line"
 Print " and make any changes specifying the command options."
 If Instr(Command.Line$,"/D:6") Then Debug.Mode=-1
 If Debug.Mode Then
    Print "Command line= "+Chr$(34)+Command$+Chr$(34)
 Endif
 Strng1="Terminated program."
 Strng2="Reason: Command line boot error."
 Strng3=Nul
 Call Write.Logfile(True)
 Port=True
 Call Exit.To.DOS
 Color 7,0
 End 0
' trap and display any error processing command line
Boot.Error2:
 Call Read.Rows(Max.Row)
 Locate Max.Row-1,1,1
 Color 14,0
 Print "Dndbbs v"+Version$+" r"+Release$+" boot error."
 Color 15,0
 Print " Baud rate can only be:"
 Print " 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200"
 Strng1="Terminated program."
 Strng2="Reason: Command line boot error."
 Strng3=Nul
 Call Write.Logfile(True)
 Port=True
 Call Exit.To.DOS
 Color 7,0
 End 0
Get.Config3:
 Default.Baud!=9600!
 VarX=0
 Do
    VarX=VarX+1
    If VarX>Options.Lines Then
       Exit Do
    Endif
    Var$=Ltrim$(Rtrim$(Options.Array(VarX)))
    If Ucase$(Var$)="[MODEM]" Then
       Do
          VarX=VarX+1
          If VarX>Options.Lines Then
             Return
          Endif
          Var$=Ltrim$(Rtrim$(Options.Array(VarX)))
          If Ucase$(Var$)="[END]" Then
             Return
          Endif
          Var=Instr(Var$,"=")
          If Var Then
             Var2$=Ltrim$(Rtrim$(Left$(Var$,Var-1)))
             Var3$=Ltrim$(Rtrim$(Mid$(Var$,Var+1)))
             Select Case Lcase$(Var2$)
             Case "ignore.baud"
                Default.Baud!=9600! ' hardwired/could be changed
                Return
             Case "default.baud"
                VarQ!=Csng(Int(Val(Var3$)))
                Select Case VarQ!
                Case 300!, 600!, 1200!, 2400!, 4800!, 9600!, 19200!, 38400!, 57600!, 115200!
                   Default.Baud!=VarQ!
                Case Else ' default baud default!
                   Default.Baud!=9600!
                End Select
             End Select
          Endif
       Loop
    Endif
 Loop
 Return
End Sub

' set the default modem baud rate
Sub Set.Baud(Temp!)
 If Temp!>=0! And Temp!<=230400! Then
    Select Case Temp!
    Case 50!, 75!, 110!, 134.5!, 150!, 450!
       Modem.Baud=300!
    Case 7200!
       Modem.Baud=4800!
    Case 12000!, 14400!, 16800!
       Modem.Baud!=9600!
    Case 21600!, 24000!, 26400!, 28800!, 31200!, 33600!
       Modem.Baud=19200!
    Case 64000!, 78600!
       Modem.Baud=57600!
    Case 230400!
       Modem.Baud=115200!
    Case 300!, 600!, 1200!, 2400!, 4800!, 9600!, 19200!, 38400!, 57600!, 115200!
       Modem.Baud=Temp!
    Case Else
       Modem.Baud=Default.Baud!
    End Select
 Endif
 End Sub

Sub Read.Door
 On Local Error Goto Door.Error
 If Rtrim$(Door.Name)=Nul Then
    VarX=-1
 Endif
 BBS.Name=Nul
 Door.Name=Nul
 Door.Node=Config3(83)
 Door.Time=180! ' default time
 If BBS.Mode=False Then
    Exit Sub
 Endif
 If BBS.Mode=-2 Then ' telnet mode
    Gosub Get.Config9
    Exit Sub
 Endif
 VarX$=Rtrim$(Door.Node)
 ' RBBS v17.4 node: 1-9,0,A-Z (can be nul)
 If Len(VarX$)<=1 Then ' single-letter
    Var$="DORINFO"+VarX$+".DEF"
    Filename=Config3(84)+Var$
    Var2$=Filename
    If Dir$(FileName)=Var$ Then
       Goto Read.Door.File
    Endif
 Endif
 ' RBBS v17.5 node: 1-9,0,A-Z,10-99 (can be nul)
 Var$="DINF"+VarX$+".DEF" ' dual-letter
 Filename=Config3(84)+Var$
 Var3$=Filename
 If Dir$(FileName)=Var$ Then
    Goto Read.Door.File
 Endif
 Goto Door.Error
' fixed 08/30/2020
Read.Door.File:
 Close #TempFile1
 Open FileName For Input Shared As #TempFile1
 For Var=1 To 13
    If Var=13 Then ' old rbbs file
       If Eof(TempFile1) Then
          Exit For
       Endif
    Endif
    Line Input #TempFile1,Strng
    Strng=Rtrim$(Strng)
    Select Case Var
    Case 1
       ' store BBS name.
       If Strng=Nul Then
          BBS.Name="<n/a>"
       Else
          BBS.Name=Strng
       Endif
    Case 4
       ' store modem comm port number.
       Port=Int(Val(Mid$(Strng,4)))
       ' comm port 0 is sysop.
       If Port=0 Then
          Local.Mode=True
       Endif
       ' modem port starts at 0.
       Port=Port-1
    Case 5
       ' store modem speed.
       Strng=Ltrim$(Strng)
       ' fixed variable collision here:
       VarZ=Instr(Strng," ")
       If VarZ Then
          Temp$=Left$(Strng,VarZ-1)
       Else
          Temp$=Strng
       Endif
       Modem.Baud=Csng(Int(Val(Temp$)))
       Modem.Return=Mid$(Str$(Modem.Baud),2)
    ' Note: First name 'Sysop' does not imply local mode.
    Case 7
       ' store first part of user name.
       Door.Name=Strng
    Case 8
       ' store second part of user name.
       If Len(Strng) Then
          Door.Name=Door.Name+" "+Strng
       Endif
    Case 10
       If Int(Val(Strng))=2 Then
          Remote.ANSI.Color=True
       Endif
    Case 12
       ' store remaining bbs door time.
       Door.Time=Val(Strng)*60!
    Case 13
       ' fossil
       If Val(Strng) Then
          Fossil.Active=True
          Fossil.Version=2
       Endif
    End Select
 Next
 ' check fossil override
 Select Case Fossil.Mode
 Case -1 ' off
    Fossil.Active=False
    Fossil.Version=0
 Case 1 ' v1 x00
    Fossil.Active=True
    Fossil.Version=1
 Case 2 ' v2 fossil
    Fossil.Active=True
    Fossil.Version=2
 End Select
 If VarX Then
    Strng1="RBBS door information file loaded."
    Strng2=Nul:Strng3=Nul
    Call Write.Logfile(False)
 Endif
 Exit Sub
Door.Error:
 Out2=Nul
 If Len(Var2$) Then
    Out2=Out2+Var2$
    If Len(Var3$) Then
       Out2=Out2+" -- "
    Endif
 Endif
 If Len(Var3$) Then
    Out2=Out2+Var3$
 Endif
 If Len(Var2$)=0 And Len(Var3$)=0 Then
    If Rtrim$(Door.Node)=Nul Then
       Out2=Out2+"Node -"
    Else
       Out2=Out2+"Node "+Door.Node
    Endif
 Endif
 Out3="RBBS door information file not found, or invalid."
 Strng1=Out3
 Strng2=Nul:Strng3=Nul
 Call Write.Logfile(False)
 Strng2=" reading door file:"
 Call Terminal.Error
 End 0
Get.Config9:
 ' default door settings
 BBS.Name="DNDBBS"
 Door.Name="JOE UZERNAME"
 Door.Time=3600!
 VarX=0
 Do
    VarX=VarX+1
    If VarX>Options.Lines Then
       Exit Do
    Endif
    Var$=Ltrim$(Rtrim$(Options.Array(VarX)))
    If Ucase$(Var$)="[TELNET]" Then
       Do
          VarX=VarX+1
          If VarX>Options.Lines Then
             Return
          Endif
          Var$=Ltrim$(Rtrim$(Options.Array(VarX)))
          If Ucase$(Var$)="[END]" Then
             Return
          Endif
          Var=Instr(Var$,"=")
          If Var Then
             Var2$=Ltrim$(Rtrim$(Left$(Var$,Var-1)))
             Var3$=Ltrim$(Rtrim$(Mid$(Var$,Var+1)))
             Select Case Lcase$(Var2$)
             Case "bbs.name"
                BBS.Name=Var3$
             Case "door.name"
                Door.Name=Ucase$(Var3$)
             Case "door.time"
                Door.Time=Int(Val(Var3$))*60!
             Case "ansi.color"
                If Var3$="-1" Then
                   Remote.ANSI.Color=True
                Endif
             Case "fossil.mode"
                If Var3$="-1" Then
                   Fossil.Active=True
                   Fossil.Version=2
                Endif
                If Var3$="-2" Then ' x00
                   Fossil.Active=True
                   Fossil.Version=1
                Endif
             End Select
          Endif
       Loop
    Endif
 Loop
 Return
End Sub

Sub Open.Modem
 On Local Error Goto ErrTrap4
 Static Ansi.Blank As Integer
 Gosub Get.Config5
 Ansi.Blank=False
 Connect=False
 Logged.In=False
 Lost.Carrier=False
 Locate Max.Row-1,1,1
 If BBS.Mode Then
    Color 15,0
    Lost.Carrier=False
    Timeon=Timeit!
    Time.Left=Door.Time
    Two.Minutes.Left=False
    Security.Guard=True
    If Local.Mode Then
       Print "Local DOOR Mode: Door node ";
       If Rtrim$(Door.Node)=Nul Then
          Print "-."
       Else
          Print Rtrim$(Door.Node)+"."
       Endif
       Exit Sub
    Endif
    Out2=Nul
    Out3=Nul
    Call Init.Fossil.Port
    Call Check.Modem(Var)
    If Var Then
       OutZ="no modem"
       Goto Quit.Door
    Endif
    If (OutregsX.AX And &H80)=0 Then
       OutZ="carrier lost"
       Goto Quit.Door
    Endif
    For VarQ=1 To MaxModemBauds
       Strng=Rtrim$(Modem.String(VarQ))
       If Len(Strng) Then
          If Modem.Baud=Modem.Connect(VarQ) Then
             If Modem.Allow(VarQ)=False Then
                Strng="Sorry,"+Str$(Modem.Baud)+" baud access not allowed!"
                Call IO.O
                OutZ="baud rate"
                Goto Quit.Door
             Endif
          Endif
       Endif
    Next
    Strng="DOOR Mode: Door node "
    If Rtrim$(Door.Node)=Nul Then
       Strng=Strng+"-"
    Else
       Strng=Strng+Rtrim$(Door.Node)
    Endif
    If Port=-1 Then
       Strng=Strng+": Port -"
    Else
       Strng=Strng+": Port"+Str$(Port)+", "
       Strng=Strng+": Connect"+Str$(Modem.Baud)
    Endif
    Call IO.O
    Exit Sub
 Endif
 If Bypass.Screen Or Bypass.Login Then
    Timeon=Timeit!
    Time.Left=3600!
    Two.Minutes.Left=False
    Local.Mode=True
    Exit Sub
 Endif
 Call Init.Comm.Driver
 Recycle=True
 Wait.State!=Timeit!
 Do While Recycle
    Ansi.Blank=False
    Blank.Menu=True
    Blank.Screen=False
    Menu.Timer=SFalse
    ScreenTimer=SFalse
    Connect=False
    Time.Out!=SFalse
    Ring.Count=0
    Pack.Time!=Timeit!
    Pack.Time2!=Timeit!
    VarQ=False
    Call Opening.Screen
    Call Recycle.Modem
    Wait.State!=Timeit!
    Out2=Nul
    Do Until Connect
       ' start modem loop
       If Local.Mode=False Then
          If Time.Elapsed(Wait.State!,1!) Then
             Wait.State!=Timeit!

             ' get line status
             Call Check.Modem(Var)

             ' carrier bit
             If (OutregsX.AX And &H80)=&H80 Then
                Connect=True
             Endif

             ' check ring bit
             If (OutregsX.AX And &H40)=&H40 Then
                If Ring.Count>Max.Ring.Count Then
                   VarQ=False
                   Out2=Nul
                   Time.Out!=SFalse
                   Ring.Count=0
                   Strng="No Carrier"
                   If Rtrim$(ANSIPrefixChar)<>"" Then
                      Strng=ANSIPrefixChar+"FB"+Strng ' cyan
                   Endif
                   Call Modem.Status
                   Call Playwav(1)
                   Call Recycle.Modem
                Endif
             Endif
          Endif
          Call Read.Modem
          If Instr(Out2,"RING") Then
             Ring.Count=Ring.Count+1
             Strng="Ring"+Str$(Ring.Count)
             If Rtrim$(ANSIPrefixChar)<>"" Then
                Strng=ANSIPrefixChar+"FA"+Strng ' green
             Endif
             Call Modem.Status
             Call Playwav(2)
             Time.Out!=Timeit!
             Out2=Nul
             If Instr(Config3(39),"S0=0") Then
                Strng=Config3(40)+Chr$(13) ' send ATA
                Call Send.Modem(Strng)
                Strng="Auto Answer"
                If Rtrim$(ANSIPrefixChar)<>"" Then
                   Strng=ANSIPrefixChar+"FB"+Strng ' cyan
                Endif
                Call Modem.Status
             Endif
          Endif
          If Instr(Out2,"NO CARRIER") Then
             VarQ=False
             Out2=Nul
             Time.Out!=SFalse
             Ring.Count=0
             Strng="No Carrier"
             If Rtrim$(ANSIPrefixChar)<>"" Then
                Strng=ANSIPrefixChar+"FB"+Strng ' cyan
             Endif
             Call Modem.Status
             Call playwav(1)
             Call Recycle.Modem
          Endif
	  If Time.Out! Then
	     If Time.Elapsed(Time.Out!,Csng(Config2(60))) Then
                VarQ=False
                Out2=Nul
                Time.Out!=SFalse
                Ring.Count=0
                Strng="No Carrier"
                If Rtrim$(ANSIPrefixChar)<>"" Then
                   Strng=ANSIPrefixChar+"FB"+Strng ' cyan
                Endif
                Call Modem.Status
                Call playwav(1)
                Call Recycle.Modem
	     Endif
	  Endif
       Endif
       If Time.Elapsed(Pack.Time2!,60!) Then
          If Len(MidnightX$) Then
             t1$=Format$(Now,"hh:mm")
             If t1$ = MidnightX$ Then
                Gosub Set.Usage.File
                Out2="Now exiting the Dndbbs Adventure System.."
                Out3="Reason: Specified cold boot. "+Fclock$
                Strng1="Terminated program."
                Strng2="Reason: Specified cold boot."
                Strng3=Nul
                Call Write.Logfile(False)
                ' cold boot
                DEF SEG = &HFFFF
                CALL Absolute(0)
                DEF SEG
                Call Terminate.Program
                End 0
             Endif
          Endif
          Pack.Time2!=Timeit!
          Close #TempFile1
          FileName=Usage.FileName
          Open FileName For Random Shared As #TempFile1 Len=26
          Field #TempFile1,10 As D$,8 As T$,8 As X$
          Get #TempFile1,3
          ' should reboot every midnight
          If D$<>DateS$ Then
             ' check midnight cold reboot
             If Midnight.Reboot=True Then
                Gosub Set.Usage.File
                Out2="Now exiting the Dndbbs Adventure System.."
                Out3="Reason: Midnight cold boot. "+Fclock$
                Strng1="Terminated program."
                Strng2="Reason: Midnight cold boot."
                Strng3=Nul
                Call Write.Logfile(False)
                ' cold boot
                DEF SEG = &HFFFF
                CALL Absolute(0)
                DEF SEG
                Call Terminate.Program
                End 0
             Endif
             ' check midnight warm reboot
             If Midnight.Reboot=-2 Then
                Gosub Set.Usage.File
                Out2="Now exiting the Dndbbs Adventure System.."
                Out3="Reason: Midnight warm boot. "+Fclock$
                Strng1="Terminated program."
                Strng2="Reason: Midnight warm boot."
                Strng3=Nul
                Call Write.Logfile(False)
                ' warm boot
                OUT &H64, &HF0
                Call Terminate.Program
                End 0
             Endif
          Endif
       Endif
       If Rtrim$(NodeX)=Nul Then
          If Time.Elapsed(Pack.Time!,60!) Then
             Pack.Time!=Timeit!
             If Debug.Pack=False Then
                Close #TempFile1
                FileName=Usage.FileName
                Open FileName For Random Shared As #TempFile1 Len=26
                Field #TempFile1,10 As D$,8 As T$,8 As X$
                Get #TempFile1,3
                ' should pack every midnight
                If D$<>DateS$ Then
                   Gosub DndPack
                Endif
             Endif
             ' pack at specified date/time intervals
             If Debug.Pack2 Then
                Filename=Dnd.Path+"dndpack.dat"
                Close #TempFile1
                If Dir$(Filename)<>"" Then
                   Open Filename For Input As #TempFile1
                   Do While Eof(TempFile1)=0
                      Line Input #TempFile1, Var$
                      Var$=Ltrim$(Rtrim$(Var$))
                      If Left$(Var$,1)=";" Then
                         Eat$=Nul
                      Else
                         If Len(Var$)=5 Then ' hh:mm
                            ' minutes past midnight
                            t1$ = Format$(Now, "hh:mm")
                            If Var$ = t1$ Then
                               Gosub DndPack
                               Exit Do
                            Endif
                         Else
                            If Len(Var$)=16 Then ' mm-dd-yyyy hh:mm
                               VarQ1$=Left$(Var$,10) ' date
                               VarQ2$=Mid$(Var$,12) ' time
                               If ValidDate(VarQ1$) Then
                                  d1$=Format$(Now,"mm-dd-yyyy")
                                  t1$=Format$(Now,"hh:mm")
                                  If d1$=VarQ1$ And t1$=VarQ2$ Then
                                     Gosub DndPack
                                     Exit Do
                                  Endif
                               Endif
                            Else
                               ' mm-dd-yyyy to mm-dd-yyyy hh:mm
                               If Len(Var$)=30 Then
                                  Var$=Lcase$(Var$)
                                  If Mid$(Var$,11,4)=" to " Then
                                     StartDate$=Left$(Var$,10)
                                     EndDate$=Mid$(Var$,15,10)
                                     VarQ2$=Mid$(Var$,26,5)
                                     d1$=Format$(Now,"mm-dd-yyyy")
                                     If ValidDate(StartDate$) Then
                                        If ValidDate(EndDate$) Then
                                           If ValidDate(d1$) Then
                                              S1#=DateValue(StartDate$)
                                              S2#=DateValue(EndDate$)
                                              S3#=DateValue(d1$) ' today
                                              ' compare date range.
                                              If S3#>=S1# And S3#<=S2# Then
                                                 t1$=Format$(Now,"hh:mm")
                                                 If t1$=VarQ2$ Then
                                                    Gosub DndPack
                                                    Exit Do
                                                 Endif
                                              Endif
                                           Endif
                                        Endif
                                     Endif
                                  Endif
                               Endif
                            Endif
                         Endif
                      Endif
                   Loop
                Endif
             Endif
          Endif
       Endif
       If Time.Elapsed(Time.Temp!,1!) Then
          Call Display.Time
          VarX2=Node+1
          Call Read.Message.Record(MessWorkFile1,VarX2)
          If MessWorkRecord1.ActiveNode=False Then
             If MessWorkRecord1.SuspendNode=False Then
                Call Zero.Node(0)
                Call Clear.Screen
                Out2="Now aborting the Dndbbs adventure system."
                Out3="Reason: Inactive node. "+Fclock$
                Strng1="Terminated program."
                Strng2="Reason: Inactive node."
                Strng3=Nul
                Call Write.Logfile(False)
                Call Terminate.Program
                End 0
             Endif
          Endif
          Call Read.Message.Record(MessWorkFile1,VarX2)
          If MessWorkRecord1.SuspendNode=True Then ' suspend mode on
             MessWorkRecord1.ActiveNode=False
             Call Write.Message.Record(MessWorkFile1,VarX2)
             Call Close.Files
             Call Close.Temp
             Close #MessWorkFile3
             Close #MessWorkFile4
             Close #MessWorkFile5
             Close #MessWorkFile6
             Strng="Suspend"
             If Rtrim$(ANSIPrefixChar)<>"" Then
                Strng=ANSIPrefixChar+"FB"+Strng ' cyan
             Endif
	     Call Modem.Status
          Endif
          If MessWorkRecord1.SuspendNode=1 Then ' suspend mode off
             MessWorkRecord1.ActiveNode=True
             MessWorkRecord1.SuspendNode=False
             Call Write.Message.Record(MessWorkFile1,VarX2)
             Call Open.Files
             Call Open.Session.Files
	     If Local.Mode Then
                Strng="Waiting"
	     Else
		Strng="Call Waiting"
	     Endif
	     Call Modem.Status
          Endif
          Time.Temp!=Timeit!
	  If Blank.Menu=False Then
             Menu.Timer=Menu.Timer+1!
             VarX=False
             If Menu.Timer>=Display.Menu.Timer! Then
                VarX=True
             Else
                If Config2(47)>False Then
                   If Menu.Timer>=Config2(47) Then
                      VarX=True
                   Endif
                Endif
             Endif
             If VarX Then
                Menu.Timer=SFalse
                Blank.Menu=True
                Call ScreenANSI(4,33,0)
                Call ScreenANSI(4,44,30)
                Call Display.Field
                Selection=1
             Endif
          Endif
          If Blank.Screen=False Then
             ScreenTimer=ScreenTimer+1!
             If ScreenTimer>Config2(47) Then
                ScreenTimer=SFalse
                If Config2(47)>False Then
		   Call Clear.Screen
                   Ansi.Blank=False
		   Blank.Menu=True
		   Blank.Screen=True
                   Keyboard.Timer!=Timeit!
		   Keyboard.Count=10
		   Keyboard.Flag=False
		   Shift.State=False
		   Selection=1
		Endif
	     Endif
          Endif
       Endif
       If Blank.Screen Then
          If Time.Elapsed(Keyboard.Timer!,1!) Then
             Keyboard.Timer!=Timeit!
	     If Keyboard.Count=False Then
		If Keyboard.Flag<22 Then
		   Keyboard.Flag=Keyboard.Flag+1
		   If Int(Keyboard.Flag/2)=Keyboard.Flag/2 Then
		      Key.State=False
		   Else
		      Key.State=112
		   Endif
                   Gosub ShiftKey
                   If Ansi.Blank<>True Then
                      Ansi.Blank=4
                      Var$=Mid$(Str$(Ansi.Blank),2)
                      Call Shell.Program("ANSI.EXE",Var$)
                      Locate ,,0
                      Ansi.Blank=True
                   Endif
                Else
                   If Keyboard.Flag=22 Then
                      Keyboard.Flag=23
                      Call Clear.Screen
                      Locate ,,0
                   Endif
		Endif
	     Endif
             If Keyboard.Count>False Then
		Select Case Shift.State
		Case 0
                   Key.State=False
		Case 1
		   Key.State=32
		Case 2
		   Key.State=64
		Case 3
		   Key.State=96
		Case 4
		   Key.State=16
		Case 5
		   Key.State=48
		Case 6
		   Key.State=80
		Case 7
		   Key.State=112
		End Select
                Gosub ShiftKey
		Shift.State=Shift.State+1
		If Shift.State=8 Then
		   Shift.State=False
		   Keyboard.Count=Keyboard.Count-1
		   If Keyboard.Count=False Then
		      Keyboard.Flag=False
		   Endif
                Endif
                Var$=Mid$(Str$(Ansi.Blank),2)
                Call Shell.Program("ANSI.EXE",Var$)
                Locate ,,0
                Ansi.Blank=Ansi.Blank+1
                If Ansi.Blank>4 Then
                   Ansi.Blank=1
                Endif
	     Endif
	  Endif
       Endif
       TempX=False
       Call Read.Keyboard(TempX$)
       If TempX$=Nul Then
          DEF SEG = &H40
          ShiftFlag = PEEK(&H17)
          DEF SEG
          LeftShift = ShiftFlag AND 1
          RightShift = ShiftFlag AND 2
          CtrlShift = ShiftFlag AND 4
          AltShift = ShiftFlag AND 8
          If LeftShift Or RightShift OR CtrlShift OR AltShift Then
             TempX$ = Chr$(0) + Chr$(0)
          Endif
       Endif
       If Mouse.Present Then
          Call MouseDriver
          If Mouse.Button2 Then
             TempX$=Chr$(27)
          Endif
          If Mouse.Button Then
             Call MouseSelect(1)
          Else
             If Mouse.Row Or Mouse.Column Then
                Call MouseSelect(2)
             Endif
          Endif
       Endif
       If Len(TempX$)=1 Then
          TempX$=Ucase$(TempX$)
       Endif
       If Len(TempX$) Then
	  If Len(TempX$)=2 Then
	     TempX=Asc(Right$(TempX$,1))
	  Endif
          If Blank.Screen Then
             Cls
             Call Passwrd3(Var,True)
             If Var=False Then
                Cls
                If Ansi.Blank>0 Then
                   Call Shell.Program("ANSI.EXE","-1")
                Endif
                Locate ,,0
                Goto End.Loop
             Endif
	     If Local.Mode Then
                Strng="Waiting"
	     Else
		Strng="Call Waiting"
	     Endif
	     Call Modem.Status
             TempX$=Nul
             TempX=False
	  Endif
          Menu.Timer=SFalse
          ScreenTimer=SFalse
	  If Blank.Menu Then
             TempX$=Nul
             TempX=False
	     Next.Field=1
	     Call Show.Field
          Endif
          Call Menu.Select
          If TempX$=Chr$(13) Then
             If Local.Mode=False Then ' bring modem offhook
                Select Case Selection
                Case 2, 3, 4, 5, 8, 9, 13, 14, 15, 16, 32
                   Strng=Config3(41)+Chr$(13)
                   Call Send.Modem(Strng)
		   Strng="Off Hook"
                   If Rtrim$(ANSIPrefixChar)<>"" Then
                      Strng=ANSIPrefixChar+"FB"+Strng ' cyan
                   Endif
		   Call Modem.Status
                End Select
	     Endif
             Select Case Selection
             Case 1
                If Local.Mode=False Then
                   Ring.Count=0
                   Time.Out!=Timeit!
                   Out2=Nul
                   Strng=Config3(40)+Chr$(13)
                   Call Send.Modem(Strng)
                   Strng="Auto Answer"
                   If Rtrim$(ANSIPrefixChar)<>"" Then
                      Strng=ANSIPrefixChar+"FB"+Strng ' cyan
                   Endif
                   Call Modem.Status
                Endif
             Case 2
		Call Clear.Screen
                Locate Max.Row-1,1,1
                Print "Type Exit to return.."
                Print
		Close
                Var$=Curdir$
		Shell
                Chdrive Var$
                Chdir Var$
                Call Read.Config(False)
		Exit Do
             Case 3
		Call Clear.Screen
                Print "Enter DOS command: ";
                Line Input Var$
		Close #TempFile1
		Open DOS.Exit For Output Shared As #TempFile1
		Print #TempFile1,Var$
		Print #TempFile1,"PAUSE"
		Print #TempFile1,"EXIT"
		Close #TempFile1
		Close
                Var$=Curdir$
		Shell DOS.Exit
                Chdrive Var$
                Chdir Var$
                Call Read.Config(False)
		Exit Do
             Case 4
                If Mouse.Present Then
                   Call Mouse.Function(2,0)
                Endif
                TempC=False
                TempD=False
		Call Chain.Program("EDIT.EXE",True,False)
                ' reset opening screen properties
                TempX$=Nul
                TempX=False
                Blank.Screen=False
                Connect=False
                Ring.Count=0
                Time.Out!=SFalse
                VarQ=False
                Exit Do
             Case 5
		Graphics.Off=False
		Local.Mode=True
		Lost.Carrier=False
		Recycle=False
                Timeon=Timeit!
		Time.Left=3600!
		Two.Minutes.Left=False
                If Mouse.Present Then
                   Call Mouse.Function(2,0)
                Endif
                Call Playwav(3)
		Exit Do
             Case 6
                If Local.Mode=False Then
                   Connect=False
                   Ring.Count=0
                   Time.Out!=SFalse
                   VarQ=False
                   Call playwav(1)
                   Call Recycle.Modem
                Endif
             Case 7
                If Local.Mode=False Then
                   Ring.Count=0
                   Time.Out!=Timeit!
                   Out2=Nul
                   Strng=Config3(66)+Chr$(13)
                   Call Send.Modem(Strng)
                   Strng="Originate Call"
                   If Rtrim$(ANSIPrefixChar)<>"" Then
                      Strng=ANSIPrefixChar+"FB"+Strng ' cyan
                   Endif
                   Call Modem.Status
                Endif
             Case 8
                Call Playwav(8)
		Call Chain.Program("DNDCNFG.EXE",True,False)
                ' reset opening screen properties
                TempX$=Nul
                TempX=False
                Blank.Screen=False
                Connect=False
                Ring.Count=0
                Time.Out!=SFalse
                VarQ=False
                Exit Do
             Case 9
                Call Playwav(8)
		Call Chain.Program("DNDEDIT.EXE",True,False)
                ' reset opening screen properties
                TempX$=Nul
                TempX=False
                Blank.Screen=False
                Connect=False
                Ring.Count=0
                Time.Out!=SFalse
                VarQ=False
                Exit DO
             Case 10
		Lost.Carrier=False
                Security.Guard=True
                Call Zero.Node(0)
                Call Clear.Screen
                Mouse.Present=False
                Call Playwav(3)
                Out2="Now exiting the Dndbbs Adventure System.."
                Out3="Reason: Terminate program selected. "+Fclock$
                Strng1="Terminated program."
                Strng2=Nul : Strng3=Nul
                Call Write.Logfile(False)
                Call Terminate.Program
                End 0
             Case 31 ' F11
		Lost.Carrier=False
                Security.Guard=True
                Call Zero.Node(0)
                Call Clear.Screen
                Mouse.Present=False
                Call Playwav(3)
                Out2="Now exiting the Dndbbs Adventure System.."
                Out3="Reason: Warm boot selected. "+Fclock$
                Strng1="Terminated program."
                Strng2="Reason: Warm boot."
                Strng3=Nul
                Call Write.Logfile(False)
                Close #TempFile1
                ' warm boot
                OUT &H64, &HF0
                Call Terminate.Program
                End 0
             Case 32 ' F12
		Lost.Carrier=False
                Security.Guard=True
                Call Zero.Node(0)
                Call Clear.Screen
                Mouse.Present=False
                Call Playwav(3)
                Out2="Now exiting the Dndbbs Adventure System.."
                Out3="Reason: Cold boot selected. "+Fclock$
                Strng1="Terminated program."
                Strng2="Reason: Cold boot."
                Strng3=Nul
                Call Write.Logfile(False)
                Close #TempFile1
                ' cold boot
                DEF SEG = &HFFFF
                CALL Absolute(0)
                DEF SEG
                Call Terminate.Program
                End 0
             Case 11 ' Alt-X
                ' allow any node to pack
                Gosub Dndpack2

                ' reset current node
                VarX2=Node+1
                Call Read.Message.Record(MessWorkFile1,VarX2)
                MessWorkRecord1.ActiveNode=True
                MessWorkRecord1.SuspendNode=False
                Call Write.Message.Record(MessWorkFile1,VarX2)

                ' reset opening screen properties
                TempX$=Nul
                TempX=False
                Blank.Screen=True
                Connect=False
                Ring.Count=0
                Time.Out!=SFalse
                VarQ=False
                Exit Do
             Case 12, 22 ' Alt-Y, Alt-0
                ' call windows screen saver
                If Selection=12 Then
                   Filename=DND.Path+"scrnsave.exe"
                   Call Shell.Program("SCRNSAVE.EXE","")
                Endif

                ' call dos screen saver
                Call Clear.Screen
                Call Sleep.Second2(3!) ' wait so Alt- does not stick
                Locate ,,0

                ' reset all screen saver variables
                Ansi.Blank=True
                Blank.Menu=False
                Blank.Screen=True
                Keyboard.Timer!=Timeit!
                Keyboard.Count=0
                Keyboard.Flag=23
                Shift.State=False
                Selection=1
             ' Alt-1 to 9
             Case 13 To 21
                Call Zero.Node(0)
                Var2$="/N:"+NodeX
                Call Clear.Screen
                Select Case Selection
                Case 13
                   Var$ = "CMD008.EXE" ' Bank
                Case 14
                   Var$ = "CMD023.EXE" ' Casino
                Case 15
                   Var$ = "CMD086.EXE" ' Mail
                Case 16
                   Var$ = "CMD126.EXE" ' Team
                Case 17
                   Var$ = "CMD190.EXE" ' |Password
                Case 18
                   Var$ = "CMD201.EXE" ' HexCalc
                Case 19
                   Var$ = "CMD203.EXE" ' |Toggle
                Case 20
                   Var$ = "CMD208.EXE" ' |Reboot
                Case 21
                   Var$ = "CMD037.EXE" ' Read.Dayfile
                End Select
                Call Shell.Program(Var$,Var2$)
                Call Zero.Node(-1)

                ' reset opening screen properties
                TempX$=Nul
                TempX=False
                Blank.Screen=False
                Connect=False
                Ring.Count=0
                Time.Out!=SFalse
                VarQ=False
                Exit Do
	     End Select
	  Endif
       Endif
       VarX2=Node+1
       Call Read.Message.Record(MessWorkFile1,VarX2)
       If MessWorkRecord1.SuspendNode Then
          Connect=False
       Endif
       Call Release.Time(1)
End.Loop:
    Loop
    If Local.Mode=False Then
       If Connect Then
          Modem.Return="CONNECT"+Str$(Modem.Baud)
          VarQ=False
          Time.Temp!=Timeit!
          Do
             If Time.Elapsed(Time.Temp!,6!) Then
                Exit Do
             Endif
             Call Read.Modem
             Out2=Ucase$(Out2)
             For Temp1=1 To MaxModemBauds
                Strng=Rtrim$(Modem.String(Temp1))
                If Len(Strng) Then
                   If Instr(Out2,Strng) Then
                      Modem.Return=Strng
                      VarQ=Temp1
                      Exit Do
                   Endif
                Endif
             Next
             If Instr(Out2,"CONNECT"+Chr$(13)+Chr$(10)) Then
                Out2="CONNECT 300"
             Endif
             If Instr(Out2,"CONNECT FAST") Then
                Out2="CONNECT 19200"
             Endif
          Loop
          If VarQ Then
             If Modem.Allow(VarQ)=False Then
                Strng2=Rtrim$(Modem.String(VarQ))
                Var=Instr(Strng2," ")
                If Var Then
                   Strng2=Mid$(Strng2,Var+1)
                Endif
                Strng="Sorry, "+Strng2+" baud access not allowed!"+Chr$(13)
                Call Send.Modem(Strng)
                Connect=False
             Endif
          Endif
       Endif
       If Connect Then
          Call Playwav(3)
	  Recycle=False
          Strng="Connect"+Str$(Modem.Baud)
	  Call Modem.Status
          Call Init.Fossil.Port
          Var=Instr(Modem.Return," ")
          If Var Then
             Modem.Return=Mid$(Modem.Return,Var+1)
          Endif
          Strng1="Modem to modem= "+Modem.Return
          Strng2="Computer to modem="+Str$(Modem.Baud)
          Strng3="Ring count:"+Str$(Ring.Count)
          Call Write.Logfile(False)
       Endif
    Endif
 Loop
 Call Clear.Screen
 Exit Sub
ShiftKey:
 If Bypass.Screen=False Then
    If Config2(106) Then
       Def Seg=False
       Poke &H0417,Key.State
       Def Seg
    Endif
 Endif
 Return
Quit.Door:
 ' display exit message
 Call Pre.Clock(Var$)
 Strng="Dndbbs online at "+Var$
 Print Strng
 Color 15,0
 Strng1="DOOR Mode: Door node "
 If Rtrim$(Door.Node)=Nul Then
    Strng1=Strng1+"-"
 Else
    Strng1=Strng1+Rtrim$(Door.Node)
 Endif
 If Port=-1 Then
    Strng1=Strng1+": Port -: "
 Else
    Strng1=Strng1+": Port"+Str$(Port)+": "
 Endif
 Strng1=Strng1+OutZ
 Color 14,0
 Print Strng1
 ' store log entry
 Strng2=Nul:Strng3=Nul
 Call Write.Logfile(False)
 ' exit program
 Call Zero.Node(0)
 Call Exit.To.DOS
 Color 7,0
 End 0
DndPack:
 If Only.No.Pack Then
    VarQ=0
    For VarX=False To MaxNodes
       Call Read.Message.Record(MessWorkFile1,VarX+1)
       Strng=Rtrim$(MessWorkRecord1.UserName)
       Call Valid.Name(Strng)
       If TempA Then
          If Only.No.Pack=-1 Then
             Return
          Endif
          VarQ=VarQ+1
       Endif
    Next
    If Only.No.Pack>0 Then
       If VarQ>=Only.No.Pack Then
          Return
       Endif
    Endif
 Endif
Dndpack2:
 VarX2=Node+1
 Call Read.Message.Record(MessWorkFile1,VarX2)
 If MessWorkRecord1.SuspendNode=False Then
    ' reset modem to off hook
    If Local.Mode=False Then
       Strng=Config3(41)+Chr$(13)
       Call Send.Modem(Strng)
       Strng="Off Hook"
       If Rtrim$(ANSIPrefixChar)<>"" Then
          Strng=ANSIPrefixChar+"FB"+Strng ' cyan
       Endif
       Call Modem.Status
    Endif
    ' reset active node
    MessWorkRecord1.ActiveNode=False
    Call Write.Message.Record(MessWorkFile1,VarX2)
    Call Clear.Screen
    V$="DNDPACK.EXE"
    X$="/N:"+NodeX
    Call Shell.Program(V$,X$)
    Call Sleep.Second2(3!)
    Gosub Set.Usage.File
    ' reset active node
    Call Read.Message.Record(MessWorkFile1,VarX2)
    MessWorkRecord1.ActiveNode=True
    MessWorkRecord1.SuspendNode=False
    Call Write.Message.Record(MessWorkFile1,VarX2)
    ' reset opening screen properties
    TempX$=Nul
    TempX=False
    If Blank.Screen=False Then
       Call Opening.Screen
       Connect=False
       Ring.Count=0
       Time.Out!=SFalse
       VarQ=False
       Call playwav(1)
       Call Recycle.Modem
       Return
    Endif
    Call Clear.Screen
    Locate ,,0
    If Keyboard.Count>False Then
       If Keyboard.Flag<22 Then
          Call Shell.Program("ANSI.EXE","-1")
          If Ansi.Blank>0 Then
             Var$=Mid$(Str$(Ansi.Blank),2)
             Call Shell.Program("ANSI.EXE",Var$)
          Endif
          Locate ,,0
       Endif
    Endif
 Endif
 Return
Set.Usage.File:
 ' check usage file
 Close #TempFile1
 FileName=Usage.FileName
 Open FileName For Random Shared As #TempFile1 Len=26
 Field #TempFile1,10 As D$,8 As T$,8 As X$
 Get #TempFile1,3
 Lset D$=DateS$
 Time1$=Format$(Now,"hh:mm:ss")
 Lset T$=Time1$
 Put #TempFile1,3
 Close #TempFile1
 Return
Get.Config5:
 Debug.Pack2=0
 Max.Ring.Count=10
 Display.Menu.Timer!=30!
 Only.No.Pack=0
 VarX=0
 Do
    VarX=VarX+1
    If VarX>Options.Lines Then
       Exit Do
    Endif
    Var$=Ltrim$(Rtrim$(Options.Array(VarX)))
    If Ucase$(Var$)="[MODEM]" Then
       Do
          VarX=VarX+1
          If VarX>Options.Lines Then
             Return
          Endif
          Var$=Ltrim$(Rtrim$(Options.Array(VarX)))
          If Ucase$(Var$)="[END]" Then
             Return
          Endif
          Var=Instr(Var$,"=")
          If Var Then
             Var2$=Ltrim$(Rtrim$(Left$(Var$,Var-1)))
             Var3$=Ltrim$(Rtrim$(Mid$(Var$,Var+1)))
             Select Case Lcase$(Var2$)
             Case "only.no.pack"
                Select Case Ucase$(Var3$)
                Case "-1","ON","TRUE"
                   Only.No.Pack=-1
                Case Else
                   If Int(Val(Var3$))>=1 And Int(Val(Var3$))<=127 Then
                      Only.No.Pack=Int(Val(Var3$))
                   Endif
                End Select
             Case "also.allow.data.pack"
                Select Case Ucase$(Var3$)
                Case "-1","ON","TRUE"
                   Debug.Pack2=-1
                End Select
             Case "max.ring.count"
                Select Case Int(Val(Var3$))
                Case 10 To 1024
                   Max.Ring.Count=Int(Val(Var3$))
                End Select
             Case "display.menu.timer"
                Select Case Int(Val(Var3$))
                Case 1 To 1024
                   Display.Menu.Timer!=Int(Val(Var3$))
                End Select
             End Select
          Endif
       Loop
    Endif
 Loop
 Return
ErrResume4:
 Exit Sub
ErrTrap4:
 Resume ErrResume4
End Sub

Sub Write.Logfile(Var)
 On Local Error Goto ErrTrap4a
 If Var=False Then
    If Config2(45)=0 Then
       Exit Sub
    Endif
 Endif
 Close #TempFile1
 FileName$=DND.Path+"modem"+NodeX+".log"
 Open FileName$ For Append As #TempFile1
 If Rtrim$(NodeX)=Nul Then
    Strng="-"
 Else
    Strng=NodeX
 Endif
 Strng="Node "+Strng+", "
 If Port<0 Then
    Strng=Strng+"Port -"
 Else
    Strng=Strng+"Port"+Str$(Port)
 Endif
 Print #TempFile1,Fclock$+", "+Strng
 Print #TempFile1,Strng1
 If Len(Strng2) Then
    Print #TempFile1,Strng2
 Endif
 If Len(Strng3) Then
    Print #TempFile1,Strng3
 Endif
 Print #TempFile1,""
 Exit Sub
ErrResume4a:
 Print "Error"+Str$(Err)+" writing "+Filename$
 Exit Sub
ErrTrap4a:
 Resume ErrResume4a
End Sub

Sub Menu.Select
 On Local Error Goto ErrTrap5
 Dim Menu.Array(1 To 10) As Integer
 Dim Menu.Array2(1 To 26) As Integer
 Gosub Get.Config1
 Next.Field=False
 Select Case TempX$
 Case Chr$(0) ' ctrl-break
    Exit Sub
 Case Chr$(9) ' tab
    TempX=77
 Case Chr$(27) ' escape
    TempX=10
 Case Chr$(13) ' enter
    If Left$(Menu1(Selection),1)="*" Then
       If Selection<>10 Then
          VarZ=-1
          TempX$=Nul
       Endif
    Endif
 Case Else
    ' fixed 07-19-2020
    If Len(TempX$)=1 Then
       VarX$=Nul
       For VarX=1 To 10
          VarZ$=Menu1(VarX)
          VarZ$=Rtrim$(VarZ$)
          If VarZ$="" Then
             VarX$=VarX$+"*"
          Else
             VarX$=VarX$+Left$(VarZ$,1)
          Endif
       Next
       VarX$=Ucase$(VarX$)
       TempX=Instr(VarX$,TempX$)
    Endif
 End Select
 Select Case TempX
 Case 1 To 10 ' menu key
    If Left$(Menu1(TempX),1)<>"*" Or TempX=10 Then
       Next.Field=TempX
       TempX$=Chr$(13)
    Else
       VarZ=-1
    Endif
 Case 59 To 68 ' F1 - F10
    If Left$(Menu1(TempX-58),1)<>"*" Or TempX=68 Then
       Next.Field=TempX-58
       TempX$=Chr$(13)
    Else
       VarZ=-1
    Endif
 Case 84 To 93 ' Shift-F1 To Shift-F10
    If Left$(Menu1(TempX-83),1)<>"*" Or TempX=93 Then
       Next.Field=TempX-83
       TempX$=Chr$(13)
    Else
       VarZ=-1
    Endif
 Case 94 To 103 ' Ctrl-F1 To Ctrl-F10
    If Left$(Menu1(TempX-93),1)<>"*" Or TempX=103 Then
       Next.Field=TempX-93
       TempX$=Chr$(13)
    Else
       VarZ=-1
    Endif
 Case 104 To 113 ' Alt-F1 To Alt-F10
    If Left$(Menu1(TempX-103),1)<>"*" Or TempX=113 Then
       Next.Field=TempX-103
       TempX$=Chr$(13)
    Else
       VarZ=-1
    Endif
 Case 72, 141, 152 ' up/ctrl-up/alt-up
    If Selection>1 Then
       Next.Field=Selection-1
    Endif
 Case 80, 145, 160 ' down/ctrl-dn/alt-dn
    If Selection<10 Then
       Next.Field=Selection+1
    Endif
 Case 15, 75, 155, 115 ' shift-tab/left/alt-left/ctrl-left
    If Selection>5 Then
       Next.Field=Selection-5
    Endif
 Case 77, 157, 116 ' right/alt-right/ctrl-right
    If Selection<6 Then
       Next.Field=Selection+5
    Endif
 Case 71, 119 ' home/ctrl-home
    If Selection<>1 Then
       Next.Field=1
    Endif
 Case 79, 117, 147 ' end/ctrl-end/ctrl-delete
    If Selection<>10 Then
       Next.Field=10
    Endif
 Case 73, 132, 152 ' pageup/ctrl-pageup/alt-up
    If Selection<6 And Selection<>1 Then
       Next.Field=1
    Endif
    If Selection>5 And Selection<>6 Then
       Next.Field=6
    Endif
 Case 81, 118, 160 ' pagedown/ctrl-pagedn/alt-down
    If Selection<6 And Selection<>5 Then
       Next.Field=5
    Endif
    If Selection>5 And Selection<>10 Then
       Next.Field=10
    Endif

 ' Shell to Cmd008, Cmd023, Cmd086, Cmd126,
 '   Cmd190, Cmd201, Cmd203, Cmd208, Cmd037.
 '  Alt-0 to clear screen
 Case 120 To 129 ' Alt-1 To Alt-9, Alt-0
    If Menu.Array(TempX-119)=0 Then
       Selection=TempX-107
       TempX$=Chr$(13)
    Else
       VarZ=-1
    Endif

 ' scancodes for Alt-A to Alt-Z:
 '  30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50
 '  49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44 

 ' Alt-R = refresh opening screen
 Case 19
    If Menu.Array2(18)=0 Then
       Goto Show.Toggle
    Endif

 ' Alt-G = enable/disable fossil
 Case 34
    If Menu.Array2(7)=0 Then
       If Fossil.Active Then
          Fossil.Active=0
       Else
          Fossil.Active=-1
          Fossil.Version=2
       Endif
       If Max.Row=25 Then
          If Debug.Mode Then
             Call Display25row
          Endif
       Endif
    Endif

 ' Alt-E = toggle fossil
 Case 18
    If Menu.Array2(5)=0 Then
       If Fossil.Active Then
          If Fossil.Version=1 Then
             Fossil.Version=2
          Else
             If Fossil.Version=2 Then
                Fossil.Version=1
             Endif
          Endif
          If Max.Row=25 Then
             If Debug.Mode Then
                Call Display25row
             Endif
          Endif
       Endif
    Endif

 ' Alt-A = base address
 Case 30
    If Menu.Array2(1)=0 Then
    Call ScreenANSI(2,25,3)
    Var$=Space$(77)
    Call Put.Screen(Var$)
    Call ScreenANSI(2,25,3)
    Locate 25,3
    Line Input; "Base address(hex):"; Var$
    Var$=Ucase$(Var$)
    VarX=ValidHex(Var$)
    If VarX Then
       Temp$="&H"+Var$
       If Int(Val(Temp$))>=1 And Int(Val(Temp$))<=MaxInt Then
          Base.Address=Int(Val(Temp$))
       Endif
    Endif

    Call ScreenANSI(2,25,3)
    Var$=Space$(77)
    Call Put.Screen(Var$)
    'Goto Show.Toggle
    If Debug.Mode Then
       Call Display25row
    Endif
    Endif

 ' Alt-B = baud rate
 Case 48
    If Menu.Array2(2)=0 Then
    Call ScreenANSI(2,25,3)
    Var$=Space$(77)
    Call Put.Screen(Var$)
    Call ScreenANSI(2,25,3)
    Locate 25,3
    Line Input; "Baud rate:"; Var$
    Temp!=Csng(Int(Val(Var$)))
    If Temp!>0! Then
       Call Set.Baud(Temp!)
    Endif

    Call ScreenANSI(2,25,3)
    Var$=Space$(77)
    Call Put.Screen(Var$)
    'Goto Show.Toggle
    If Debug.Mode Then
       Call Display25row
    Endif
    Endif

 ' Alt-C = comm port
 Case 46 
    If Menu.Array2(3)=0 Then
    Call ScreenANSI(2,25,3)
    Var$=Space$(77)
    Call Put.Screen(Var$)
    Call ScreenANSI(2,25,3)
    Locate 25,3
    Line Input; "Comm port(0-64):"; Var$
    Temp=Int(Val(Var$))
    'If Temp=0 Then
    '   Port=-1
    'Endif
    If Temp>=0 And Temp<=64 Then
       Port=Temp-1
       Port.Override=Temp
    Endif

    Call ScreenANSI(2,25,3)
    Var$=Space$(77)
    Call Put.Screen(Var$)
    'Goto Show.Toggle
    If Debug.Mode Then
       Call Display25row
    Endif
    Endif

 ' Alt-D  disk log
 Case 32
    If Menu.Array2(4)=0 Then
       Call Flag.Toggles(7)
       Goto Show.Toggle
    Endif
    VarZ=-1
 ' Alt-P  printer log
 Case 25
    If Menu.Array2(16)=0 Then
       Call Flag.Toggles(8)
       Goto Show.Toggle
    Endif
    VarZ=-1
 ' Alt-W  toggle display
 Case 17
    If Menu.Array2(23)=0 Then
       Select Case Bypass.Splash
       Case 0
          Bypass.Splash=1
       Case 1
          Bypass.Splash=2
       Case 2
          Bypass.Splash=3
       Case 3
          Bypass.Splash=0
       End Select
       Goto Show.Toggle
    Endif
    VarZ=-1
 ' Alt-X  shell to dndpack
 Case 45
    If Menu.Array2(24)=0 Then
       ' node pack
       Selection=11
       TempX$=Chr$(13)
    Else
       VarZ=-1
    Endif
 ' Alt-Y  windows screen saver function call
 Case 21
    If Menu.Array2(25)=0 Then
       Selection=12
       TempX$=Chr$(13)
    Else
       VarZ=-1
    Endif
 ' Alt-Z toggle debug
 Case 44
    If Menu.Array2(26)=0 Then
       Debug.Mode=Not Debug.Mode
       Goto Show.Toggle
    Endif
    VarZ=-1
 ' Alt-F toggle local.mode
 Case 33
    If Menu.Array2(6)=0 Then
       Local.Mode=Not Local.Mode
       Goto Show.Toggle
    Endif

   ' F11=133, shift-F11=135, ctrl-F11=137, alt-F11=139
   ' F12=134, shift-F12=136, ctrl-F12=138, alt-F12=140
 Case 133, 135, 137, 139 ' F11
    Selection=31
    TempX$=Chr$(13)
    Exit Sub
 Case 134, 136, 138, 140 ' F12
    Selection=32
    TempX$=Chr$(13)
    Exit Sub
 Case 241 To 250 ' mouse
    Next.Field=TempX-240
 End Select
 If Next.Field Then
    Call Show.Field
 Endif
 If VarZ Then
    Call playwav(1)
 Endif
 Exit Sub
Show.Toggle:
 Blank.Screen=True
 If Local.Mode Then
    Strng="Waiting"
 Else
    Strng="Call Waiting"
 Endif
 If Mouse.Present Then
    Call Mouse.Function(2,0)
 Endif
 Call Modem.Status
 If Mouse.Present Then
    Call Mouse.Function(1,0)
 Endif
 Exit Sub
Get.Config1:
 VarX=0
 Do
    VarX=VarX+1
    If VarX>Options.Lines Then
       Exit Do
    Endif
    Var$=Ltrim$(Rtrim$(Options.Array(VarX)))
    If Ucase$(Var$)="[DNDBBS]" Then
       Do
          VarX=VarX+1
          If VarX>Options.Lines Then
             Exit Do
          Endif
          Var$=Ltrim$(Rtrim$(Options.Array(VarX)))
          If Ucase$(Var$)="[END]" Then
             Exit Do
          Endif
          Var=Instr(Var$,"=")
          If Var Then
             Var2$=Lcase$(Ltrim$(Rtrim$(Left$(Var$,Var-1))))
             Var3$=Lcase$(Ltrim$(Rtrim$(Mid$(Var$,Var+1))))
             If Left$(Var2$,4)="alt-" Then
                VarQ$=Mid$(Var2$,5)
                If Len(VarQ$)=1 Then
                   Select Case Var3$
                   Case "0", "false", "off"
                      Select Case VarQ$
                      Case "1" To "9" ' Alt-1 to Alt-9
                         VarQ=Int(Val(VarQ$))
                         Menu.Array(VarQ)=-1
                      Case "0" ' Alt-0
                         Menu.Array(10)=-1
                      Case "a" To "z" ' Alt-A to Alt-Z
                         VarQ=Asc(VarQ$)-96
                         Menu.Array2(VarQ)=-1
                      End Select
                   End Select
                Endif
             Endif
          Endif
       Loop
    Endif
 Loop
 Return
ErrResume5:
 Exit Sub
ErrTrap5:
 Resume ErrResume5
End Sub

' display blank field
Sub Show.Field
 On Local Error Goto ErrTrap6
 Call Display.Field
 Blank.Menu=False
 Selection=Next.Field
 Call Mouse.Function(2,0)
 Var1=Menu2(Selection,1)
 Var2=Menu2(Selection,2)+3
 If Selection=10 Then
    Var2=Var2+1
 Endif
 Call ScreenANSI(2,Var1,Var2)
 Call ScreenANSI(4,37,0)
 Call ScreenANSI(4,45,95)
 Strng=Left$(Menu1(Selection),1)
 Call Scrn(Strng)
 Call ScreenANSI(4,33,0)
 Call ScreenANSI(4,45,94)
 Strng=Mid$(Menu1(Selection),2)
 Strng=Rtrim$(Strng)
 VarZ=Local.Mode
 Local.Mode=True
 Call Convert.String ' convert macros
 Call Convert.ANSI(False,VarQ,VarR) ' convert prefixes
 Local.Mode=VarZ
 Call Scrn(Strng)
 Call Mouse.Function(1,0)
ErrResume6:
 Exit Sub
ErrTrap6:
 Resume ErrResume6
End Sub

' display hilighted field
Sub Display.Field
 On Local Error Goto ErrTrap7
 Var1=Menu2(Selection,1)
 Var2=Menu2(Selection,2)+3
 If Selection=10 Then
    Var2=Var2+1
 Endif
 Call Mouse.Function(2,0)
 Call ScreenANSI(2,Var1,Var2)
 Call ScreenANSI(4,37,0)
 Call ScreenANSI(4,44,31)
 Strng=Left$(Menu1(Selection),1)
 Call Scrn(Strng)
 Call ScreenANSI(4,33,0)
 Call ScreenANSI(4,44,30)
 Strng=Mid$(Menu1(Selection),2)
 Strng=Rtrim$(Strng)
 VarZ=Local.Mode
 Local.Mode=True
 Call Convert.String ' convert macros
 Call Convert.ANSI(False,VarQ,VarR) ' convert prefixes
 Local.Mode=VarZ
 Call Scrn(Strng)
 Call Mouse.Function(1,0)
ErrResume7:
 Exit Sub
ErrTrap7:
 Resume ErrResume7
End Sub

Sub Recycle.Modem
 On Local Error Goto ErrTrap8
 ' test modem offline/turned off
 If Local.Mode=False Then
    Call Check.Modem(Var)
    If Var Then
       Blank.Screen=True
       Local.Mode=True
       Strng="Waiting"
       Call Modem.Status
       Exit Sub
    Endif
 Endif
 ' check local, display & exit
 If Local.Mode Then
    Strng="Waiting"
    Call Modem.Status
    Exit Sub
 Endif
 ' reset cycle counter
 Var1=False
 ' start modem recycle loop
 TempX$=""
 Do
    ' check escape pressed
    TempX$=Inkey$
    If TempX$=Chr$(27) Then
       Call Playwav(3)
       Strng="Recycle Halt"
       If Rtrim$(ANSIPrefixChar)<>"" Then
          Strng=ANSIPrefixChar+"FC"+Strng ' red
       Endif
       Exit Do
    Endif
    ' display recycle
    Strng="Recycle"
    Call Modem.Status
    ' lower/raise dtr
    TempX$=""
    Call Recycle.DTR
    ' activate port
    Call Init.Fossil.Port
    ' check locked baud
    If Config2(65)=False Then
       Call Set.Driver ' set baud n,8,1
    Endif
    ' check escape during recycle.dtr
    If TempX$=Chr$(27) Then
       Call Playwav(3)
       Strng="Recycle Halt"
       If Rtrim$(ANSIPrefixChar)<>"" Then
          Strng=ANSIPrefixChar+"FC"+Strng ' red
       Endif
       Exit Do
    Endif
    ' recycle modem
    Out2=Nul
    Strng=Config3(42)+Chr$(13) ' ATZ
    Call Send.Modem(Strng)
    Display.Timer!=Timeit!
    Time.Temp!=Timeit!
    Do
       ' check escape pressed
       TempX$=Inkey$
       If TempX$=Chr$(27) Then
          Call Playwav(3)
          Strng="Recycle Halt"
          If Rtrim$(ANSIPrefixChar)<>"" Then
             Strng=ANSIPrefixChar+"FC"+Strng ' red
          Endif
          Goto RecycleEnd
       Endif
       Call Read.Modem
       If Instr(Out2,"OK") Then
          Exit Do
       Endif
       If Time.Elapsed(Time.Temp!,Csng(Config2(84))) Then
	  Exit Do
       Endif
       If Time.Elapsed(Display.Timer!,1!) Then
          Display.Timer!=Timeit!
          Call Display.Time
       Endif
    Loop
    If Instr(Out2,"OK") Then
       Strng="Reset OK"
       VarX=True
    Else
       If Instr(Out2,"ERROR") Then
          Strng="Reset Error"
          VarX=False
       Else
          Strng="Reset Fail"
          VarX=False
       Endif
    Endif
    If Rtrim$(ANSIPrefixChar)<>"" Then
       Strng=ANSIPrefixChar+"FA"+Strng ' green
    Endif
    Call Modem.Status
    Call Sleep.Second2(1!)
    Out2=Nul
    Strng=Config3(39)+Chr$(13) ' init string
    Call Send.Modem(Strng)
    Display.Timer!=Timeit!
    Time.Temp!=Timeit!
    Do
       ' check escape pressed
       TempX$=Inkey$
       If TempX$=Chr$(27) Then
          Call Playwav(3)
          Strng="Recycle Halt"
          If Rtrim$(ANSIPrefixChar)<>"" Then
             Strng=ANSIPrefixChar+"FC"+Strng ' red
          Endif
          Goto RecycleEnd
       Endif
       Call Read.Modem
       If Instr(Out2,"OK") Then
          Exit Do
       Endif
       If Time.Elapsed(Time.Temp!,Csng(Config2(84))) Then
	  Exit Do
       Endif
       If Time.Elapsed(Display.Timer!,1!) Then
          Display.Timer!=Timeit!
          Call Display.Time
       Endif
    Loop
    If Instr(Out2,"OK") Then
       Strng="Init OK"
       VarY=True
    Else
       If Instr(Out2,"ERROR") Then
          Strng="Init Error"
          VarY=False
       Else
          Strng="Init Fail"
          VarY=False
       Endif
    Endif
    If Rtrim$(ANSIPrefixChar)<>"" Then
       Strng=ANSIPrefixChar+"FA"+Strng ' green
    Endif
    Call Modem.Status
    Call Sleep.Second2(1!)
    Out2=Nul
    ' test both strings sent & received OK
    If VarX And VarY Then
       Strng="Call Waiting"
       Exit Do
    Endif
    ' check counters
    If Config2(49)>False Then
       Var1=Var1+1
       If Var1>Config2(49) Then
          Call Playwav(3)
	  Strng="Recycle Fail"
          If Rtrim$(ANSIPrefixChar)<>"" Then
             Strng=ANSIPrefixChar+"FC"+Strng ' red
          Endif
	  Exit Do
       Endif
    Endif
 Loop
RecycleEnd:
 Call Modem.Status
ErrResume8:
 Exit Sub
ErrTrap8:
 Resume ErrResume8
End Sub

Sub Shell.Program(Var$,Var2$)
 On Local Error Goto ErrTrap9
 If Var2$="43" Or Var2$="50" Then
    Close #TempFile1
    Open DND.Path+"NODE"+NodeX+".DEF" For Output As #TempFile1
    Print #TempFile1,Config3(11) ' c:\dnddat\
    Print #TempFile1,Config3(51) ' dndusage
    Print #TempFile1,Config3(15) ' .dat
    Print #TempFile1,Var2$ ' screen size
    Close #TempFile1
 Endif

 VarX=0
 Select Case Var$
 Case "ANSI.EXE", "COPYSCRN.EXE", "SCRNSAVE.EXE", "BYTEFREE.EXE", "TOPTEN.EXE"
    VarX=-1
 End Select
 ' get dndpath with filename
 Filename=DND.Path+Var$
 ' get ramdrive with filename
 If Left$(Var$,3)="CMD" Then
    Var1=Val(Mid$(Var$,4,3)) ' command number
    Call Get.Config2x(Option1$,Var1)
    Filename=Option1$+Var$
 Endif
 If Dir$(Filename)<>Nul Then
    Call Close.Nodes
    Call Close.Files
    Call Close.Temp
    Var3$=Curdir$
    If Var2$="43" Or Var2$="50" Then
       Filename=Filename+" /"+NodeX
    Else
       If Var2$<>Nul Then
          Filename=Filename+" "+Var2$
       Else
          If Var$="SCRNSAVE.EXE" Then
             If Windows.Detected Then
                Filename="START "+Var$
             Endif
          Else
             Filename=Var$
          Endif
       Endif
    Endif

    If VarX=0 Then
       Color 15,0
       Cls
       Locate Max.Row-1,1,1
       Print
       Print "Shelling: "+Filename
       Print "  (error here then use Shroom)"
    Endif

    Shell Filename

    If VarX=0 Then
       Call Sleep.Second2(3!)
    Endif

    Chdrive Var3$
    Chdir Var3$
    Call Open.Shell.Files
    Call Open.Temp.Files
    Call Open.Node.Files
    Call Open.Session.Files
    Exit Sub
 Endif
ErrResume9:
 If VarX Then
    Exit Sub
 Endif
 Var2=Err
 If Var2=0 Then
    Var2=53 ' file not found
 Endif
 Call Error.Message(Var2,VarX$)
 Cls
 Color 15,0
 Print "Dndbbs menu error:"
 Color 14,0
 Print
 Print "Error:"+VarX$+" shelling to "+Filename+". Reinstall Dndbbs."
 Call More.Prompt
 Exit Sub
ErrTrap9:
 Resume ErrResume9
End Sub

Sub Init.Drivers
 On Local Error Goto ErrTrap10
 Call Read.Rows(Max.Row)
 ' check ansi
 Call Plex.Function(26)
 If (OutregsX.AX And &HFF)=&HFF Then
    Local.ANSI.Color=True
 Else
    Local.ANSI.Color=False
 Endif
 ' check config switch
 If Disable.ANSI=True Then
    Local.ANSI.Color=False
 Endif
 If Disable.ANSI=-2 Then
    Local.ANSI.Color=True
 Endif
 ' check avatar
 Local.Avatar.Color=False
 Call Plex.Function(27)
 If (OutregsX.AX And &HFF)=&HFF Then
    If (OutregsX.DX And &HFF)=&H16 Then
       Local.Avatar.Color=True
    Endif
 Endif
 ' check config switch
 If Disable.Avatar=True Then
    Local.Avatar.Color=False
 Endif
 If Disable.Avatar=-2 Then
    Local.Avatar.Color=True
 Endif
 ' check mouse
 Locate Max.Row-1,1,1
 Mouse.Present=False
 Call Mouse.Function(0,0)
 ' mouse block cursor is 8x8 pixels..
 If OutregsX.AX=&HFFFF Then
    Mouse.Present=True
    M.Row=Max.Row*8-8 ' row is 0 based.
    Call Mouse.Function2(7,0,0,632) ' 80 columns
    Select Case Max.Row
    Case 25
       Call Mouse.Function2(8,0,0,M.Row) ' 25 rows
    Case 43
       Call Mouse.Function2(8,0,0,M.Row) ' 43 rows
    Case 50
       Call Mouse.Function2(8,0,0,M.Row) ' 50 rows
    Case Else
       Call Mouse.Function2(8,0,0,192) ' 25 rows
    End Select
 Endif
 ' check os
 Call StdinInt(48,0)
 ' store dos version
 DOS.Major=OutregsX.AX And &HFF
 DOS.Minor=(OutregsX.AX And &HFF00)/256
 ' check os/2
 If DOS.Major=10 Or DOS.Major=20 Then
    OS2.Detected=True
 Else
    OS2.Detected=False
 Endif
 ' check windows
 Windows.Detected = False
 Call Plex.Function(22)
 If OutregsX.BX>0 Then
    Windows.Detected = True
    ' store windows version
    Win.Minor=OutregsX.BX And &HFF
    Win.Major=(OutregsX.BX And &HFF00)/256
 Endif
 ' check share
 Call Plex.Function(16)
 If (OutregsX.AX And &HFF)=&HFF Then
    Share.Installed=True
 Else
    Share.Installed=False
 Endif
 ' check config switch
 If Disable.Share=True Then
    Share.Installed=False
 Endif
 If Disable.Share=-2 Then
    Share.Installed=True
 Endif
 ' init screen
 Call ScreenANSI(1,37,15)
 Call ScreenANSI(4,37,15)
 Call ScreenANSI(2,Max.Row-1,1)
ErrResume10:
 Exit Sub
ErrTrap10:
 Resume ErrResume10
End Sub

Sub System.Type
 On Local Error Goto ErrTrap11
 If Windows.Detected Then
    If Win.Major=4 Then
       If Win.Minor>10 Then
          Strng="Win ME"
       Else
          If Win.Minor=10 Then
             Strng="Win 98"
          Else
             If Win.Minor=3 Then
                Strng="Win 95B"
             Else
                Strng="Win 95"
             Endif
          Endif
       Endif
    Else
       If Win.Major>4 Then
          Strng="WinX" ' OS past 98
       Else
          Strng="Win"+Str$(Win.Major)+"."+Ltrim$(Str$(Win.Minor))
       Endif
    Endif
    Exit Sub
 Endif
 Select Case DOS.Major
 Case 10
    Strng="OS/2 v1.0"
 Case 20
    Strng="OS/2 v2.0"
    Select Case DOS.Minor
    Case 30
       Strng="OS/2 v3.0"
    Case 40
       Strng="OS/2 v4.0"
    End Select
 Case 30
    Strng="Mac OSX"
 Case Else
    Strng="DOS"+Str$(DOS.Major)+"."+Ltrim$(Str$(DOS.Minor))
 End Select
ErrResume11:
 Exit Sub
ErrTrap11:
 Resume ErrResume11
End Sub

Sub Get.Free.Memory
 On Local Error Goto ErrTrap12
 Strng=Nul
 If OS2.Detected Then ' has no freespace
    Strng="256.00 KB"
 Else
    Temp#=Fre(-1)+Fre(a$) ' free far+temp
    Call Make.Format(Temp#)
 Endif
ErrResume12:
 Exit Sub
ErrTrap12:
 Resume ErrResume12
End Sub

Sub Make.Format(Var#)
 On Local Error Goto ErrTrap13
 Var2#=Var#
 If Var2#<=0 Then
    Strng="0.00 B"
    Exit Sub
 Endif
 TempA=False
 Do
    If Var2#<1024# Then
       Exit Do
    Endif
    Var2#=Var2#/1024#
    TempA=TempA+1
    If TempA=8 Then
       Exit Do
    Endif
 Loop
 Strng=Nul
 If TempA>=1 And TempA<=8 Then
    Strng=Mid$("KMGTPEZY",TempA,1)
 Endif
 Strng=Format$(Var2#,"#,##0.00;;")+" "+Strng+"B"
ErrResume13:
 Exit Sub
ErrTrap13:
 Resume ErrResume13
End Sub

Sub Read.Rows(Var)
 On Local Error Goto Error.Trap62x
 Temp1=50
 Locate 50,1,0
 Var=50
 Exit Sub
Next.Trap1:
 Temp1=43
 Locate 43,1,0
 Var=43
 Exit Sub
Next.Trap2:
 Var=25
Error.Resume62x:
 Exit Sub
Error.Trap62x:
 If Temp1=50 Then
    Resume Next.Trap1
 Endif
 If Temp1=43 Then
    Resume Next.Trap2
 Endif
 Resume Error.Resume62x
End Sub

Sub Amount(Var#,Var$)
 If Instr(Str$(Var#),"D") Then
    Var$=Str$(Var#)
 Else
    Var$=" "+Form$(Var#)
 Endif
End Sub

Sub Amount2(Var#,Var$)
 VarX$=Ltrim$(Str$(Var#)) ' 1.111D308
 V=Instr(VarX$,"D")
 If V Then
    If Mid$(VarX$,2,1)="." Then
       VarX$=Left$(VarX$,1)+Mid$(VarX$,V)
    Endif
    Var$=" "+VarX$
 Else
    Var$=" "+Form$(Var#)
 Endif
End Sub
