;
;  Program:  LD
;  Author:  Richard Conn
;  Version:  1.1
;  Date:  6 Jan 83
;  Previous Versions:  1.0 (6 Dec 82)
;
;       LD Loads the named Directory file (LD=Load Directory) NAMES.DIR or
; that file specified in the command line into the memory-resident directory
; buffer.  It also has the capability of displaying the contents of this
; buffer to the user.  Forms of this command are:
;
;               LD              <-- Display Loaded Directory
;               LD filename     <-- Load Directory filename.DIR
;               LD filename.typ <-- Load Directory filename.typ
;               LD //           <-- Ask for Help
;
vers    equ     11

;
;       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.
;


;
;  Constants
;
cr      equ     0dh
lf      equ     0ah
tfcb    equ     5ch     ; ZCPR2 FCB

;
;  Externals
;
       ext     zgpins  ; installation program
       ext     zfninit ; reinit NAMES.DIR
       ext     zdname  ; load names into buffer
       ext     codend  ; end of code
       ext     moveb   ; move routine
       ext     print   ; print routine
       ext     padc    ; print A as decimal chars
       ext     cout    ; output char
       ext     crlf    ; new line
       ext     retud   ; return current user/disk

;
;  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      0FFH    ; 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      0FFH    ; EXTERNAL PATH?
MCREQD:
       DB      000H    ; MULTIPLE COMMAND LINE?
MXREQD:
       DB      0FFH    ; MAX USER/DISK?
UDREQD:
       DB      000H    ; ALLOW USER/DISK CHANGE?
PUREQD:
       DB      000H    ; PRIVILEGED USER?
CDREQD:
       DB      000H    ; CURRENT INDIC AND DMA?
NDREQD:
       DB      0FFH    ; NAMED DIRECTORIES?
Z2CLASS:
       DB      0       ; CLASS 0
       DB      'ZCPR2'
       DS      10      ; RESERVED

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

;
;  Start of Program
;
start:
       call    zgpins  ; init ZCPR2 routines
       call    retud   ; get current user number
       mov     a,b     ; save current disk number away
       sta     cdisk
       mov     a,c     ; save current user number away
       sta     cuser

       call    print
       db      'LD  Version '
       db      (vers/10)+'0','.',(vers mod 10)+'0',0

       lhld    ndradr  ; check for facility support in the first place
       mov     a,h
       ora     l       ; HL=0 if no facilities for mem-based named dirs
       jnz     start0
       call    print
       db      cr,lf,'Memory-Based Named Directories Not Supported'
       db      cr,lf,'on this System -- Aborting',0
       ret

start0:
       lxi     h,tfcb+1        ; pt to first byte of file name
       mov     a,m     ; get it
       cpi     ' '     ; display loaded directory if no file name given
       jz      ldisp
       cpi     '/'     ; option?
       jnz     start1  ; load directory if file specified

       call    print
       db      cr,lf,' LD is the Load Directory program for ZCPR2.'
       db      cr,lf,'The functions of LD are to load the memory-resident'
       db      cr,lf,'named directory buffer from the specified or implied'
       db      cr,lf,'disk file and to display the contents of the named'
       db      cr,lf,'directory buffer.'
       db      cr,lf
       db      cr,lf,' The forms of the LD command are --',cr,lf
       db      cr,lf,'         LD              <-- Display Loaded Directory'
       db      cr,lf,'         LD filename     <-- Load filename.DIR'
       db      cr,lf,'         LD filename.typ <-- Load filename.typ'
       db      cr,lf,'         LD //           <-- Print this Help Message'
       db      cr,lf,0
       ret

;
;  Process Load Function
;
start1:
       lxi     d,8     ; pt to file type
       dad     d
       mov     a,m     ; get first char of file type
       cpi     ' '     ; any file type?
       jnz     setname ; yes, so user file given totally
       lxi     d,dirtyp        ; set file type to DIR
       xchg            ; copy type into TFCB
       mvi     b,3     ; 3 bytes
       call    moveb
setname:
       lxi     d,tfcb  ; pt to FCB
       mvi     a,80h   ; only set FCB
       call    zfninit ; set new NAMES.DIR file
       call    codend  ; get end of code
       call    zdname  ; load NAMES.DIR file (or user file)
       jz      loaderr ; load error
       lhld    ndradr  ; pt to named directory buffer
       mov     a,m     ; get limit
       cmp     c       ; within range?
       jnc     load1
       call    print
       db      cr,lf,'Load Error -- Not Enough Room in Memory Buffer'
       db      cr,lf,'for Directory Names -- Aborting',0
       ret
loaderr:
       call    print
       db      cr,lf,'Load Error -- File Not Found -- Aborting',0
       ret
