;
;  PROGRAM:  TINIT
;  VERSION:  2.1
;  AUTHOR:  RICHARD CONN
;  DATE:  25 June 83
;  DERIVATION:  TINIT.C, VERSION 1.1
;  PREVIOUS VERSIONS:  2.0 (1 Jan 83)
;
vers    equ     21

;
;       TINIT inits the TVI 950 terminal from a config file, optionally
; specified by the user.  The Config file is created by CONFIG.  TINIT
; will search along the command-search path for an indicated or default
; file, load it, and program the TVI 950 from it.
;
;       TINIT assumes that X-ON/X-OFF flow control is enabled in the
; TVI 950.  It uses this to ensure that the commands are not sent to
; the terminal too quickly.
;
;       TINIT is invoked by the following forms:
;               TINIT           <-- Program using STD.CFG
;               TINIT file      <-- Program using file.CFG
;               TINIT file.typ  <-- Program using file.typ
;               TINIT //        <-- Print Help Message
;

;
;  CP/M Constants
;
cpm     equ     0       ; base of system
fcb     equ     cpm+5ch
tbuff   equ     cpm+80h
xoff    equ     13h     ; ^S=X-OFF
cr      equ     0dh
lf      equ     0ah
esc     equ     1bh     ; ESCAPE code for CRT Programming
delay   equ     200h    ; long delay for TVI 950 to accept command
tablen  equ     80      ; length of tab buffer
ullen   equ     81      ; length of user line buffer
fkeylen equ     464     ; length of function key buffer

;
;  SYSLIB Routines
;
       ext     zpfind,zgpins,cst,cin,cout,crlf,print,pause,moveb
       ext     getud,logud,putud
       ext     codend,initfcb,fi0$open,f0$get,fi0$close

;
;  TVI 950 Commands
;
clear   equ     '+'     ; clear screen

fctkey  equ     '|'     ; begin function key defn
fctend  equ     'Y'-'@' ; end function key defn

loadusr equ     'f'     ; load user line
dispusr equ     'g'     ; display user line

sscroll equ     '8'     ; smooth scroll
hscroll equ     '9'     ; hard scroll

tabclr  equ     '3'     ; all tab clear
tabset  equ     '1'     ; set tab at cursor

vidnorm equ     'd'     ; normal video
vidrev  equ     'b'     ; reverse video

clkon   equ     '>'     ; key click on
clkoff  equ     '<'     ; key click off

curs    equ     '.'     ; define cursor type

;
;  General Init Settings
;
cls     equ     '+'     ; clear screen
unlock  equ     '"'     ; unlock keyboard
nograph equ     '%'     ; no graphics
noprot  equ     27h     ; protect mode off
normi   equ     '('     ; normal intensity
notabs  equ     '3'     ; clear all tabs
noclick equ     '<'     ; key click off
nocopy  equ     'A'     ; copy print mode off
cmode   equ     'C'     ; conversation mode on
fdx     equ     'F'     ; full duplex
nomonit equ     'X'     ; clear monitor mode
nobufpr equ     'a'     ; buffer print off
vid1    equ     'd'     ; white on black
nopage  equ     'w'     ; auto page off

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

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

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

;
;  Default Name of CFG File
;
speed:
       db      4               ; 4 MHz
cfgfile:
       db      'STD     '      ; may be changed by GENINS
       db      'CFG'

;
;  Start of Program
;
start:
       call    zgpins  ; init ZCPR2 buffers

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

;
;  Allocate Buffer Space
;
       call    codend          ; get start of buffer
       shld    ulbuffer        ; start of underline buffer
       lxi     d,ullen         ; buffer is ullen bytes
       dad     d
       shld    tabbuffer       ; start of tab buffer
       lxi     d,tablen        ; buffer is tablen bytes
       dad     d
       shld    fkeybuffer      ; start of function key buffer

;
;  Copy Default File Name into FCB
;
       lxi     h,cfgfile       ; pt to default name
       lxi     d,cfgfcb+1      ; pt to FCB
       mvi     b,11            ; 11 bytes
       call    moveb

;
;  Check for file name
;
       lda     fcb+1   ; check for file name
       cpi     ' '     ; <SP> if none
       jz      program ; program from default FCB
       cpi     '/'     ; help?
       jnz     start1

;
;  Print Help Message
;
       call    print
       db      cr,lf,' TINIT is used to program a TVI 950 CRT from a'
       db      cr,lf,'Configuration File (CFG File) created by the CONFIG'
       db      cr,lf,'Program.  TINIT is invoked in the following ways --'
       db      cr,lf
       db      cr,lf,'         TINIT           <-- Program from Default'
       db      cr,lf,'         TINIT file      <-- Pgm from file.CFG'
       db      cr,lf,'         TINIT file.typ  <-- Pgm from file.typ'
       db      cr,lf,'         TINIT //        <-- Print Help'
       db      cr,lf,0
       ret

