        name msxhp1
; File MSXHP1.ASM
; System dependent module for HP150.
; Latest modification: 20 April 1986

; Add global entry point vtstat for use by Status in mssset.
; Add clearing of terminal emulation flag, flags.vtflg, in procedure lclini.
; Joe R. Doupnik 12 March 1986
; Add register save/restore in poscur and in other procedures as well.
; Add global procedures ihosts and ihostr to handle host initialization
; when packets are to be sent or received by us,resp. 24 March 1986
; Add global procedure dtrlow (without worker serhng) to force DTR & RTS low
; in support of Kermit command Hangup. Says Not Yet Implemented. [jrd]
; Fix procedure getbaud to report unrecognized baud rate. [jrd]
; Add global procedure Dumpscr, called by Ter in file msster, to dump screen
;  to a file. Just does a beep for now. 13 April 1986 [jrd]
; In proc Outchr add override of xon from chkxon sending routine.
;  This makes a hand typed Xoff supress the xon flow control character sent
;  automatically as the receiver buffer empties. 20 April 1986 [jrd]
;
; Fix inverse video mode line from Arvind Kumar @ hplabs marked [ak], 1/86

        public  serini, serrst, clrbuf, outchr, coms, vts, vtstat, dodel, ctlu
        public  cmblnk, locate, prtchr, dobaud, clearl, lclini
        public  dodisk, getbaud, beep, setkhlp, setktab
        public  machnam, xofsnt, count, term, poscur
        public  clrmod, putmod, puthlp, sendbr, showkey
        public  ihosts, ihostr, dtrlow, dumpscr                 ; [jrd]
        include mssdef.h

false   equ     0
true    equ     1

wrdev   equ     40H
rddev   equ     3fH
open    equ     3dH
close   equ     3eH
rdchan  equ     2
e_send_break equ 6
e_ioctl equ     44h             ; DOS i/o control function   [jrd]

datas   segment public 'datas'
        extrn   drives:byte, flags:byte, trans:byte
        extrn   portval:word, port1:byte, port2:byte, dmpname:byte ; [jrd]
machnam db      'HP-150$'
erms20  db      cr,lf,'?Warning: System has no disk drives$' ; [21a]
erms40  db      cr,lf,'?Warning: Unrecognized baud rate$'
erms41  db      cr,lf,'?Warning: Cannot open com port$'
noimp   db      cr,lf,'Command not implemented.$'
hngmsg  db      cr,lf,' The phone should have hungup.',cr,lf,'$' ; [jrd]
hnghlp  db      cr,lf,' The modem control lines DTR and RTS for the current'
        db      ' port are forced low (off)'
        db      cr,lf,' to hangup the phone. Normally, Kermit leaves them'
        db      ' high (on) when it exits.'
        db      cr,lf,'$'                                       ; [jrd]
rdbuf   db      80 dup (?)      ; temp buf [jrd]
setktab db      0
setkhlp db      0
shkmsg  db      'Not implemented.'
shklen  equ     $-shkmsg
crlf    db      cr,lf,'$'
comphlp db      cr,lf,'1 (COM1)   2 (COM2)$'            ; [19b]
delstr  db      BS,BS,'  ',BS,BS,'$'    ; Delete string. [21d]
clrlin  db      cr,esc,'K$'
xofsnt  db      0               ; Say if we sent an XOFF.
xofrcv  db      0               ; Say if we received an XOFF.
invseq  db      esc,'&dB$'      ; Reverse video.
nrmseq  db      esc,'&d@$'      ; Normal mode.
ivlseq  db      80 dup (' '),esc,'A','$' ; [ak] Make a line inverse video
tmp     db      ?,'$'
temp    dw      0
temp1   dw      ?               ; Temporary storage.
temp2   dw      ?               ; Temporary storage.

; Entries for choosing communications port. [19b]

comptab db      04H
        db      01H,'1$'
        dw      01H
        db      01H,'2$'
        dw      00H
        db      04H,'COM1$'
        dw      01H
        db      04H,'COM2$'
        dw      00H

