;
;  Program:  STARTUP
;  Author:  Richard Conn
;  Version:  1.4
;  Date:  9 Jan 83
;  Previous Versions:  1.3 (7 Jan 83)
;  Previous Versions:  1.2 (6 Jan 83), 1.1 (7 Dec 82), 1.0 (8 Nov 82)
;
;       STARTUP loads the ZCPR2 command line with an initial command string
; for execution on cold boot.  The user may specify what this command string
; is to STARTUP in an interactive mode, and STARTUP may be configured at
; any time.
;
vers    equ     14

;
;       This program is Copyright (c) 1982, 1983 by Richard Conn
;       All Rights Reserved
;
;       ZCPR2 and its utilities, including this one, are released
; to the public domain.  Anyone who wishes to USE them may do so with
; no strings attached.  The author assumes no responsibility or
; liability for the use of ZCPR2 and its utilities.
;
;       The author, Richard Conn, has sole rights to this program.
; ZCPR2 and its utilities may not be sold without the express,
; written permission of the author.
;


;
;  Externals
;
       ext     print,bbline,initfcb
       ext     f$delete,f$make,f$write,f$close
       ext     cin,cout,caps,crlf
       ext     eval,padc,phl4hc
       ext     shftlh,pstr
       ext     fname,bdos
       ext     codend

;
;  Constants
;
fcb     equ     5ch
cr      equ     0dh
lf      equ     0ah

;
;  Branch to Start of Program
;
       jmp     start

;
;******************************************************************
;
;  SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
;
;       This data block precisely defines the data format for
; initial features of a ZCPR2 system which are required for proper
; initialization of the ZCPR2-Specific Routines in SYSLIB.
;

;
;  EXTERNAL PATH DATA
;
EPAVAIL:
       DB      0FFH    ; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
EPADR:
       DW      40H     ; ADDRESS OF EXTERNAL PATH IF AVAILABLE

;
;  INTERNAL PATH DATA
;
INTPATH:
       DB      0,0     ; DISK, USER FOR FIRST PATH ELEMENT
                       ; DISK = 1 FOR A, '$' FOR CURRENT
                       ; USER = NUMBER, '$' FOR CURRENT
       DB      0,0
       DB      0,0
       DB      0,0
       DB      0,0
       DB      0,0
       DB      0,0
       DB      0,0     ; DISK, USER FOR 8TH PATH ELEMENT
       DB      0       ; END OF PATH

;
;  MULTIPLE COMMAND LINE BUFFER DATA
;
MCAVAIL:
       DB      000H    ; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
MCADR:
       DW      0FF00H  ; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE

;
;  DISK/USER LIMITS
;
MDISK:
       DB      4       ; MAXIMUM NUMBER OF DISKS
MUSER:
       DB      31      ; MAXIMUM USER NUMBER

;
;  FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
;
DOK:
       DB      0FFH    ; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
UOK:
       DB      0FFH    ; ALLOW USER CHANGE? (0=NO, 0FFH=YES)

;
;  PRIVILEGED USER DATA
;
PUSER:
       DB      10      ; BEGINNING OF PRIVILEGED USER AREAS
PPASS:
       DB      'chdir',0       ; PASSWORD FOR MOVING INTO PRIV USER AREAS
       DS      41-($-PPASS)    ; 40 CHARS MAX IN BUFFER + 1 for ending NULL

;
;  CURRENT USER/DISK INDICATOR
;
CINDIC:
       DB      '$'     ; USUAL VALUE (FOR PATH EXPRESSIONS)

;
;  DMA ADDRESS FOR DISK TRANSFERS
;
DMADR:
       DW      80H     ; TBUFF AREA

;
;  NAMED DIRECTORY INFORMATION
;
NDRADR:
       DW      00000H  ; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
NDNAMES:
       DB      64      ; MAX NUMBER OF DIRECTORY NAMES
DNFILE:
       DB      'NAMES   '      ; NAME OF DISK NAME FILE
       DB      'DIR'           ; TYPE OF DISK NAME FILE

;
;  REQUIREMENTS FLAGS
;
EPREQD:
       DB      000H    ; EXTERNAL PATH?
MCREQD:
       DB      0FFH    ; MULTIPLE COMMAND LINE?
MXREQD:
       DB      000H    ; MAX USER/DISK?
UDREQD:
       DB      000H    ; ALLOW USER/DISK CHANGE?
PUREQD:
       DB      000H    ; PRIVILEGED USER?
