;
;  PROGRAM:  DEVICE3
;  AUTHOR:  RICHARD CONN
;  VERSION:  1.0
;  DATE:  4 Apr 84
;  PREVIOUS VERSION:  None
;  DERIVATION:  DEVICE2 from ZCPR2
;
VERS    EQU     10
z3env   SET     0f400h

;
;       DEVICE is a program which enables the user to manipulate the
; extended ZCPR3 redirectable device drivers.  It allows the user to
; perform the following functions:
;
;               o Display the Names of the Current Devices
;               o Set One or More of the Current Devices
;               o Ask for Help
;
;       The format of the DEVICE command is:
;
;               DEVICE          <-- Enter Interactive Mode
;               DEVICE //       <-- Ask for Help
;
;       In Interactive Mode, DEVICE commands are:
;
;               DISPLAY ALL     <-- Display Names of All Devices
;               DISPLAY CON     <-- Display Names of Consoles
;               DISPLAY LST     <-- Display Names of Printers
;               DISPLAY RDR     <-- Display Names of Readers
;               DISPLAY PUN     <-- Display Names of Punches
;
;               CON: name       <-- Select Console
;               LST: name       <-- Select Printer
;               RDR: name       <-- Select Reader
;               PUN: name       <-- Select Punch
;

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

;
;  SYSLIB Routines
;
       ext     z3init,getiop
       ext     cin,cout,epstr,eprint,cline,bline,codend,caps

;
; Environment Definition
;
       if      z3env ne 0
;
; External ZCPR3 Environment Descriptor
;
       jmp     start
       db      'Z3ENV' ;This is a ZCPR3 Utility
       db      1       ;External Environment Descriptor
z3eadr:
       dw      z3env
start:
       lhld    z3eadr  ;pt to ZCPR3 environment
;
       else
;
; Internal ZCPR3 Environment Descriptor
;
       MACLIB  Z3BASE.LIB
       MACLIB  SYSENV.LIB
z3eadr:
       jmp     start
       SYSENV
start:
       lxi     h,z3eadr        ;pt to ZCPR3 environment
       endif

;
; Start of Program -- Initialize ZCPR3 Environment
;
       call    z3init  ;initialize the ZCPR3 Env and the VLIB Env

;
;  Start of Program
;

       call    getiop  ;check for initialization
       mov     a,h
       ora     l       ;must NOT be zero
       jnz     start0
       call    banner
       call    eprint
       db      cr,lf,'DEVICE NOT Initialized with I/O Base',0
abort:
       call    eprint
       db      ' -- Aborting',0
       ret

start0:
       call    status  ;check for drivers
       jnz     start1
       call    banner
       call    eprint
       db      cr,lf,'Redirection Not Supported',0
       jmp     abort

start1:
       lda     fcb+1   ;get first char of argument
       cpi     '/'     ;help?
       jnz     command ;run command subroutine

;
;  Print Help Message
;
help:
       call    banner
       call    eprint
       db      cr,lf,'DEVICE - Interactive Redirectable I/O Driver Selection'
       db      cr,lf,'Syntax:'
       db      cr,lf,'   DEVICE      <-- Enter Interactive Mode'
       db      cr,lf,'   DEVICE //   <-- Print Help Message'
       db      0
       ret
;
; Print General Help Message
;
genhelp:
       call    eprint
       db      'Enter Command Character:'
       db      cr,lf,'  D - Display all or selected devices'
       db      cr,lf,'  C - Select Console Device'
       db      cr,lf,'  L - Select List Device'
       db      cr,lf,'  P - Select Punch Device'
       db      cr,lf,'  R - Select Reader Device'
       db      cr,lf,'  X - Exit Program'
       db      0
       ret
;
; Print Display Help Message
;
disphelp:
       call    eprint
       db      cr,lf,'Enter Devices to Display:'
       db      cr,lf,'  A - All'
       db      cr,lf,'  C - Consoles'
       db      cr,lf,'  L - Lists'
       db      cr,lf,'  P - Punches'
       db      cr,lf,'  R - Readers'
       db      0
       ret
;
; Print Banner
;
banner:
       call    eprint
       db      'DEVICE3, Version '
       db      (vers/10)+'0','.',(vers mod 10)+'0',0
       ret
;
;  Skip to Non-Blank Routine
;
sblank:
       mov     a,m     ;get char
       inx     h       ;pt to next
       cpi     ' '     ;blank?
       jz      sblank  ;continue if so
       dcx     h       ;pt to non-blank
       ret

;
;  COMMAND -- This is an interactive mainline which allows user input,
;    runs command lines via DOCMD, and permits Help and Comments
;
command:
       call    banner
       call    eprint
       db      ' - Interactive I/O Device Selection Utility'
       db      cr,lf,'Strike ? for Help'
       db      0