;
;  Process File Name
;
start1:
       lxi     h,fcb+1         ; copy file name part
       lxi     d,cfgfcb+1      ; copy into CFGFCB
       mvi     b,8             ; 8 bytes
       call    moveb
       lxi     h,fcb+9         ; pt to file type
       lxi     d,cfgfcb+8      ; prepare to copy file type
       mvi     b,3             ; 3 bytes
       mov     a,m             ; any specified?
       cpi     ' '             ; default type if space
       cnz     moveb

;
;  Load Config File and Program TVI 950
;
program:
       lxi     d,cfgfcb        ; pt to fcb
       call    initfcb         ; init it
       mvi     b,0ffh          ; search current dir first
       call    zpfind          ; look for file
       jnz     prog1
       call    print
       db      cr,lf,'Configuration File ',0
       xchg                    ; HL pts to config file
       inx     h               ; pt to file name
       call    prfn            ; print name
       call    print
       db      ' Not Found',0
       jmp     cpm

;
;  Load File Buffer into Files
;
prog1:
       call    print
       db      cr,lf,'Programming TVI 950 from File ',0
       mov     h,d             ; ptr to fcb in HL also
       mov     l,e
       inx     h
       call    prfn            ; print file name
       call    crlf            ; new line
       call    putud
       call    logud           ; log into directory
       call    fi0$open        ; open file for input
       call    getch           ; read char
       sta     cursor          ; set cursor type
       call    getch
       sta     ffkeys          ; set function key flag
       call    getch
       sta     click           ; set key click
       call    getch
       sta     scroll          ; set scrolling
       call    getch
       sta     ftabs           ; set tab program flag
       call    getch
       sta     fuline          ; set user line program flag
       call    getch
       sta     video           ; set video type
       call    getch           ; flush <CR> <LF>
       call    getch
       lhld    ulbuffer        ; load user line if specified
       lxi     d,ullen         ; size of buffer
       lda     fuline
       ora     a               ; 0=no
       cnz     readbuffer      ; read buffer if yes
       lhld    tabbuffer       ; load tab line if specified
       lxi     d,tablen        ; size of buffer
       lda     ftabs
       ora     a
       cnz     readbuffer
       lhld    fkeybuffer      ; program function keys if specified
       lxi     d,fkeylen       ; size of buffer
       lda     ffkeys
       ora     a
       cnz     readbuffer
       call    fi0$close       ; close file
       call    getud           ; restore original user/disk

;
;  Send Out All Terminial Initializations
;
       mvi     a,unlock        ; unlock keyboard
       call    cmnd
       mvi     a,nograph       ; no graphics
       call    cmnd
       mvi     a,noprot        ; protect off
       call    cmnd
       mvi     a,normi         ; normal intensity
       call    cmnd
       mvi     a,notabs        ; no tabs
       call    cmnd
       mvi     a,noclick       ; no key click
       call    cmnd
       mvi     a,nocopy        ; no copy print mode
       call    cmnd
       mvi     a,cmode         ; conversation mode on
       call    cmnd
       mvi     a,fdx           ; full duplex
       call    cmnd
       mvi     a,nomonit       ; no monitor mode
       call    cmnd
       mvi     a,nobufpr       ; no buffer print
       call    cmnd
       mvi     a,vid1          ; white on black
       call    cmnd
       mvi     a,nopage        ; auto page off
       call    cmnd
       lxi     h,videom        ; normal video
       call    cmnds
       lxi     h,insert        ; set insert char to space
       call    cmnds
;
;  Program Cursor Type
;
       mvi     a,curs
       call    cmnd
       lda     cursor          ; cursor type
       call    coutx
;
;  Program Function Keys
;
       lda     ffkeys          ; any function keys?
       ora     a               ; 0=no
       jz      setclick
       mvi     b,22            ; 22 keys to program
       lhld    fkeybuffer      ; pt to buffer
       mvi     a,'1'           ; set for first function key
       sta     fkey
nxtkey:
       mov     a,m             ; get first char
       ora     a               ; no string?
       jz      nkey1
       push    h               ; save ptr to first char
       mvi     a,fctkey        ; function key follows
       call    cmnd
       lda     fkey            ; print function key
       call    coutx
       call    pstr            ; print string pted to by HL
       mvi     a,fctend        ; end function
       call    coutx
       pop     h               ; get ptr to first char