CDREQD:
       DB      000H    ; CURRENT INDIC AND DMA?
NDREQD:
       DB      000H    ; NAMED DIRECTORIES?
Z2CLASS:
       DB      0       ; CLASS 0
       DB      'ZCPR2'
       DS      10      ; RESERVED

;
;  END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
;
;******************************************************************
;

;
;  Start of Program
;
start:
       lda     mcavail ;multiple commands available?
       ora     a       ;0=no
       jz      mcerr
       call    codend  ;allocate buffer space
       shld    oldcmd  ;256 bytes for old command line
       lda     fcb+1   ;check for option char
       cpi     ' '     ;no option if <sp>
       jz      run     ;run command
       cpi     'S'     ;setup?
       jz      setup
       call    banner  ;print banner
       call    print   ;print help message
       db      cr,lf,'STARTUP is used to execute an initial set of commands'
       db      cr,lf,'  under ZCPR2 with Multiple Commands implemented.'
       db      cr,lf
       db      cr,lf,'STARTUP is invoked by one of the following command'
       db      cr,lf,'  lines:'
       db      cr,lf
       db      cr,lf,' STARTUP         <-- execute built-in commands'
       db      cr,lf,' STARTUP SETUP   <-- define built-in commands'
       db      cr,lf,'                     (only the S in SETUP is needed)'
       db      cr,lf,0
       ret
;
;  Multiple Command Line Buffer not Supported -- Fatal Error
;
mcerr:
       call    banner
       call    print
       db      cr,lf,'Multiple Command Line is not supported.'
       db      cr,lf,'STARTUP is based on the use of this buffer,'
       db      cr,lf,'and STARTUP cannot function without it.'
       db      cr,lf,'STARTUP is aborting.'
       db      cr,lf,0
       ret
;
;  Print Startup Banner
;
banner:
       call    print
       db      'STARTUP, Version '
       db      vers/10+'0','.',(vers mod 10)+'0'
       db      0
       ret

;
;  Run STARTUP Command Line
;
run:
       lhld    oldcmd  ;pt to save buffer
       xchg            ;... in DE
       lhld    mcadr   ;get base of command line
       mov     a,m     ;low-order address in A
       inx     h
       mov     h,m     ;high-order address in H
       mov     l,a     ;low-order address in L
run0:
       mov     a,m     ;get char
       stax    d       ;put it
       inx     h       ;pt to next
       inx     d
       ora     a       ;end of line?
       jnz     run0
       lhld    mcadr   ;pt to base address of command line
       push    h       ;save ptr
       lxi     d,4     ;pt to command line byte
       dad     d       ;hl pts to command line byte
       xchg            ;... de pts to it
       pop     h       ;get ptr to base
       mov     m,e     ;store address
       inx     h
       mov     m,d
       xchg            ;hl pts to first byte of command line
       shld    byte1   ;save ptr in case of error
       lxi     d,cmnd  ;pt to STARTUP Buffer
       push    h       ;save HL for now
       lhld    mcadr   ;address of multiple command line buffer
       inx     h       ;skip ptr
       inx     h       ;pt to buffer size
       mov     b,m     ;... in B
       pop     h       ;restore HL
       call    stline  ;store line
       jz      err     ;line too long?
       dcx     h       ;pt to ending null
       xchg
       lhld    oldcmd  ;pt to old command line
       xchg            ;... in DE
       call    stline
       jz      err     ;line too long?
       ret
err:
       call    banner
       call    print
       db      cr,lf,7,'** Command Line too Long -- Abort **',0
       lhld    byte1   ;clear line
       mvi     m,0
       ret
;
;  Store commands pted to by DE in buffer pted to by HL; B=space left in buffer
;
stline:
       ldax    d       ;get byte of command
       mov     m,a     ;store it
       inx     h       ;pt to next
       inx     d
       dcr     b       ;count down
       jz      stlerr
       ora     a       ;done?
       jnz     stline
       mvi     a,0ffh  ;set no error
       ora     a
       ret
stlerr:
       xra     a       ;error
       ret
;
;  STARTUP Setup Mode
;
setup:
       call    banner