; variables for serial interrupt handler

source  db      bufsiz DUP(?)   ; Buffer for data from port.
bufout  dw      0               ; buffer removal ptr
count   dw      0               ; Number of chars in int buffer.
bufin   dw      0               ; buffer insertion ptr
telflg  db      0               ; Are we acting as a terminal. [16] [17c]
clreol  db      esc,'K$'
prttab  dw      com2,com1
com1    db      'COM1',0
com2    db      'COM2',0
blank   db      esc,'H',esc,'J$'
movcur  db      esc,'&a'
colno   db      20 dup (?)
ten     db      10
prthnd  dw      0
tempbuf dw      10 dup(?)
ourarg  termarg <>
datas   ends

code    segment public 'code'
        extrn   comnd:near, dopar:near, prserr:near
        extrn   sleep:near                              ; [jrd]
        assume  cs:code,ds:datas

; See how many disk drives we have.
DODISK  PROC    NEAR
        mov ah,gcurdsk                  ; Current disk value to AL.
        int dos
        mov dl,al                       ; Put current disk in DL.
        mov ah,seldsk                   ; Select current disk.
        int dos                         ; Get number of drives in AL.
        mov drives,al
        ret
DODISK  ENDP

; Clear the input buffer before sending a packet. [20e]

CLRBUF  PROC    NEAR
        cli
        mov ax,offset source
        mov bufin,ax
        mov bufout,ax
        mov count,0
        sti
clrb1:  call prtchr             ; get a character
         jmp clrb1              ; until there aren't any more
         nop
        ret
CLRBUF  ENDP

; Common routine to clear to end-of-line. [19a]

CLEARL  PROC    NEAR
        push    ax              ; save regs [jrd]
        push    dx
        mov dx,offset clreol
        mov ah,prstr
        int dos
        pop     dx              ; restore regs [jrd]
        pop     ax
        ret
CLEARL  ENDP

dobaud  proc    near            ; updated by [jrd] to set baud.
        mov ah,prstr
        mov dx,offset noimp     ; Say it's not implemented.
        int dos
        push bx                 ; save reg. [jrd]
        mov bx,portval
        mov [bx].baud,0FFFFH    ; So it's not a recognized value.
        pop bx
        ret                     ; Must be set before starting Kermit.
;;;[jrd]        jmp notimp
dobaud  endp

; Send the break signal out data comm.
sendbr: mov al,e_send_break
        jmp  dc_ioctl

; Set some data comm ioctl option.  AL has function code.
dc_ioctl proc   near
        push    ax                      ; save regs [jrd]
        push    bx
        push    cx
        push    dx
        mov ah,8h
        mov tempbuf,ax
        mov dx,offset tempbuf
        mov ah,e_ioctl
        mov al,3
        mov bx,prthnd
        mov cx,2
        int 21h
        pop     dx                      ; restore regs [jrd]
        pop     cx
        pop     bx
        pop     ax
        ret
dc_ioctl endp


outchr: push bp                 ; save regs. [jrd]
        push cx
        mov bp,portval
        cmp ds:[bp].floflg,0    ; Are we doing flow control.
        je outch2               ; No, just continue.
        xor cx,cx               ; clear counter
        cmp ah,byte ptr [bp].flowc      ; sending xoff? [jrd]
        jne outch1              ; ne = no
        mov xofsnt,false        ; supress xon from chkxon buffer routine
outch1: cmp xofrcv,true         ; Are we being held?
        jne outch2              ; No - it's OK to go on.
        loop outch1             ; held, try for a while
        mov xofrcv,false        ; timed out, force it off and fall thru.
outch2: push dx                 ; Save register.
        push bx
        cmp prthnd,0            ; do we have a port handle?
        jne outch3              ; yes, go on
        push ax
        call opnprt             ; open the port
        pop ax
outch3: mov byte ptr temp,ah    ; save character
        mov bx,prthnd
        mov ah,wrdev
        mov cx,1
        mov dx,offset temp
        int dos
        pop bx
        pop dx
        pop cx                  ; [jrd]
        pop bp
        jmp rskp