nkey1:
       lxi     d,20            ; pt to next function key
       dad     d
       lda     fkey            ; increment function key
       inr     a
       sta     fkey
       dcr     b               ; count down
       jnz     nxtkey
       call    sleep

;
;  Set Key Click
;
setclick:
       lda     click           ; from file
       call    cmnd

;
;  Set Scrolling
;
       lda     scroll          ; from file
       call    cmnd

;
;  Set Tabs
;
       lda     ftabs           ; set tabs?
       ora     a               ; 0=no
       jz      setul
       mvi     a,tabclr        ; clear all tab stops
       call    cmnd
       call    crlf            ; new line
       lhld    tabbuffer       ; pt to buffer
       mvi     b,tablen        ; tablen chars in buffer
settabs:
       mov     a,m             ; get buffer char
       inx     h               ; pt to next
       cpi     '.'             ; dot means set tab here
       jnz     stabs1
       mvi     a,tabset        ; set tab
       call    cmnd
stabs1:
       mvi     a,' '           ; space over
       call    coutx
       dcr     b               ; count down
       jnz     settabs
       call    crlf            ; new line

;
;  Set User Line
;
setul:
       lda     fuline          ; get flag
       ora     a               ; 0=no
       jz      setvideo
       mvi     a,loadusr       ; load user line
       call    cmnd
       lhld    ulbuffer        ; print buffer contents
       call    pstr
       mvi     a,cr            ; send just <CR>
       call    coutx
       mvi     a,dispusr       ; display user line
       call    cmnd
       call    sleep
;
;  Set Video
;
setvideo:
       lda     video           ; get command
       call    cmnd

;
;  Done -- Clear Screen and Return to OS
;
       mvi     a,cls           ; clear screen
       call    cmnd
       ret

;
;  Write Single-Char Command in A
;
cmnd:
       push    psw             ; save command
       mvi     a,esc
       call    coutx           ; send ESC
       pop     psw
       call    coutx           ; send char
       ret

;
;  Write String Command pted to by HL
;
cmnds:
       mvi     a,esc           ; send ESC
       call    coutx           ; and fall thru to pstr
;
;  Write String Pted to by HL
;
pstr:
       push    h               ; save HL
pstr1:
       mov     a,m             ; get char
       ora     a               ; done?
       jz      pstr2
       inx     h               ; pt to next
       call    coutx           ; send char
       jmp     pstr1
pstr2:
       pop     h               ; get HL
       ret
;
;  Print File Name pted to by HL
;
prfn:
       push    b               ; save BC
       mvi     b,8
       call    prfn1           ; print name part
       mvi     a,'.'
       call    coutx
       mvi     b,3             ; print type
       call    prfn1
       pop     b               ; restore BC
       ret
prfn1:
       mov     a,m             ; get char
       call    coutx           ; print char
       inx     h               ; pt to next
       dcr     b               ; count down
       jnz     prfn1
       ret

;
;  Sleep 0.1 secs
;
sleep:
       push    h               ; save regs
       push    b
       push    psw
       lda     speed           ; get processor speed
       mov     b,a             ; ... in B
       lxi     h,1             ; 0.1 secs
       call    pause
       pop     psw             ; restore regs
       pop     b
       pop     h
       ret

;
;  Output Char in A to Console, but Check for X-OFF first
;
coutx:
       push    psw     ; save char
       call    cst     ; char pending?
       ora     a       ; nz=not rda
       jnz     coutx1
       call    cin     ; get char
       cpi     xoff    ; pause?
       jnz     coutx1
       call    cin     ; accept any char for continue
coutx1:
       pop     psw     ; get char
       jmp     cout    ; send it

;
;  Get Char from File with Possible Abort
;
getch:
       call    f0$get          ; get char
       rz                      ; char OK
       call    print
       db      cr,lf,'File Read Error -- Aborting',0
       jmp     cpm

;
;  Read into buffer pted to by HL for DE bytes
;
readbuffer:
       call    getch           ; get byte from file
       mov     m,a             ; put byte
       inx     h               ; pt to next
       dcx     d               ; count down
       mov     a,d             ; done?
       ora     e
       jnz     readbuffer
       call    getch           ; flush <CR> <LF>
       jmp     getch

;
;  Some Command Strings
;
videom:
       db      'G0',0
insert:
       db      'e ',0

;
;  Buffers
;
cursor: ds      1
fuline: ds      1
video:  ds      1
ftabs:  ds      1
fkey:   ds      1
click:  ds      1
scroll: ds      1
ffkeys: ds      1
ulbuffer:
       ds      2       ; ptr
tabbuffer:
       ds      2       ; ptr
fkeybuffer:
       ds      2       ; ptr
cfgfcb:
       ds      36      ; FCB for config file

       end