cloop:
       call    eprint
       db      cr,lf,'DEVICE3 Command? ',0
       lxi     h,majcmd        ;process major command
       call    ccheck  ;look for and run command
       mov     a,b     ;get char
       call    cout    ;echo it
       call    eprint
       db      ' - Invalid Command',0
       jmp     cloop
;
; Command Table for Major Commands
;
majcmd:
       db      '?'     ;help
       dw      genhelp
       db      ' '     ;skip command
       dw      exit1
       db      cr      ;skip command
       dw      exit1
       db      'D'     ;display devices
       dw      display
       db      'C'     ;Select Console
       dw      console
       db      'L'     ;Select List
       dw      list
       db      'P'     ;Select Punch
       dw      punch
       db      'R'     ;Select Reader
       dw      reader
       db      'X'     ;Exit
       dw      exit
       db      0       ;end of table
;
; Display major command
;
display:
       pop     psw     ;clear return address
       call    eprint
       db      'Display Devices for ',0
       lxi     h,discmd        ;table of display commands
       call    ccheck
       mov     a,b
       call    cout    ;print error command
       call    eprint
       db      ' - Invalid Command',cr,lf,0
       jmp     display
;
; Display Command Table
;
discmd:
       db      '?'     ;help
       dw      disphelp
       db      cr      ;exit
       dw      exit1
       db      ' '     ;exit
       dw      exit1
       db      'A'     ;all
       dw      dispall
       db      'C'     ;console
       dw      dispcon
       db      'L'     ;list
       dw      displst
       db      'P'     ;punch
       dw      disppun
       db      'R'     ;reader
       dw      disprdr
       db      0       ;end of table

;
; Console major command
;
console:
       call    eprint
       db      'Select Console ',0
       call    getname
       mvi     a,0     ;select CON:
       jmp     assign
;
; List major command
;
list:
       call    eprint
       db      'Select List ',0
       call    getname
       mvi     a,3     ;select LST:
       jmp     assign
;
; Punch major command
;
punch:
       call    eprint
       db      'Select Punch ',0
       call    getname
       mvi     a,2     ;select PUN:
       jmp     assign
;
; Reader major command
;
reader:
       call    eprint
       db      'Select Reader ',0
       call    getname
       mvi     a,1     ;select RDR:
       jmp     assign
;
; Exit major command
;
exit:
       call    eprint
       db      'Exit',0
       pop     psw     ;clear stack
exit1:
       ret             ;exit to OS or DEVICE (if entry at EXIT1)
;
; Check for Command in A in Table Pted to by HL
;
ccheck:
       call    cin     ;get user input
       call    caps    ;capitalize it
       mov     b,a     ;save command in B
cc1:
       mov     a,m     ;get command letter
       ora     a       ;end of table?
       rz
       cmp     b       ;match?
       jz      cc2
       inx     h       ;skip to next
       inx     h
       inx     h
       jmp     cc1
cc2:
       inx     h       ;pt to address
       mov     e,m     ;get low
       inx     h
       mov     d,m     ;get high
       lxi     h,cloop ;set return address
       xthl            ;return address on stack
       xchg            ;address of routine in HL
       pchl            ;"call" routine
;
; Get Device Name from User
;   Return with NZ if name input, else reissue command
;
getname:
       call    eprint
       db      ' [Enter a Device Name] ',0
       call    codend  ;pt to end of available code
       mvi     m,20    ;set length of line
       mvi     a,0ffh  ;capitalize
       call    bline
       call    sblank  ;skip to non-blank
       mov     a,m     ;empty line?
       ora     a       ;0=yes
       jz      gnabort ;abort input if so
       shld    name    ;set ptr to name
       ret             ;NZ means name present
gnabort:
       pop     psw     ;clear stack
       ret             ;return to main command processor

;
;  Do Assignment in General
;
assign:
       mov     b,a     ;save A in B
       sta     logical ;save logical device number
       inr     b       ;add 1 for offset
       call    status  ;get device status
       dcx     h       ;pt to previous
       dcx     h
asgn1:
       inx     h       ;pt to next
       inx     h
       dcr     b       ;count down
       jnz     asgn1
       mov     c,m     ;get number of devices in C
       mov     a,c     ;check for value of zero
       ora     a
       jnz     asgn2
       call    eprint
       db      cr,lf,' Invalid Device Name: ',0
       lhld    name    ;pt to error name
       call    epstr   ;print name
       ret
asgn2:
       lda     logical ;get logical device number
       mov     b,a     ;... in B
       push    b       ;save device count
       dcr     c       ;pt to previous
       call    namer   ;get name
       xchg            ;name pted to by DE
       lhld    name    ;user's name pted to by HL
asgn3:
       ldax    d       ;get name of device
       cpi     ' '+1   ;done?
       jc      asgn3a
       cmp     m       ;compare to user
       jnz     asgn4
       inx     h       ;pt to next
       inx     d
       jmp     asgn3