load1:
       inx     h       ; pt to dir size
       mov     m,c     ; set dir size
       inx     h       ; pt to first byte of first entry
       xchg            ; ... in DE
       call    codend  ; pt to first loaded byte in HL
load2:
       mvi     b,10    ; 10 bytes/entry
load3:
       mov     a,m     ; get byte
       stax    d       ; put byte
       inx     h       ; pt to next
       inx     d
       dcr     b       ; count down
       jnz     load3
       dcr     c       ; count down entries
       jnz     load2
       call    print
       db      cr,lf,'Load Complete',0
       ret

;
;  Display Contents of Loaded Directory
;
ldisp:
       lhld    ndradr  ; get address
       call    print
       db      cr,lf,'**********************************************'
       db      cr,lf,'** Memory-Based Named Directory Definitions **'
       db      cr,lf,'** Number of Entries Permitted: ',0
       mov     a,m     ; get count
       call    padc    ; print as decimal
       call    print
       db      '         **'
       db      cr,lf,'** Number of Entries Loaded: ',0
       inx     h       ; pt to count
       mov     a,m     ; get count
       call    padc
       call    print
       db      '            **'
       db      cr,lf,'**********************************************',0
       ora     a       ; any entries?
       jnz     ldisp0
       call    print
       db      cr,lf,' -- No Named Directories Loaded --',0
       ret
ldisp0:
       call    print
       db      cr,lf,' -- Named Directory Display --',0
       inx     h       ; pt to first entry
       mov     b,a     ; count in B
       mvi     c,0ffh  ; set current disk indicator to nothing
       mvi     d,0     ; set entry counter
ldisp1:
       mov     a,m     ; get next disk
       cmp     c       ; same as current indicator?
       jz      ldisp2  ; process if same
       mov     c,a     ; set new disk
       call    crlf    ; new line
       adi     'A'     ; convert to letter
       call    cout
       call    print
       db      ' --',0
       mvi     d,0ffh  ; set for increment to zero
ldisp2:
       inx     h       ; pt to user number
       lda     puser   ; get priv user number
       dcr     a       ; back up to last non-priv number
       cmp     m       ; compare to entry
       jnc     ldisp3  ; go ahead and display if non-priv number
       push    b       ; save BC
       lda     cuser   ; get current user
       mov     b,a     ; ... in B
       lda     puser   ; check for privileged user
       dcr     a       ; set top of non-priv users
       cmp     b       ; privileged?
       pop     b       ; restore BC
       jc      ldisp3  ; privileged
       mov     a,l     ; pt to next entry
       adi     9       ; 9 bytes to next entry
       mov     l,a
       mov     a,h
       aci     0
       mov     h,a
       jmp     ldisp5
ldisp3:
       inr     d       ; increment entry counter
       mov     a,d     ; get count
       ani     3       ; check for 4th
       cz      crlf
       mov     a,m     ; get user number
       call    padc    ; print user number as decimal chars
       mvi     a,':'   ; print colon
       call    cout
       mvi     a,' '   ; print space
       call    cout
       inx     h       ; pt to first char of name
       mvi     e,8     ; print 8-char name
ldisp4:
       mov     a,m     ; get char of dir name
       call    cout
       inx     h       ; pt to next
       dcr     e       ; count down
       jnz     ldisp4
ldisp5:
       dcr     b       ; count down
       jnz     ldisp1
       call    print
       db      cr,lf,cr,lf,'** Current Directory **',cr,lf,'   ',0
       lhld    ndradr  ; get address of buffer
       inx     h       ; pt to entry count
       mov     b,m     ; get entry count
       inx     h       ; pt to first entry
cdisp:
       mov     c,m     ; get next disk number
       inx     h       ; pt to user number
       lda     cdisk   ; compare to current disk
       cmp     c
       jnz     cdisp2  ; skip if no match
       lda     cuser   ; compare current user
       cmp     m       ; to user pted to
       jnz     cdisp2  ; skip if no match
       inx     h       ; we have found it, so pt to first char
       lda     cdisk   ; print current disk letter
       adi     'A'
       call    cout
       lda     cuser   ; print current user number
       call    padc
       mvi     a,':'   ; print separator
       call    cout
       mvi     a,' '
       call    cout
       mvi     b,8     ; print 8 chars
cdisp1:
       mov     a,m     ; get char
       call    cout    ; print char
       inx     h       ; pt to next
       dcr     b       ; count down
       jnz     cdisp1
       ret
cdisp2:
       lxi     d,9     ; skip to next entry
       dad     d
       dcr     b       ; count down
       jnz     cdisp
       call    print
       db      'Not Named in Directory Buffer',0
       ret

;
;  Buffers
;
cdisk:  ds      1       ; current disk number
cuser:  ds      1       ; current user number
dirtyp: db      'DIR'   ; type of Directory file

       end