opnprt: mov al,flags.comflg
        mov ah,0
        push    si              ; [jrd]
        mov si,ax
        shl si,1                ; double index
        mov dx,prttab[si]
        pop     si              ; [jrd]
        mov ah,open
        mov al,2
        int dos
        jnc opnpr1
        mov ah,prstr
        mov dx,offset erms41
        int dos
        ret
opnpr1: mov prthnd,ax
        ret

; This routine blanks the screen.

CMBLNK  PROC    NEAR            ; This is stolen from the IBM example.
        mov ah,prstr
        mov dx,offset blank
        int dos
        ret
CMBLNK  ENDP

LOCATE  PROC    NEAR
        mov dx,0                ; Go to top left corner of screen.
        jmp poscur              ; callret...
LOCATE  ENDP

GETBAUD PROC    NEAR
        ret
GETBAUD ENDP


; skip returns if no character available at port,
; otherwise returns with char in al, # of chars in buffer in dx.

PRTCHR  PROC    NEAR
        push bx
        push cx
        push si
        push bp
        cmp prthnd,0            ; have a handle yet?
        jne prtch1              ; yes, keep going
        call opnprt
prtch1: cmp count,0             ; no characters? [jrd]
        jne prtch2              ; no, go fill buffer  [jrd]
        mov bx,prthnd
        mov al,rdchan
        mov ah,ioctl
        mov dx,offset source    ; buffer to read into
        mov cx,bufsiz           ; length of buffer
        int dos
        mov count,ax            ; reset count
        mov dx,ax               ; needed to obey rules [jrd]
        or ax,ax
        jz prtch4               ; still no chars
        mov bufout,offset source ; this is output ptr
prtch2: dec count
        mov dx,count            ; return count in dx
        mov si,bufout
        lodsb                   ; get character
        mov bufout,si           ; update ptr
        mov bp,portval
        cmp ds:[bp].parflg,PARNON       ; no parity?
        je prtch3               ; then don't strip
        and al,7fh              ; else turn off parity
prtch3: pop bp
        pop si
        pop cx
        pop bx
        ret
prtch4: pop bp
        pop si
        pop cx
        pop bx
        jmp rskp                ; no chars...
PRTCHR  ENDP

; IHOSTS - Initialize the host by sending XON, or equivalent, and enter the
; cycle of clear input buffer, wait 1 second, test if buffer empty then exit
; else repeat cycle. Requires that the port be initialized before hand.
; Ihosts is used by the local send-file routine just after initializing
; the serial port.
; 22 March 1986 [jrd]