cloop:
       call    print
       db      cr,lf,'STARTUP Setup Command (?=Help)? ',0
       call    capin   ;get response, capitalize, and echo
       cpi     'C'     ;define command line
       jz      setupc
       cpi     'D'     ;display values
       jz      setupd
       cpi     'X'     ;exit
       jz      setupx
       call    print   ;print help message
       db      cr,lf,'  Setup Mode Commands are --'
       db      cr,lf,' C -- Define STARTUP Multiple Command Line'
       db      cr,lf,' D -- Display STARTUP Values'
       db      cr,lf,' X -- Exit and Optionally Rewrite STARTUP'
       db      0
       jmp     cloop
;
;  Set STARTUP Multiple Command Line Buffer Contents
;
setupc:
       call    print
       db      cr,lf,' Current Multiple Command Buffer Contents is --',cr,lf,0
       lxi     h,cmnd  ;pt to line
       call    pstr
       call    print
       db      cr,lf,' New Line? ',0
       xra     a       ;no caps
       call    bbline  ;get line from user
       lxi     d,cmnd  ;pt to command line
copy:
       mov     a,m     ;get byte
       stax    d       ;put byte
       inx     h       ;pt to next
       inx     d
       ora     a       ;done?
       jnz     copy    ;fall thru to setupd to display result
;
;  Display Values
;
setupd:
       call    print
       db      cr,lf
       db      cr,lf,' Multiple Command Line --',cr,lf,'       --->',0
       lxi     h,cmnd  ;pt to buffer
       call    pstr    ;print it
       call    crlf    ;new line
       jmp     cloop   ;get next command

;
;  Exit to OS with optional rewrite of STARTUP.COM
;
setupx:
       call    print
       db      cr,lf,' Do you wish to update STARTUP (Y/N/<CR>=Y)? ',0
       call    capin   ;get response, capitalize, and echo
       cpi     'N'     ;no?
       rz              ;done if so
       call    print
       db      cr,lf,' STARTUP will write file to current disk/user',0
file:
       call    print
       db      cr,lf,' STARTUP File is ',0
       lxi     h,sfcb+1        ;pt to FN field
       call    prfn    ;print file name
       call    print
       db      cr,lf,' Enter New File Name or <CR> if OK: ',0
       mvi     a,0ffh  ;capitalize
       call    bbline  ;get line
       ora     a       ;any input?
       jz      write
       lxi     d,sfcb  ;pt to FCB
       call    fname   ;convert into FCB
       mov     a,b     ;anything other than default given?
       ana     c
       cpi     0ffh    ;must be FF if both defaults
       jz      file
       call    print
       db      cr,lf,' ** Disk or User Specification Ignored **',0
       jmp     file
prfn:
       mvi     b,8     ;8 chars
       call    prch
       mvi     a,'.'
       call    cout
       mvi     b,3     ;3 chars
prch:
       mov     a,m     ;get char
       call    cout    ;output it
       inx     h       ;pt to next
       dcr     b       ;count down
       jnz     prch
       ret
capin:
       call    cin     ;get response
       call    caps
       jmp     cout
;
;  Begin procedure to write file to disk
;
write:
       call    print
       db      cr,lf,' Writing File ',0
       lxi     h,sfcb+1        ;print file name
       call    prfn
       call    print
       db      ' to Disk ... ',0
       lxi     d,sfcb  ;pt to fcb
       call    initfcb ;init it
       call    f$delete        ;delete it
       call    initfcb ;reinit it
       call    f$make  ;create file
       cpi     0ffh    ;error?
       jz      derr
       call    codend  ;get end of code
       call    shftlh  ;shift HL left 1 bit so we have a block (128 byte)
                       ;count
       mov     b,h     ;count in b
       lxi     h,100h  ;pt to start of program
writel:
       xchg            ;de is dma address
       push    h       ;save HL
       mvi     c,26    ;set dma address
       call    bdos
       lxi     h,80h   ;pt to next block
       dad     d
       pop     d       ;get de (ptr to sfcb), hl pts to next block
       call    f$write ;write block to disk
       ora     a       ;0=ok
       jnz     derr
       dcr     b       ;count down
       jnz     writel
       call    f$close ;close file
       call    print
       db      'Done',0
       ret
derr:
       call    print
       db      cr,lf,' Disk Output Error -- Aborting',0
       ret

;
;  Buffers
;
oldcmd:
       ds      2       ;original command line
byte1:
       ds      2       ;ptr to first byte
cmnd:
       db      0       ;empty line initially
       ds      256     ;buffer for command line

;  FCB to write STARTUP to
sfcb:
       db      0       ;current disk
       db      'STARTUP COM'
       ds      4
       ds      16
       ds      4

       end