asgn3a:
       mov     a,m     ;get user
       cpi     ' '+1   ;done?
       jc      asgn3b
       cpi     ','     ;done?
       jnz     asgn4
asgn3b:
       pop     b       ;match -- C-1 is selected device
       dcr     c       ;decrement
       call    select  ;select device
       lda     logical ;get logical device in A
       call    curr    ;print name of device selected
       lhld    name    ;pt to name for scan continuation
       ret
asgn4:
       pop     b       ;count down
       dcr     c       ;count down
       jnz     asgn2   ;continue
       lhld    name    ;pt to invalid name
       call    eprint
       db      cr,lf,'Invalid Name at -- ',0
       call    epstr
       lhld    name    ;pt to name for scan continuation
       ret

;
; Display Devices
;
dispall:
       call    eprint
       db      'All Devices',cr,lf
       db      ' CON: Devices --',0
       call    dc1     ;successive displays
       call    eprint
       db      cr,lf,' RDR: Devices --',0
       call    dr1
       call    eprint
       db      cr,lf,'Strike Any Key -- ',0
       call    cin
       call    eprint
       db      cr,lf,' PUN: Devices --',0
       call    dp1
       call    eprint
       db      cr,lf,' LST: Devices --',0
       jmp     dl1
dispcon:
       call    eprint
       db      'CON: Devices',0
dc1:
       mvi     a,0     ;select CON:
       call    disp
       jmp     curr
displst:
       call    eprint
       db      'LST: Devices',0
dl1:
       mvi     a,3     ;select LST:
       call    disp
       jmp     curr
disprdr:
       call    eprint
       db      'RDR: Devices',0
dr1:
       mvi     a,1     ;select RDR:
       call    disp
       jmp     curr
disppun:
       call    eprint
       db      'PUN: Devices',0
dp1:
       mvi     a,2     ;select PUN:
       call    disp
;
;  Print Name of Current Device
;
curr:
       push    h       ;save ptr
       mov     b,a     ;save number in B
       push    b       ;save B
       call    eprint
       db      cr,lf,' Current Assignment: ',0
       push    b       ;save B
       call    status  ;get status
       pop     b       ;get B
       inr     b       ;add 1 for offset
       dcx     h       ;back up
curr1:
       inx     h       ;pt to next
       inx     h
       dcr     b       ;count down
       jnz     curr1
       pop     b       ;get logical number in B
       mov     c,m     ;get physical number in C
       call    pname0  ;print first part of name only
       pop     h       ;get ptr
       ret
;
;  Print Names of All Physical Devices for a Logical Device
;
disp:
       push    h       ;save char ptr
       push    psw     ;save device number
       mov     b,a     ;logical device in B
       push    b       ;save for later
       push    b       ;save it
       call    status  ;get status report
       pop     b       ;get logical device number
       inr     b       ;add 1 for offset
       dcx     h       ;back up
       dcx     h
disp1:
       inx     h       ;pt to next
       inx     h
       dcr     b       ;count down
       jnz     disp1
       pop     b       ;get B back
       mov     c,m     ;get count of devices
       mov     a,c     ;check for none
       ora     a
       jz      disp3
disp2:
       push    b       ;save values
       dcr     c       ;pt to next name
       call    eprint
       db      cr,lf,'    ',0
       call    pnamer  ;print name (B=logical, C=physical)
       pop     b       ;get count
       dcr     c       ;count down
       jnz     disp2
disp3:
       pop     psw
       pop     h
       ret
;
;  Routine to Print Name of Selected Device
;       B=logical number, C=physical number
;
pnamer:
       push    b       ;save BC
       call    pname0  ;print first part of name
       call    eprint  ;print separator
       db      ' - ',0
       call    epstr   ;print rest as string
       pop     b       ;restore BC
       ret
;
;  Print first part of selected device name
;
pname0:
       call    namer   ;get ptr to string
       mvi     b,8     ;at most 8 chars
pname1:
       mov     a,m     ;get char
       inx     h       ;pt to next char
       cpi     ' '     ;end of name?
       jz      pname2
       call    cout    ;print char
       dcr     b       ;count down
       jnz     pname1
       ret
pname2:
       mvi     a,' '   ;print spaces
       call    cout
       dcr     b       ;count down
       jnz     pname2
       ret

;
;  Basic Interface Routines
;
status:
       lxi     d,0     ;Offset 0
runit:
       call    getiop  ;device driver base
       dad     d
       pchl
select:
       lxi     d,3     ;Offset 3
       jmp     runit
namer:
       lxi     d,6     ;Offset 6
       jmp     runit

;
;  Buffers
;
logical:
       ds      1       ;Logical Device Number
name:
       ds      2       ;Pointer to User-Supplied Name

       end