IHOSTS  PROC    NEAR
        push    ax              ; save the registers
        push    bx
        push    cx
        push    dx
        mov     bx,portval      ; port indicator
        mov     ax,[bx].flowc   ; put Go-ahead flow control char in ah
        call    outchr          ; send it (release Host's output queue)
         nop                    ; outchr can do skip return
         nop
         nop
ihosts1:call    clrbuf          ; clear out interrupt buffer
        mov     ax,1            ; sleep for 1 second
        call    sleep           ; procedure sleep is in msscom.asm
        call    prtchr          ; check for char at port
         jmp    ihosts1         ; have a char in al, repeat wait/read cycle
         nop                    ; prtchr does skip return on empty buffer
        pop     dx              ; empty buffer. we are done here.
        pop     cx
        pop     bx
        pop     ax
        ret
IHOSTS  ENDP

; IHOSTR - initialize the remote host for our reception of a file by
; sending the flow-on character (XON typically) to release any held
; data. Called by receive-file code just after initializing the serial
; port.         22 March 1986 [jrd]
IHOSTR  PROC    NEAR
        push    ax              ; save regs
        push    bx
        push    cx
        mov     bx,portval      ; port indicator
        mov     ax,[bx].flowc   ; put Go-ahead flow control char in ah
        call    outchr          ; send it (release Host's output queue)
         nop                    ; outchr can do skip return
         nop
         nop
        pop     cx
        pop     bx
        pop     ax
        ret
IHOSTR  ENDP

DTRLOW  PROC    NEAR            ; Global proc to Hangup the Phone by making
                                ; DTR and RTS low.
        mov ah,cmtxt            ; allow text to be able to display help
        mov bx,offset rdbuf     ; dummy buffer
        mov dx,offset hnghlp    ; help message
        call comnd              ; get a confirm
         jmp r
; not yet imp.  call serhng             ; drop DTR and RTS
        mov ah,prstr            ; give a nice message
; not yet imp.  mov dx,offset hngmsg
        mov dx,offset noimp     ; for now
        int dos
        jmp rskp
DTRLOW  ENDP

; Hang up the Phone. Similar to SERRST except it just forces DTR and RTS low
; to terminate the connection. 29 March 1986 [jrd]
; Calling this twice without intervening calls to serini should be harmless.
; Returns normally.
; SERHNG is Not Yet Implemented.


; Position the cursor according to contents of DX.

POSCUR  PROC    NEAR
        push    ax                      ; save regs [jrd]
        push    dx
        push    di
        push    es
        mov     ax,ds
        mov     es,ax                   ; address data segment!!!
        cld
        mov     di,offset colno
        mov     al,dl                   ; column
        call    nout
        mov     al,'c'
        stosb
        mov     al,dh                   ; row
        call    nout
        mov     al,'Y'
        stosb
        mov     al,'$'
        stosb
        mov     dx,offset movcur
        mov     ah,prstr
        int     dos                     ; print the sequence
        pop     es                      ; restore regs [jrd]
        pop     di
        pop     dx
        pop     ax
        ret
POSCUR  ENDP

NOUT    PROC    NEAR
        cbw                     ; extend to word
        div     byte ptr ten    ; divide by 10
        or      al,al           ; any quotient?
        jz      nout1           ; no, forget this
        push    ax              ; save current result
        call    nout            ; output high order
        pop     ax              ; restore
nout1:  mov     al,ah           ; get digit
        add     al,'0'          ; make printable
        stosb
        ret                     ; put in buffer and return
NOUT    endp

; Write a line in inverse video at the bottom of the screen...
; the line is passed in dx, terminated by a $.  Returns normally.
putmod  proc    near
        push    dx              ; preserve message
        mov     dx,24 * 100H    ; line 24
        call    poscur
        mov     dx,offset invseq ; put into inverse video
        mov     ah,prstr
        int     dos
        pop     dx
        int     dos
        mov     dx,offset nrmseq ; normal videw
        int     dos
        ret                     ; and return
putmod  endp

; Clear the mode line written by putmod.  Returns normally.
clrmod  proc    near
        mov     dx,24 * 100H
        call    poscur
        call    clearl
        ret
clrmod  endp

; Put a help message one the screen in reverse video.  Pass
; the message in AX, terminated by a null.  Returns normally.
; The message is put wherever the cursor currently is located.
puthlp  proc    near
        push ax
        mov ah,prstr            ; Leave some room before the message.
        mov dx,offset crlf
        int dos
        pop si                  ; Put message address here.
puth0:  mov ah,prstr
        mov dx,offset invseq    ; Put into reverse video.
        int dos
        mov ah,prstr
        mov dx,offset ivlseq    ; Make line inverse video
        int dos
puth1:  lodsb
        cmp al,0                ; Terminated with a null.
        je puth2
        mov dl,al
        mov ah,conout
        int dos
        cmp al,lf               ; Line feed?
        je puth0                ; Yes, clear the next line.
        jmp puth1               ; Else, just keep on writing.
puth2:  mov dx,offset crlf
        mov ah,prstr
        int dos
        mov dx,offset nrmseq    ; Normal video.
        int dos
        ret
puthlp  endp

; Perform a delete.

DODEL   PROC    NEAR
        mov ah,prstr
        mov dx,offset delstr    ; Erase weird character.
        int dos
        ret
DODEL   ENDP

; Perform a Control-U.

CTLU    PROC    NEAR
        mov ah,prstr
        mov dx,offset clrlin
        int dos
        ret
CTLU    ENDP

COMS    PROC    NEAR
        mov dx,offset comptab
        mov bx,offset comphlp
        mov ah,cmkey
        call comnd
         jmp r
        push bx
        mov ah,cmcfm
        call comnd              ; Get a confirm.
         jmp comx               ;  Didn't get a confirm.
         nop
        pop bx
        mov flags.comflg,bl     ; Set the comm port flag.
        cmp flags.comflg,1      ; Using Com 1?
        jne coms0               ; Nope.
        mov ax,offset port1
        mov portval,ax
        ret
coms0:  mov ax,offset port2
        mov portval,ax
        ret
comx:   pop bx
        ret
COMS    ENDP

VTS     PROC    NEAR
        jmp notimp
VTS     ENDP


VTSTAT  PROC    NEAR    ; For Status display [jrd]
        ret             ; no emulator status to display
VTSTAT  ENDP

; Save the screen to a buffer and then append buffer to a disk file. [jrd]
; Default filename is Kermit.scn; actual file can be a device too. Filename
; is determined by mssset and is passed as pointer dmpname.

DUMPSCR PROC    NEAR    ; Dumps screen contents to a file. Just Beeps here
        call beep       ; [jrd]
        ret
DUMPSCR ENDP


notimp: mov ah,prstr
        mov dx,offset noimp
        int dos
        jmp prserr

lclini: mov     flags.vtflg,0   ; no terminal emulation. [jrd]
        mov     prthnd,0        ; no port handle yet. [jrd]
        ret

showkey:
        mov ax,offset shkmsg
        mov cx,shklen
        ret

;  Common initialization for using serial port.

SERINI  PROC    NEAR
        call opnprt
        call clrbuf             ; Clear input buffer. [20e]
        ret                     ; We're done. [21c]
SERINI  ENDP

SERRST  PROC    NEAR
        push bx                 ; save reg. [jrd]
        mov bx,prthnd
        cmp bx,0                ; none there?
        je serrs1               ; no, don't try to close.
        mov ah,close
        int dos                 ; close handle
        mov prthnd,0
serrs1: pop bx                  ; [jrd]
        ret                     ; All done. [21c]
SERRST  ENDP

; Generate a short beep.

BEEP    PROC    NEAR
        mov dl,bell
        mov ah,conout
        int dos
        ret
BEEP    ENDP

; Jumping to this location is like retskp.  It assumes the instruction
;   after the call is a jmp addr.

RSKP    PROC    NEAR
        pop bp
        add bp,3
        push bp
        ret
RSKP    ENDP

; Jumping here is the same as a ret.

R       PROC    NEAR
        ret
R       ENDP

term    proc    near
        mov si,ax               ; this is source
        mov di,offset ourarg    ; place to store arguments
        mov ax,ds
        mov es,ax               ; address destination segment
        mov cx,size termarg
        rep movsb               ; copy into our arg blk
term1:  call prtchr
        jmp short term2         ; have a char...
        nop
        nop
        jmp short term3         ; no char, go on
term2:  push ax
        mov dl,al
        and dl,7fh              ; mask off parity for terminal
        mov ah,dconio
        int dos                 ; write out the character
        pop ax
        test ourarg.flgs,capt   ; capturing output?
        jz term3                ; no, forget it
        call ourarg.captr       ; else call the routine
term3:  mov ah,dconio
        mov dl,0ffh
        int dos
        jz term1                ; no character, go on
        cmp al,ourarg.escc      ; escape char?
        je term4                ; yes, exit
        push ax                 ; save char
        mov ah,al
        or ah,80H               ; turn on hi bit so DOS doesn't interfere
        call outchr             ; output the character
        nop
        nop
        nop
        pop ax
        test ourarg.flgs,lclecho ; echoing?
        jz term1                ; no, continue loop
        mov dl,al
        mov ah,dconio
        int dos
        jmp term1               ; else echo and keep going
term4:  ret
term    endp
code    ends
        end
