        NAME msyap3
; File MSYAP3.ASM;

; NEC APC III system dependent module (taken from msyibm.asm).
;  Much EGA and other screen support commented out from ibm code.
; NEC modifications by Robert F. Goeke
; Last Edit: 14 March 1988
; edit history:
; 15 Mar 1988 Incorporate latest IBM mods for NEC

; Following comments from msyibm.asm code:
; 5 Jan 1988 Restore cursor codes broken by Tek code additions. [jrd]
; 1 Jan 1988 version 2.30
; 24 Dec 1987 Restore startup screen attributes at Kermit prompts. [jrd]
; 21 Dec 1987 Fix memory size sign problem for >640K systems. From Edgar Butt
; 4 Dec 1987 cleanup mode switching, add more Video 7 material. [jrd]
; 8 Nov 1987 Add EGA mode switching, from Terry Kennedy.
; 1 Nov 1987 Add support for Tektronix, based on work by Brian Holley. [jrd]
; 13 Oct 1987 Revise memory allocation sequence to avoid small holes. [jrd]
; 2 Oct 1987 Make log file character width match Set Display but 8 bits when
;  debugging. [jrd]
; 12 Sept 1987 clarify sequence of translation and 8 bit display. [jrd]
; 27 Aug 1987 Do Translation before logging. [jrd]
; 18 Aug 1987 Change ESC to escape for MASM 4.5+ [jrd]
; 28 July 1987 Fix scron problem in screen save. [jrd]
; 23 June 1987 Add plain_attribute macro; fix bug in circular buffer
;  routines which kept attributes from being stored (and replayed)
; 8 June 1987 Add keypad application mode tests to emit single chars. [jrd]
; 6 June 1987 Adapt to most recent msyibm file (keyboard translator et al)
;  [jrd]
; 10 May 1987 Move input translation into terminal emulator, leave copy
;  here for terminal type None, use mszibm byte anspflg to sense print
;  screen is active, print translated characters but don't translate if
;  debugging is active. [jrd]
; 28 March 1987 Make low_rgt screen coord word a global parameter.
;  Add support for variable length screens and cursor size changes with
;  EGA boards. Tests ok with 25, 35, 43, 50 lines with &/without MS Windows.
;  EGA Memory locations 40:84H and 40:87H are used in this process.
;  Use savadr dw as place to save screen: usually screen page 1 if screen
;  dimensions are non-standard (80x25), else memory buffer scrsav. [jrd]
; 21 March 1987 Translate arriving Connect mode chars via table rxtable. [jrd]
;  Add 132 Column support for Tseng Labs EVA board via procedure chgdsp,
;  add restore scrolled screen before writing to it. From David L. Knoell [dlk]
; Modify msy and msz to use variable screen length and widths. [dlk] and [jrd]
; 17 March 1987 Reduce screen roll back buffer to half the memory to do the
;  same number of screens. [jrd]
; 12 Jan 1987 Add keyboard translator, remove older code. [jrd]
; 1 Oct 1986 Version 2.29a

        public  term, lclyini                      ; entry points
        public  prtbout, prtnout, csrtype, scrmod, scrseg, scrsync
        public  scroff, scron, atsclr, vtscru, vtscrd, scrloc, trnmod, telmsy
        public  chgdsp, vtroll
                        ; action verb procedures for keyboard translator
        public  uparrw, dnarrw, rtarr, lfarr, pf1, pf2, pf3, pf4
        public  kp0, kp1, kp2, kp3, kp4, kp5, kp6, kp7, kp8, kp9
        public  kpminus, kpcoma, kpenter, kpdot, chrout, cstatus, cquit
        public  cquery, dmpscn, vtans52, vtinit, dnwpg, upwpg, endwnd, homwnd
        public  upone, dnone, trnprs, dumpscr, modlin, modwrt, snull
        public  klogon, klogof, cdos, chang

        public  vtemu, crt_mode, scbattr, refresh, low_rgt  ; data
	public  crt_cols, crt_lins, savescr, restscr, getflgs
        include mssdef.h

; some definitions
; NEC APC III hardware
screen  equ     19h                     ; bios screen call
kb      equ     18h                     ; keyboard interrupt
vram    equ     0A000H                  ; Video Ram
alt_shift equ   8H                      ; alt shift key down
ctl_shift equ   4H                      ; ctl key down
left_shift equ  2H                      ; left shift key down
; right_shift equ 1H                      ; right shift key down
func_shift equ  1H                      ; an NEC mod                    RFG

biostty equ     0eh                     ; Bios screen tty write mode [jrd]

modfrm  struc                           ; format of mode (status) line
        db      'Esc-chr: '             ; do not write in last column.
m_echr  db      2 dup (?)
        db      '  help: '
m_hlp   db      2 dup (?)
        db      '?  port:'
m_prt   db      1 dup (?)
        db      ' speed:'
m_baud  db      5 dup (?)
        db      ' parity:'
m_par   db      4 dup (?)
        db      ' echo:'
m_echo  db      3 dup (?)
m_term  db      13 dup (' ')            ; 13 bytes for term type
m_prn   db      3 dup (' ')             ; show PRN when printer is on [jrd]
modfrm  ends

; This macro flips the rev_video bit of attribute in ah.    RFG
; NB this neither changes any other attribute nor any other register
flip_rev_video  macro
                local   flip,flop
                test    ah,att_rev_video
                jnz     flip
                or      ah,att_rev_video
                jmp     flop
flip:           and     ah,not att_rev_video
flop:           nop
                endm

; This macro makes takes the character attributes in ah and makes them plain
; Different than IBM case 'cause we don't really have "intensity".       RFG
plain_attribute macro
                and     ah,not(att_overline+att_blink+att_underline)
                endm

att_overline    equ     01H             ; this is all NEC version stuff RFG
att_blink       equ     02H
att_rev_video   equ     04H
att_underline   equ     08H
att_intensity   equ     04H             ; same as reverse video

datas   segment public 'datas'
        extrn flags:byte, mar_top:byte, mar_bot:byte, portval:word
        extrn filtst:byte, dmpname:byte, kbdflg:byte, rxtable:byte
        extrn anspflg:byte, tekflg:byte

; stuff for screen routines
yflags  db      ?                       ; status flags...
flags1  db      0                       ; internal flags (but used in mszibm).
prtscr  equ     1                       ; print screen pressed
inited  equ     08h                     ; been here before...
vtinited db     0                       ; flag for emulator having been inited
cursor  dw      ?
esc_ch  db      ?
parmsk  db      ?                       ; 8/7 bit parity mask, for reception
argadr  dw      ?                       ; address of arg blk

savadr  dw      2 dup (?)               ; offset then segment of saved screen
savflg  dw      ?                       ; low_rgt at time of screen save


vtemu   emulst  <>                      ; emulator flags [jrd]
ansflgs db      0                       ; ANSI flags
trmtyp  db      0                       ; most recent terminal type
mtty    db      '  TTY   '              ; no terminal type (mode line)

lincur  dw      ?                       ; cursor type save area
scbattr db      ?                       ; Screen background attribute
oldattr db      ?                       ; screen attributes at init time
curattr db      ?                       ; current attribute
temp    dw      ?                       ; scratch storage
modtemp db      0                       ; temp to hold Kermit modeline status
captrtn dw      ?                       ; routine to call for captured output
dmphand dw      ?                       ; screen dump file handle 
dumpbuf db      132 dup (?), cr, lf     ; 134 byte dump work buffer
dumpsep db      FF,cr,lf                ; screen image separators
dmperr  db      ' Cannot open file to save screen to disk $'
crlf    db      cr,lf,'$'

; some static data for mode line
modbuf  modfrm  <>                      ; mode line buffer
unkbaud db      'unkwn'                 ; must be 5 chars...
baudn   db      ' 45.5',' 50  ',' 75  ',' 110 ','134.5',' 150 ',' 300 ',' 600 '
        db      ' 1200',' 1800',' 2000',' 2400',' 4800',' 9600','19200','38400'
        db      '57.6K','115 K'
baudnsiz  equ   18                      ; # of baud rates known (tbl size / 4)
parnams db      'even','mark','none','odd ','spc '
lclmsg  db      'loc'
remmsg  db      'rem'
portno  db      ?

; storage for multi-window stuff
swidth  equ     80                      ; max screen width
slen    equ     24                      ; and length of text
npages  equ     10                      ; # of pages of scrolling on each side
crt_norm db     ?                       ; video mode for normal screen
crt_mode db     ?                       ; video mode (typ 3, must be text)
crt_cols db     ?                       ; number of screen columns (typ 80)
crt_lins db     24                      ; number of screen rows - 1 (typ 24)
low_rgt dw      ?                       ; lower right corner of text window
                                        ; high = row address (typ 23)
                                        ; low = column address (typ 79)
inipara dw      ?                       ; initial paragraphs of scroll memory
refresh db      0                       ; screen refresh (0=wait for retrace)
vtroll  db      0                       ; auto roll back allowed (0 = no).

; circular buffer for screen roll back.
cbuf    struc
pp      dw      ?                       ; place ptr in buffer
bend    dw      ?                       ; end of buffer
orig    dw      ?                       ; buffer origin
lcnt    dw      0                       ; # of lines in buffer.
lmax    dw      ?                       ; max lines of buffer. [jrd]
cbuf    ends

twnd    cbuf    <>                      ; top screen spill-buffer struct
bwnd    cbuf    <>                      ; bottom screen spill buffer struct

datas   ends

code    segment public 'code'                   ; code segment
        extrn   beep:near, prtchr:near, outchr:near, sbrk:near, pcwait:near
        extrn   isfile:near, strlen:near, strcpy:near   ; in mssfil
        extrn   anstty:near,ansini:near,ansrei:near     ; in mszibm
        extrn   anstat:near,anskbi:near,ansdsl:near     ; in mszibm
        extrn   ans52t:near, vsinit:near                ; in mszibm
        extrn   msuinit:near, keybd:near                ; in msuibm
        extrn   tekini:near,tekcls:near,tekemu:near,tekend:near ;in msgibm

        assume  cs:code, ds:datas, es:datas

; do initialization local to this module...
; Dynamically allocates 4000 bytes for screen save/restore buffer plus
;  320 to 38400 bytes for screen scroll back buffers. Tries to leave space
;  for Command.com before enlarging buffers. [jrd]
; delete screen dump memory allocation; see savescr                     RFG
lclyini proc    near
        call    msuinit                 ; initialize keyboard module msuxxx
        mov     ax,swidth               ; ask for two lines (1 per buffer)
        add     ax,ax
        add     ax,ax                   ; times four (2 lines of char + attrib)
        call    sbrk                    ; allocate mem. Exit Kermit on failure
                                        ;if we get here them we have the lines
        mov     bwnd.orig,ax            ; memory segment, bottom window area
        mov     twnd.orig,ax            ; top. same place for both buffers!
        push    es                      ; save this register.
        mov     es,ax                   ; seg pointer to new memory block
        mov     bx,(swidth*slen*npages+7)/8 ; paragraphs wanted for roll back
        add     bx,24000D/16            ; plus paragraphs to run Command.com
        mov     ah,setblk               ; DOS Setblock. Ask for that space.
        int     dos                     ; bx has # paragraphs available
        sub     bx,24000D/16            ; deduct space for DOS 3.x Command.Com
        cmp     bx,(swidth*4+15)/16     ; any room left for buffers?
        jae     lclyin2                 ; some space is available for buffers
        mov     bx,(swidth*4+15)/16     ; else use our sbrk allocation
lclyin2:mov     ah,setblk               ; ask for that many (bx) paragraphs
        int     dos                     ; Errors here == DOS deceived us.
        pop     es                      ; restore reg.
        mov     ax,bx                   ; bx = # paragraphs allocated by DOS
        mov     inipara,bx              ; save for later resizing of buffers
        mov     cl,3                    ; 2**3 = 8
        shl     ax,cl                   ; paragraphs to words (char + attrib)
        xor     dx,dx                   ; clear extended size
        mov     cx,swidth               ; number of chars per line in buffer
        div     cx                      ; ax = number of lines in buffer
        mov     bwnd.lmax,ax            ; max lines per buffer (quotient)
        mov     twnd.lmax,ax            ; max lines per buffer
        add     cx,cx                   ; count char and attribute per item
        xor     dx,dx                   ; clear extended numerator
        mul     cx                      ; ax = effective # bytes per buffer
        dec     ax                      ; adjust for counting from zero
        mov     bwnd.bend,ax            ; offset of last byte in buffer
        mov     twnd.bend,ax            ; offset of last byte in buffer
        mov     bwnd.pp,0               ; offset of first byte in buffer
        mov     twnd.pp,0               ; offset of first byte in buffer
        mov     bwnd.lcnt,0             ; number of lines occupied in buffer
        mov     twnd.lcnt,0             ; number of lines occupied in buffer
        call    scrseg                  ; test running in an Environment
        call    scrmod                  ; read video state, get crt_mode.
        mov     ah,8                    ; read current attributes
        xor     bh,bh                   ; page 0
        int     screen
        mov     scbattr,ah              ; save video attributes
        mov     oldattr,ah              ; and here too
        call    vsinit                  ; init terminal emulator module MSZ
        ret
lclyini endp

scrini  proc    near                    ; init screen stuff
        call    scrmod                  ; get screen mode, low_rgt
        mov     ah,3                    ; get cursor position and char.
        xor     bh,bh                   ; page 0
        int     screen
        mov     lincur,cx               ; save cursor type (scan line #'s)
        mov     dx,cursor               ; assume old cursor
        test    flags1,inited           ; have we been here before?
        jnz     scrin4                  ; nz = yes, use old cursor
        mov     ah,oldattr              ; get init time attributes
        mov     curattr,ah              ; and set nice screen attribute
        mov     scbattr,ah
        mov     ah,3                    ; figure out where cursor is
        xor     bh,bh                   ; page 0
        int     screen                  ; read cursor position, in dx
scrin4: cmp     dh,byte ptr low_rgt+1   ; past logical end of screen?
        jb      scrin2                  ; b = no, keep going
        mov     dh,byte ptr low_rgt+1   ; yes, just use lower right corner
scrin2: cmp     dl,byte ptr low_rgt     ; maybe past right margin
        jb      scrin3                  ; b = no, use the way it is
        mov     dl,byte ptr low_rgt
scrin3: mov     cursor,dx               ; init cursor
        mov     ah,2                    ; set cursor position
        xor     bh,bh                   ; page zero
        int     screen                  ; set cursor in case it moved
        ret
scrini  endp

; Routine to initialize terminal emulator. Call once.

vtinit  proc    near
        cmp     flags.vtflg,0           ; doing emulation?
        je      vtinix                  ; e = no
        cmp     tekflg,0                ; Tek mode active?
        jne     vtini2                  ; ne = yes, do it's reinit
        or      vtinited,inited
        call    ansflg                  ; update ansi flags
        mov     al,yflags               ; Pass the flags.
        mov     bx,argadr               ; Get address of argument block
        mov     dl,[bx].baudb           ; Baud rate code in dl
        mov     dh,[bx].parity          ; Parity code in bits
        mov     cl,4                    ; 0-3 of dh
        shl     dh,cl
        test    flags.remflg,d8bit      ; eight bit display?
        jnz     vtini1                  ; nz = yes
        or      dh,07H                  ; Just say 7 data bits.
        call    ansini                  ; call startup routine in mszibm.
        ret
vtini1: or      dh,8                    ; say 8 bits
        call    ansini
vtinix: clc
        ret
vtini2: call    tekcls                  ; clear Tek screen
        clc
        ret
vtinit  endp


argini  proc    near                    ; read passed arguments
        mov     bx,argadr               ; base of argument block
        mov     al,[bx].flgs            ; get flags
        and     al,capt+emheath+havtt+trnctl+lclecho+modoff+lnwrap
        mov     yflags,al               ; mask for allowable and save
        mov     al,[bx].prt
        mov     portno,al               ; update port number
        mov     al,[bx].rows
        mov     crt_lins,al             ; init # of rows and cols
        mov     ax,[bx].captr
        mov     captrtn,ax              ; buffer capture routine
        mov     al,[bx].escc
        mov     esc_ch,al
        mov     parmsk,0ffh             ; parity mask, assume parity = None
        cmp     [bx].parity,parnon      ; is parity None?
        je      argini1                 ; e = yes, keep all 8 bits
        mov     parmsk,07fh             ; else keep lower 7 bits
argini1:ret				; that's it

argini  endp

modlin  proc    near                    ; turn on mode line
        mov     al,esc_ch
        mov     modbuf.m_echr,' '       ; first char is initial space
        mov     modbuf.m_hlp,' '        ; goes here too.
        cmp     al,32                   ; printable?
        jnb     modl1                   ; yes, keep going
        add     al,40h                  ; made printable
        mov     modbuf.m_echr,5eh       ; caret, note control char
        mov     modbuf.m_hlp,5eh
modl1:  mov     modbuf.m_echr+1,al      ; fill in character
        mov     modbuf.m_hlp+1,al
        mov     bx,argadr               ; get argument block
        mov     al,[bx].baudb           ; get baud bits
        mov     si,offset unkbaud       ; assume unknown baud
        cmp     al,baudnsiz             ; too big?
        jnb     modl2                   ; nb = yes, use default
        mov     cl,size m_baud          ; each is 5 bytes long
        mul     cl
        mov     ah,0
        add     ax,offset baudn
        mov     si,ax
modl2:  mov     cx,size m_baud          ; length of baud space
        mov     di,offset modbuf.m_baud
        push    es                      ; save es
        push    ds
        pop     es                      ; set es to datas segment
        cld
        rep     movsb                   ; copy in baud rate
        mov     al,[bx].parity          ; get parity code
        mov     cl,2                    ; each is 4 bytes long...
        shl     al,cl
        mov     ah,0
        add     ax,offset parnams       ; names of parity settings
        mov     si,ax
        mov     cx,4                    ; each is 4 long
        mov     di,offset modbuf.m_par
        rep     movsb
        mov     si,offset remmsg        ; Assume remote echoing.
        test    yflags,lclecho          ; Is remote side echoing?
        jz      modl4                   ; Yes, keep going
        mov     si,offset lclmsg        ; Else it's local echoing.
modl4:  mov     cx,3                    ; size of on/off
        mov     di,offset modbuf.m_echo
        rep     movsb
        mov     al,portno               ; communications port
        cmp     al,' '                  ; binary (non-printable)?
        jae     modl5                   ; ae = no, ascii
        add     al,'0'                  ; convert to ascii
modl5:  mov     modbuf.m_prt,al         ; fill in port number
        mov     cx,8                    ; blank out terminal id field
        mov     si,offset mtty          ; assume no terminal emulation.
        mov     di,offset modbuf.m_term ; destination
        rep     movsb                   ; copy it in.
        mov     modbuf.m_prn,' '        ; assume not printing the screen [jrd]
        mov     modbuf.m_prn+1,' '
        mov     modbuf.m_prn+2,' '
        test    anspflg,prtscr          ; doing a print the screen?
        jz      modl5a                  ; z = no.
        mov     modbuf.m_prn,'P'        ; yes. display PRN at end of line
        mov     modbuf.m_prn+1,'R'
        mov     modbuf.m_prn+2,'N'
modl5a: mov     cx,size modfrm          ; this is size of mode line
        mov     si,offset modbuf        ; mode line image
        pop     es
                        ; alternate entry to write an alternate mode line
modwrt: push    cx
        push    si                      ; save mode line and size
        mov     ah,3                    ; read cursor position
        xor     bx,bx                   ; screen page 0
        int     screen
        mov     cursor,dx               ; save cursor position
        call    trmatt                  ;[IU2] Get terminal attributes
        plain_attribute
        mov     bh,ah                   ; get video attribute
        mov     dx,low_rgt              ; right most column
        inc     dh                      ; refer to status line
        mov     ch,dh                   ; bottom line [dlk]
        mov     cl,0                    ; left col = 0 (first) [dlk]
        mov     ax,600h                 ; scroll to clear the line
        int     screen
        mov     dh,byte ptr low_rgt+1   ; refer to status line
        inc     dh
        xor     dl,dl                   ; left most column
        mov     bh,0
        mov     ah,2                    ; set cursor position
        int     screen
        pop     si
        pop     cx                      ; restore these
        cmp     cl,crt_cols             ; mode line longer than screen?
        jbe     modl6                   ; le = no
        mov     cl,crt_cols             ; else do just one line's worth [jrd]
        dec     cx                      ; don't let screen scroll
modl6:  cld
        lodsb                           ; get a byte
        push    si                      ; RFG
        mov     ah,14                   ; write to terminal
        mov     bh,0                    ; page 0
        int     screen
        pop     si                      ; RFG
        loop    modl6                   ; write out entire mode line
        cmp     flags.vtflg,0           ; emulating?
        je      modl7                   ; e = no
        and     yflags,not modoff       ; update local flags (mode line on)
        mov     al,yflags               ; Yes - update flags also
        call    ansdsl                  ; get extras from emulator
modl7:  mov     dx,cursor
        mov     ah,2
        mov     bh,0
        int     screen                  ; put cursor back where it belongs
        ret                             ; and return
modlin  endp

clrmod  proc    near                    ; clear mode line
	cmp	flags.vtflg,tttek	; NEC -- a precaution only
	je	clrmodx
        call    trmatt                  ; Get terminal screen attributes
        mov     bh,al                   ; Use screen background attribute
        mov     ax,600h                 ; blank window
        mov     dx,low_rgt              ; right most column
        inc     dh                      ; refer to status line
        mov     cx,dx                   ; bottom line [dlk]
        xor     cl,cl                   ; left most column
        int     screen                  ; clear mode line
clrmodx: ret                            ; and return
clrmod  endp


; Fetch screen attributes from emulator (if emulating). It exists mainly
; so that the reverse video will work.   Returns the current mode
; line background attribute in ah, the current screen background in al,
; and the current "cursor" (foreground) attribute in bl.  (Note: anstat
; returns status yflags in bh).

trmatt  proc    near                    ; Get attributes
        cmp     flags.vtflg,0           ; emulating? [jrd]
        je      trmat1                  ; No, just do simple stuff.
        mov     al,yflags               ; anstat expects flags byte in al.
        call    anstat                  ; Fetch emulator status/attributes
        ret
trmat1: mov     al,scbattr              ; Background attributes. [jrd]
        mov     bl,curattr              ; And cursor attribute.
        mov     ah,al                   ; where modlin needs them [jrd]
        plain_attribute
        flip_rev_video                  ; reverse the video
        ret
trmatt  endp

; Get byte yflags of terminal emulator passed in AL. Used in mode line
; handling when 25th line is used by the emulator.
telmsy  proc    near
        mov     yflags,al               ; get the updated flags
        call    ansflg                  ; and any other emulator info
        ret
telmsy  endp


;[IU2] This routine updates the ANSI status flags from the emulator,
; and passes the "yflags" byte to the VT100 emulator also.

ansflg  proc    near
        push    ax                      ; Save acs over call
        push    bx
        mov     al,yflags
        call    anstat                  ; Get status and attributes
        mov     ansflgs,bh              ; Save.
        pop     bx
        pop     ax
        ret
ansflg  endp

getflgs proc    near                    ; supply yflags for terminal emulators
        mov     al,yflags
        ret
getflgs endp

term    proc    near                    ; terminal mode entry point
        mov     argadr,ax               ; save argument ptr
        call    argini                  ; init options from arg address
        call    scrini                  ; init screen stuff

        test    flags1,inited           ; have we run yet?
        jz      term1                   ; z = no, so no saved screen yet
        call    restscr                 ; restore screen
term1:  or      flags1,inited           ; remember we've run already.
        cmp     flags.vtflg,0           ; current terminal type = None?
        je      term3a                  ; e = yes, nothing to init.
        mov     al,yflags               ; tell emulator we are back
        cmp     vtinited,inited         ; inited emulator yet?
        je      term3                   ; e = yes
        cmp     tekflg,0                ; Tek mode still active?
        jne     term3a                  ; ne = yes, no re-init here
        call    vtinit                  ; init it now
        jmp     term3a
term3:  call    ansrei                  ; reinit the emulator
        call    ansflg                  ; and get its flags
term3a: cmp     flags.modflg,0          ; is mode line disabled?
        je      term2a                  ; e = yes, disabled
        cmp     flags.vtflg,0           ; emulating a terminal?
        jne     term1a                  ; ne = yes, can have mode line
        cmp     trmtyp,0                ; previous terminal type = none?
        jne     term2                   ; ne = no. need to clear mode line.
        jmp     term2a                  ; yes, let 25th line be intact
term1a: test    yflags,modoff           ; is mode line toggled off?
        jnz     term2                   ; nz = yes, clear the line.
        cmp     flags.vtflg,tttek       ; going to be a Tek terminal?
        je      term2a                  ; e = yes, no mode line
        call    modlin                  ; turn on mode line
        jmp     term2a
term2:  call    clrmod                  ; ensure its off
term2a: mov     al,flags.vtflg          ; current terminal type
        mov     trmtyp,al               ; place to remember it til next time
        cmp     flags.vtflg,tttek       ; Tek mode?
        je      term4                   ; e = yes
        cmp     tekflg,0                ; Tek mode active within DEC stuff?
        je      lp                      ; e = no
term4:  call    tekini                  ; reinit to get graphics screen

lp:     call    portchr                 ; char at port?
         jnc    chkinp                  ; nc = no, keep going
         nop
        call    outtty                  ; print on terminal

chkinp: call    keybd                   ; call keyboard translator in msu
        jnc     lp                      ; nc = no char or have processed it
                                        ; carry set = quit Connect mode.

quit:   call	tekend
	mov     ah,3                    ; get cursor position
        xor     bh,bh                   ; page 0
        int     screen
        mov     cursor,dx               ; save position
        call    savescr                 ; save screen
        cmp     flags.vtflg,0           ; emulating?
        je      quit1                   ; e = no
        call    clrmod                  ; erase mode line
quit1:  mov     ah,oldattr              ; attributes at init time
        mov     scbattr,ah              ; background = original state [jrd]
                                        ; for ega in non-standard # lines
        mov     cx,lincur               ; cursor type at startup
        mov     ah,1
        int     screen                  ; restore cursor type
quit3:
        mov     ah,2                    ; Position cursor
        mov     bh,0                    ; Page 0
        mov     dx,low_rgt              ; bottom line
        inc     dh                      ; status line position
        xor     dl,dl                   ; left most column
        int     screen                  ; Do it.

        mov     al,yflags
        mov     bx,argadr
        mov     [bx].flgs,al            ; update flags in arg block
        ret                             ; and return to caller
term    endp

; put the character in al to the screen
outtty  proc    near
        cmp     flags.vtflg,0           ; emulating a terminal?
        jne     outnoc                  ; ne = yes, emulator handles printing
        test    flags.remflg,d8bit      ; keep 8 bits for displays?
        jnz     outnp9                  ; nz = yes, 8 bits if possible
        and     al,7fh                  ; remove high bit
outnp9: cmp     rxtable+256,0           ; translation turned off?
        je      outnp7                  ; e = yes, no translation
        push    bx
        mov     bx,offset rxtable       ; address of translate table
        xlatb                           ; new char is in al
        pop     bx
outnp7: test    anspflg,prtscr          ; should we be printing?
        jz      outnop                  ; no, keep going
        push    ax
        mov     ah,lstout               ; write to system printer device
        mov     dl,al
        int     dos
        pop     ax
        jnc     outnop                  ; nc = successful print
        push    ax
        call    beep                    ; else make a noise and
        call    trnprs                  ;  turn off printing
        pop     ax
outnop: test    yflags,capt             ; capturing output?
        jz      outnoc                  ; no, forget this part
        push    ax                      ; save char
        call    captrtn                 ; give it captured character
        pop     ax                      ; restore character and keep going
outnoc: cmp     tekflg,0                ; Tek mode active?
        jne     outnp6                  ; ne = yes, skip screen rolling
        cmp     vtroll,0                ; auto roll back allowed?
        jz      outnp6                  ; z = no, leave screen as is.
        cmp     bwnd.lcnt,0             ; is screen rolled back? [dlk]
        je      outnp6                  ; e = no
        call    endwnd                  ; restore screen before writing [dlk]
outnp6: cmp     flags.vtflg,0           ; emulating a terminal?
        jnz     outnop1                 ; nz = yup, go do something smart
        test    yflags,trnctl           ; debug? if so use Bios tty mode
        jz      outnp4                  ; z = no
        mov     ah,biostty              ; Bios tty screen write
        cmp     al,7fh                  ; Ascii Del char or greater?
        jb      outnp1                  ; b = no
        je      outnp0                  ; e = Del char
        push    ax                      ; save the char
        mov     al,7eh                  ; output a tilde for 8th bit
        int     screen
        pop     ax                      ; restore char
        and     al,7fh                  ; strip high bit
outnp0: cmp     al,7fh                  ; is char now a DEL?
        jne     outnp1                  ; ne = no
        and     al,3fH                  ; strip next highest bit (Del --> '?')
        jmp     outnp2                  ; send, preceded by caret
outnp1: cmp     al,' '                  ; control char?
        jae     outnp3                  ; ae = no
        add     al,'A'-1                ; make visible
outnp2: push    ax                      ; save char
        mov     al,5eh                  ; caret
        int     screen                  ; display it
        pop     ax                      ; recover the non-printable char
outnp3: int     screen
        ret
outnp4: cmp     al,bell                 ; bell (Control G)? [jrd]
        jne     outnp5                  ; ne = no
        jmp     beep                    ; use short beep, avoid char loss.
outnp5: mov     dl,al                   ; write without intervention.
        mov     ah,conout
        int     dos                     ; else let dos display char
        ret                             ; and return

outnop1:cmp     flags.vtflg,tttek       ; doing Tektronix emulation?
        je      outnop2                 ; e = yes, use Tek emulator
        cmp     tekflg,0                ; Tek submode active?
        jne     outnop2                 ; ne = yes, use Tek emulator
        jmp     anstty                  ; call terminal emulator routine & ret
outnop2:jmp     tekemu                  ; use Tek emulator and return

outtty  endp

; get shift state into al.  We care about only shift, ctl, and alt keys.
; right shift is collapsed into left shift.
; in NEC there is no left/right shift, but the right_shift code is used
;       to indicate FUNC                                        RFG
gss     proc    near
        mov     ah,2
        int     kb                      ; get current shift state
        mov     bl,al                   ; copy for a moment
        and     al,(func_shift + left_shift + alt_shift + ctl_shift)
        ret
gss     endp

;[IU2] Here to output character to port with no echo (like escape sequences
; sent by PF keys, responses to requests from the host, etc.   It is
; wrong thinking to echo these).

prtbout proc    near                    ; Global routine now.
        mov     ah,al                   ; This is where outchr expects it
	call    outchr
         nop                            ; Ignore skip return.
         nop
         nop
        ret
prtbout endp


;[IU2] Here to output an unsigned 8-bit number (in al) to the port without
; echoing. Used by terminal emulator escape sequence output.

prtnout proc    near
        mov     bl,10                   ; Output in base 10.
        jmp     prtno2                  ; Ensure at least a zero.

prtno1: cmp     al,0
        jne     prtno2                  ; Yes - do more digits
        ret                             ; No - return from recursive call.
prtno2: mov     ah,0                    ; Clear previous remainder.
        div     bl                      ; Divide off a digit
        push    ax                      ; Push remainder (in ah) on stack
        call    prtno1                  ; Recur.
        pop     ax                      ; Pop off a digit
        add     ah,'0'                  ; Make it ASCII
        call    outchr                  ; Output to port
	 nop
	 nop
	 nop
        ret
prtnout endp

; send the character in al out to the serial port; handle echoing.
; Can send an 8 bit char while displaying only 7 bits locally.
outprt  proc    near
        test    yflags,lclecho          ; echoing?
        jz      outpr1                  ; z = no, forget it
        push    ax                      ; save char
        call    outtty                  ; print it
        pop     ax                      ; restore
outpr1: mov     ah,al                   ; this is where outchr expects it
        call    outchr                  ; output to the port
         nop
         nop
         nop                            ; skip returns...
        ret
outprt  endp

; returns with carry on if a character is available

portchr proc    near
        call    prtchr                  ; character at port?
         jmp    short portc1            ; yes, go handle
         nop                            ; skip return is stupid...
portc0: clc                             ; no carry -> no character
        ret                             ; and return...
portc1: and     al,parmsk               ; apply 8/7 bit parity mask [jrd]
        stc                             ; have a character
        ret                             ; and return
portchr endp

;;; Action routines (verbs) for keyboard translator KEYBD in msuibm.
; These are invoked by a jump instruction. Return carry clear for normal
; processing, return carry set for invoking Quit (kbdflg has transfer char).
uparrw: mov     al,'A'                  ; cursor keys
        jmp     short comarr
dnarrw: mov     al,'B'
        jmp     short comarr
rtarr:  mov     al,'C'
        jmp     short comarr
lfarr:  mov     al,'D'
comarr: push    ax                      ; save final char
        mov     al,escape		; Output an escape.
	cmp	flags.vtflg,tttek	; Tek terminal
	je	comar0			; e = yes, use VT100 codes
        call    outprt                  ; Output, echo permitted
        cmp     flags.vtflg,ttvt100     ; VT100 terminal emulation?
        jne     comar2                  ; No, do VT52/HEATH-19 sequence.
comar0: call    ansflg                  ; Update flags all around.
        mov     al,'['                  ; Maybe this next?
        test    ansflgs,decckm          ; Cursor key mode reset?
        je      comar1                  ; Yes, output the "["
        mov     al,'O'                  ; No, set, use the "O".
comar1: call    outprt                  ; Output it (echo permitted).
comar2: pop     ax                      ; recover final char
        call    outprt                  ; Output to port (echo permitted)
        clc
        ret

pf1:    mov     al,'P'                  ; keypad function keys 1-4
        jmp     short compf
pf2:    mov     al,'Q'
        jmp     short compf
pf3:    mov     al,'R'
        jmp     short compf
pf4:    mov     al,'S'
compf:  push    ax                      ; save final char
        mov     al,escape                  ; Output an escape.
        call    prtbout
        call    ansflg                  ; get emulator flags
        test    ansflgs,decanm          ; ansi mode?
        jz      short compf1            ; z = no
        mov     al,'O'                  ; send an "O".
        call    prtbout                 ; Output it.
compf1: pop     ax                      ; Get the saved char back
        call    prtbout                 ; Output to port
        clc
        ret

kp0:    mov     al,'p'                  ; keypad numeric keys
        jmp     short comkp
kp1:    mov     al,'q'
        jmp     short comkp
kp2:    mov     al,'r'
        jmp     short comkp
kp3:    mov     al,'s'
        jmp     short comkp
kp4:    mov     al,'t'
        jmp     short comkp
kp5:    mov     al,'u'
        jmp     short comkp
kp6:    mov     al,'v'
        jmp     short comkp
kp7:    mov     al,'w'
        jmp     short comkp
kp8:    mov     al,'x'
        jmp     short comkp
kp9:    mov     al,'y'
        jmp     short comkp
kpminus:mov     al,'m'
        jmp     short comkp
kpcoma: mov     al,'l'
        jmp     short comkp
kpenter:mov     al,'M'
        jmp     short comkp
kpdot:  mov     al,'n'
comkp:  test    ansflgs,deckpam         ; keypad application mode active?
        jnz     comkp3                  ; nz = yes, use escape sequences
        sub     al,40h                  ; deduct offset to numeric symbols
        jmp     comkp0                  ; and send that single char
comkp3: push    ax                      ; save final char
        mov     al,escape                  ; Output an escape.
        call    prtbout
        mov     al,'O'                  ; Output the "O"
        cmp     flags.vtflg,ttvt100     ; VT100 mode?
        je      comkp1                  ; e = yes, use "O" code
	cmp	flags.vtflg,tttek	; Tek terminal
	je	comkp1			; e = yes, use VT100 codes
        test    ansflgs,decanm          ; ANSI (alt application keypad) mode?
        jnz     comkp1                  ; nz = yes, use "O"
comkp2: mov     al,'?'                  ; else use "?" instead of "O".
comkp1: call    prtbout
        pop     ax                      ; recover final char
comkp0: call    prtbout                 ; send it
        clc
        ret

klogon  proc    near                    ; resume logging (if any)
        test    flags.capflg,logses     ; session logging enabled?
        jz      klogn                   ; z = no, forget it
        or      argadr.flgs,capt        ; turn on capture flag
        or      yflags,capt             ; set local msy flag as well
	call	ansflg
klogn:  clc
        ret
klogon  endp

klogof  proc    near                    ; suspend logging (if any)
        and     argadr.flgs,not capt    ; stop capturing
        and     yflags,not capt         ; reset local msy flag as well
	call	ansflg
klogo:  clc
        ret
klogof  endp

snull   proc    near                    ; send a null byte
        mov     al,0                    ; the null
        call    prtbout                 ; send without logging and local echo
        clc
        ret
snull   endp
                                        ; general character out for emulator
chrout: cmp     flags.vtflg,0           ; emulating?
        je      chrou5                  ; e = no
        call    anskbi                  ; Yes, say we had keyboard input.
        cmp     al,cr                   ; A CR?
        jne     chrou5                  ; No - just output it and return
        call    ansflg                  ; Yes - update VT100 flags
        test    ansflgs,anslnm          ; ANSI new-line mode set?
        jz      chrou5                  ; No - just send the cr
        call    outprt                  ; Yes - output a carriage-return
        mov     al,lf                   ; Followed by a line feed.
chrou5: call    outprt
        clc
        ret

                                        ; these commands invoke Quit

cdos:   mov     al,'P'                  ; Push to DOS
        jmp     short cmdcom
cstatus:mov     al,'S'                  ; Status
        jmp     short cmdcom
cquit:  mov     al,'C'                  ; Exit Connect mode
        jmp     short cmdcom
cquery: mov     al,'?'                  ; Help
        jmp     short cmdcom
chang:  mov     al,'H'                  ; Hangup, drop DTR & RTS
        jmp     short cmdcom
cmdcom: mov     kbdflg,al               ; pass char to msster.asm via kbdflg
        stc                             ; signal that Quit is needed
        ret

dmpscn  proc    near                    ; dump screen to file
        call    savescr                 ; save screen to buffer
        call    dumpscr                 ; do buffer to file
        clc                             ; do not exit Connect mode
        ret
dmpscn  endp


; Routine to toggle VT100/VT52/Heath-19 modes in VT100 emulator.

vtans52 proc    near
        cmp     flags.vtflg,0           ; emulating?
        je      vtans5                  ; e = no
        call    ans52t                  ; Call MSZ toggle-it routine.
        call    ansflg                  ; Update flags.
        clc                             ; clear c bit so don't exit Connect.
vtans5: ret
vtans52 endp
                                        ; Toggle Mode Line
trnmod: cmp     flags.modflg,0          ; is mode line enabled?
        je      trnm2                   ; e = no, don't touch it
	cmp	flags.vtflg,tttek	; Tek mode?
	je	trnm2			; yes
	cmp	tekflg,0		; Tek submode?
	jne	trnm2			; ne = yes, no mode line changes
        test    yflags,modoff           ; mode line already off?
        jnz     trnm1                   ; yes, go turn on
        call    clrmod                  ; no, clear mode line here
        or      yflags,modoff           ; turn on flag
        call    ansflg                  ; Update flags all around.
        clc                             ; clear c bit so don't exit Connect
        ret                             ; and return
trnm1:  and     yflags,not modoff       ; Clear flag first.
        call    modlin                  ; Then turn on mode line.
        call    ansflg                  ; Update flags all around.
trnm2:  clc
	ret

trnprs: push    ax                      ; toggle ^ PrtSc screen to printer
        test    anspflg,prtscr          ; are we currently printing?
        jnz     trnpr2                  ; nz = yes, its on and going off
        mov     ah,ioctl
        mov     al,7                    ; get output status of printer
        push    bx
        mov     bx,4                    ; file handle for system printer
        int     dos
        pop     bx
        jc      trnpr1                  ; c = printer not ready
        cmp     al,0ffh                 ; Ready status?
        je      trnpr2                  ; e = Ready
trnpr1: call    beep                    ; Not Ready, complain
        jmp     trnpr3                  ; and ignore request
trnpr2: xor     anspflg,prtscr          ; flip the flag
        test    yflags,modoff           ; mode line off?
        jnz     trnpr3                  ; nz = yes
        call    modlin                  ; else rewrite mode line
trnpr3: pop     ax
        clc                             ; return carry clear (don't quit)
        ret

;;;;; General screen management routines for NEC APC

; computes screen location to ax, given row and col in [dh,dl], resp.
; trashes dx
scrloc  proc    near
        mov     al,dh                   ; get row
        xor     ah,ah                   ; clear ah
        mul     crt_cols                ; multiply by number of columns
        xor     dh,dh                   ; clear row
        add     ax,dx                   ; this is current position
        shl     ax,1                    ; double for attributes
        ret
scrloc  endp

; Routine to set cursor type.  Pass cursor type in al: 0 = No cursor,
; 1 = Underline cursor, 2 = Block cursor, 3 = restore cursor,
; 5 = No blink underline, 6 = No blink block.
; modified for NEC                                  RFG

csrtype proc    near
        push    cx                      ; save the reg
        mov     ah,1                    ; Video fxn for set cursor type
        mov     cx,0707H                ; Set one line.
        cmp     al,1                    ; Underline?
        je      csrty2                  ; Right - then do it
        or      cx,0400H                ; set for no blink
        cmp     al,5                    ; is it this?
        je      csrty2                  ; Right - then do it
        mov     cx,0007H                ; set for block
        cmp     al,2                    ; Block?
        je      csrty2                  ; Right - then do it
        or      cx,0400H                ; set for no blink
        cmp     al,5                    ; no-blink underline?
        je      csrty2                  ; Right - then do it
        cmp     al,0                    ; Disable cursor?
        je      csrty3                  ; Right - then do it
        jmp     csrty4                  ; last choice is enable
csrty2: int     screen                  ; Set it.
        pop     cx
        ret
csrty3: push    bx
        mov     ah,3                    ; BIOS call to read current
        mov     bh,0                    ;    current cursor status
        int     screen
        or      ch,80H                  ; Set disable bit
        mov     ah,1                    ; And set cursor
        pop     bx
        jmp     csrty2
csrty4: push    bx
        mov     ah,3
        mov     bh,0
        int     screen
        and     ch,7FH                  ; Clear disable bit
        mov     ah,1
        pop     bx
        jmp     csrty2
csrtype endp


; Save the entire screen in a buffer so we can restore and/or dump it.
; Saves regular (80x25) screens to memory buffer scrsav and other sized
; screens to video memory page 1. Resultant save place put into savadr
; (offset then segment) and current low_rgt size info in savflg. Note,
; some Environments (TopView/Windows etc) may not permit use of page 1. [jrd]
; modified for the NEC since text/attribute pattern is different.
;       put image of Page 0 VRAM into Page 1 VRAM for the save  RFG
savescr proc    near
        push    ax
        push    bx
        push    cx
        push    dx
        push    di
        push    si
        push    ds
        push    es
        mov     ax,vram                 ; start of VRAM is A000:0000
        mov     savadr+2,ax             ; save segment in this word
        call    scrmod                  ; ascertain video mode and screen
        mov     ax,low_rgt              ; text screen lower right (typ 23,79)
        mov     savflg,ax               ; save it for screen restore
        mov     si,0                    ; this is Page 0, to be saved
        mov     di,1000H                ; this is Page 1, the save buffer
        mov     savadr,di               ; save offset in this word
        mov     cx,80*25
        mov     ax,vram
        mov     ds,ax
        mov     es,ax
        cld
        rep     movsw                   ; move the text page
        mov     si,2000H                ; this is Page 0, attributes
        mov     di,3000H                ; this is Page 1
        mov     cx,80*25
        rep     movsw                   ; move the attribute page
        pop     es
        pop     ds
        pop     si
        pop     di
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ret                             ; and return
savescr endp

; restore screen from scrsav buffer. Restores all 25 lines. [jrd]
; like savescr, modified for NEC                                RFG
restscr proc    near
        push    ax
        push    bx
        push    cx
        push    dx
        push    di
        push    si
        push    ds
        push    es
        mov     ax,vram                 ; start of VRAM is A000:0000
        mov     ds,ax
        mov     es,ax
        mov     si,1000H                ; this is Page 1, to be restored
        mov     di,0                    ; this is Page 0
        mov     cx,80*25
        rep     movsw                   ; move the text page
        mov     si,3000H                ; this is Page 1, attributes
        mov     di,2000H                ; this is Page 0
        mov     cx,80*25
        rep     movsw                   ; move the attributes
        pop     es
        pop     ds
        pop     si
        pop     di
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ret                             ; and return
restscr 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 reads the screen image saved by savescr so call savescr call first.
; Mod to use VRAM (see savescr)                                 RFG

dumpscr proc    near
        push    ax
        push    bx
        push    cx
        push    dx
        mov     dmphand,-1              ; preset illegal handle
        mov     dx,offset dmpname       ; name of disk file, from mssset
        mov     ax,dx                   ; where isfile wants name ptr
        call    isfile                  ; what kind of file is this?
        jc      dmp5                    ; c = no such file, create it
        test    byte ptr filtst.dta+21,1fh ; file attributes, ok to write?
        jnz     dmp0                    ; nz = no.
        mov     al,1                    ; writing
        mov     ah,open2                ; open existing file
        int     dos
        jc      dmp0                    ; c = failure
        mov     dmphand,ax              ; save file handle
        mov     bx,ax                   ; need handle here
        mov     cx,0ffffh               ; setup file pointer
        mov     dx,-1                   ; and offset
        mov     al,2                    ; move to eof minus one byte
        mov     ah,lseek                ; seek the end
        int     dos
        jmp     dmp1

dmp5:   test    filtst.fstat,80h        ; access problem?
        jnz     dmp0                    ; nz = yes
        mov     ah,creat2               ; file did not exist
        mov     cx,20h                  ; attributes, archive bit
        int     dos
        mov     dmphand,ax              ; save file handle
        jnc     dmp1                    ; nc = ok

dmp0:   mov     ah,3                    ; get cursor position
        xor     bx,bx                   ; page 0
        int     screen
        push    dx                      ; save it
        mov     dh,byte ptr low_rgt+1   ; go to status line
        inc     dh
        xor     dl,dl                   ; left most column
        mov     ah,2                    ; position cursor
        int     screen
        mov     dx,offset dmperr        ; say no can do
        mov     ah,prstr
        int     dos
        pop     dx                      ; get original cursor position
        mov     ah,2                    ; position cursor
        xor     bx,bx                   ; page 0
        int     screen
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        clc
        ret

dmp1:   mov     ah,ioctl                ; is destination ready for output?
        mov     al,7                    ; test output status
        mov     bx,dmphand              ; handle
        int     dos
        jc      dmp0                    ; c = error
        cmp     al,0ffh                 ; ready?
        jne     dmp0                    ; ne = not ready.
        push    di                      ; read screen buffer, write lines
        push    si
        push    es
        mov     cl,byte ptr low_rgt+1   ; number of lines - 2
        add     cl,2                    ; number of line on screen
        xor     ch,ch
        mov     si,savadr               ; offset in storage area
dmp2:   push    cx                      ; save outer loop counter
        mov     es,savadr+2             ; get storage segment
        mov     di,offset dumpbuf       ; data segment memory
        mov     cl,byte ptr savflg      ; number of columns on screen - 1
        inc     cl                      ; number of columns on screen
        xor     ch,ch
dmp3:   mov     ax,word ptr es:[si]     ; read char + trash
        mov     byte ptr [di],al        ; store just char, don't use es:
        inc     si                      ; update pointers
        inc     si
        inc     di
        loop    dmp3                    ; do for each column
        std                             ; set scan backward
        mov     cl,byte ptr savflg      ; number of columns on screen - 1
        inc     cl                      ; number of columns on screen
        xor     ch,ch
        push    es
        mov     ax,ds
        mov     es,ax                   ; set es to data segment for es:di
        mov     di,offset dumpbuf       ; start of line
        add     di,cx                   ; plus length of line
        dec     di                      ; minus 1 equals end of line
        mov     al,' '                  ; thing to scan over
        repe    scasb                   ; scan until non-space
        cld                             ; set direction forward
        pop     es
        jz      dmp3a                   ; z = all spaces
        inc     cx
        inc     di
dmp3a:  mov     word ptr [di+1],0A0Dh   ; append cr/lf
        add     cx,2                    ; line count + cr/lf
        mov     dx,offset dumpbuf       ; array to be written
        mov     bx,dmphand              ; need file handle
        mov     ah,write2               ; write the line
        int     dos
        pop     cx                      ; get line counter again
        jc      dmp3b                   ; c = error
        loop    dmp2                    ; do next line
        mov     dx,offset dumpsep       ; put in formfeed/cr/lf
        mov     cx,3                    ; three bytes overall
        mov     ah,write2               ; write them
dmp3b:  mov     bx,dmphand              ; file handle
        int     dos
        mov     ah,close2               ; close the file now
        int     dos
dmp6:   pop     es
        pop     si
        pop     di
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        clc
        ret
dumpscr endp


; Get CRT mode - returns mode in variable crt_mode,
; updates crt_cols and low_rgt. [jrd]
scrmod  proc    near
        push    ax
        push    dx
        mov     ah,15                   ; Get current video state.
        int     screen
        mov     crt_mode,al             ; Store CRT mode value.
        mov     crt_cols,ah             ; store # of cols [jrd]
        mov     dl,ah                   ; # of cols again
        mov     dh,crt_lins             ; and # of rows (constant from msster)
        dec     dl                      ; max text column, count from zero
        dec     dh                      ; max text row, count from zero
        mov     low_rgt,dx              ; save away window address
        pop     dx
        pop     ax
        ret                             ; And return.
scrmod  endp


; Get screen segment - returns screen segment in ax, and full address in es:di

; modified for NEC; there is only one answer                    RFG
scrseg  proc    near
        mov     ax,vram
        mov     es,ax
        xor     di,di                   ; start at beginning of screen (0,0)
        ret
scrseg  endp

; Synchronize a Topview provided virtual screen buffer with the image
; seen by the user. Requires cx = number of words written to screen
; (char & attribute bytes) and es:di = ENDING address of screen write.
; Changes ax and di.
; Stripped out on NEC          RFG
scrsync proc    near
        ret
scrsync endp

; The following two routines are used to turn off the display while we
; are reading or writing the screen in one of the color card modes.
; Turn screen off for (known) color card modes only. All regs preserved.
; not an NEC required function                                  RFG

scroff  proc    near
        ret                             ; And return.
scroff  endp


; Turn screen on for (known) color card modes only
; All registers are preserved.

scron   proc    near
        ret                             ; And return.
scron   endp


; Screen clearing routine. [IU]
;
; Call:         ax/     coordinates of first screen location to be cleared.
;               bx/     coordinates of last location to be cleared.
; Coord: ah = row [0-24], al = column [0-79]. Preserves all registers. [jrd]
; redone for the NEC in a non-Topview manner                    RFG
atsclr: push    ax
        push    bx
        push    cx
        push    dx
        mov     cx,ax                   ; upper left corner
        mov     dx,bx                   ; lower right corner
        mov     bh,scbattr              ; attribute
        mov     al,0                    ; blank entire window
        mov     ah,6                    ; scroll the page described above
        int     screen
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ret

; Scrolling routines.  vtscru scrolls up one row, vtscrd scrolls down one
; row.  atsprep is called before scrolling up to save the top line in the
; circular buffer. All registers are preserved.

; Screen-roll down. Move text down one line, for terminal emulator only.

vtscrd: push    ax                      ; Upgraded by [jrd]
        push    bx
        push    cx
        push    dx
        mov     ax,701H                 ; scroll down one line
        mov     ch,mar_top              ; top margin line
        mov     cl,0                    ; left most column
        mov     dh,mar_bot              ; bottom margin line
        mov     dl,byte ptr low_rgt     ; right most column
        mov     bh,scbattr              ; attributes
        int     screen                  ; scroll it down
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        clc
        ret
                                        ; worker routine for vtscru/d
atsprep:push    es                      ; upgraded from older version  [jrd]
        call    scrseg                  ; get display address in es:di
        mov     si,di                   ; si will be source
        mov     bx,offset twnd          ; this is where it goes
        call    putcirc                 ; put screen line in circular buffer
        pop     es                      ; and that
        ret                             ; and return


; Screen scroll up one line (text moves up) for terminal emulator use.

vtscru: push    ax                      ; Upgraded by  [jrd]
        push    bx
        push    cx
        push    dx
        push    si
        push    di
        cmp     mar_top,0               ; scrolling the top screen line?
        ja      scru1                   ; a = no. don't save anything
        call    atsprep                 ; save top line
scru1:  mov     ax,601H                 ; scroll up one line
        mov     dh,mar_bot              ; bottom row
        mov     dl,byte ptr low_rgt     ; right most column
        mov     ch,mar_top              ; top row of scrolling region
        mov     cl,0                    ; left most column
        mov     bh,scbattr              ; background attributes
        int     screen                  ; scroll up that region
        pop     di                      ; Restore the rest of the regs.
        pop     si
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        clc
        ret                             ; And return

;screen text roll up, version for manual scrolling only

mscru:  push    ax                      ; Upgraded by  [jrd]
        push    bx
        push    cx
        push    dx
        push    si
        push    di
        cmp     bwnd.lcnt,0             ; any lines in bottom window?
        je      mscru2                  ; e = no, so ignore request
        call    atsprep                 ; save top line
mscru1: mov     ax,601H                 ; scroll up one line
        mov     dx,low_rgt              ; lower right corner
        xor     cx,cx                   ; top row of scrolling region
        mov     bh,scbattr              ; background attributes
        int     screen                  ; scroll up that region
        mov     dx,low_rgt
        mov     dl,0                    ; location is lower left corner
        call    scrloc                  ; get count from display start
        push    es
        push    ax                      ; save count
        call    scrseg                  ; get screen's segment into ax, es:di
        pop     ax                      ; recover count
        add     di,ax                   ; destination memory address (es:di)
        mov     bx,offset bwnd          ; source of lines
        call    getcirc                 ; get line from circ buf to screen
        pop     es                      ; restore es
mscru2: pop     di                      ; Restore the rest of the regs.
        pop     si
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ret


; prep for screen scroll down. [jrd]
; copies bottom scroll line from screen to bottom window buffer.
; destroys ax,cx,dx,si,di.
getbot proc near                        ; Upgraded from old version [jrd]
        push    es
        mov     dx,low_rgt              ; from screen location, row
        mov     dl,0                    ; starting in col 0
        call    scrseg                  ; get adaptor's offset into es:di
        call    scrloc                  ; get offset in display buffer in ax
        add     di,ax                   ; source addr in display buffer es:di
        mov     si,di                   ; screen is source (si)
        mov     bx,offset bwnd          ; buffer to use (bottom window)
        call    putcirc                 ; copy bottom screen line to circ buf
        pop     es
        ret
getbot endp

;screen text scroll down, for manual mode only
mscrd:  push    ax                      ; Upgraded by [jrd]
        push    bx
        push    cx
        push    dx
        push    si
        push    di
        cmp     twnd.lcnt,0             ; any lines left in top window?
        je      mscrd1                  ; e = no, ingore request
        call    getbot                  ; fetch bottom line from screen
        mov     ax,701H                 ; scroll down one line
        xor     cx,cx                   ; top left corner
        mov     dx,low_rgt              ; bottom right corner
        mov     bh,scbattr              ; attributes
        int     screen                  ; scroll it down
        push    es
        call    scrseg                  ; get segment address of screen
        mov     bx,offset twnd          ; buffer to use (top window)
        call    getcirc                 ; copy from circ buf to screen
        pop     es
mscrd1: pop     di                      ; Restore the rest of the ACs.
        pop     si
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ret

; move viewing window down as much as possible (text moves up)
endwnd  proc    near                    ; go to end of scrolling text
	push	cx
        mov     cx,bwnd.lcnt            ; all bottom window lines [dlk]
        jmp     dnwp0                   ; and enter dwnpg
endwnd  endp

dnone   proc    near                    ; move text up one line [jrd]
	push	cx
        mov     cx,1
        jmp     dnwp0
dnone   endp

; scroll viewing window down (text moves up) one page (24 lines)
dnwpg   proc    near
	push	cx
        mov     cl,byte ptr low_rgt+1   ; number of rows, excl status
        inc     cl                      ; count from 1, not 0
        mov     ch,0
dnwp0:                                  ; additional entry point
        cmp     bwnd.lcnt,cx            ; enough lines in bottom line buffer?
        jge     dnwp1                   ; ge = we have that many lines stored
        mov     cx,bwnd.lcnt            ; do as many as we have
dnwp1:  jcxz    dnwp2                   ; z = nothing to do
	cmp	tekflg,0		; Tek mode active?
	jne	dnwp2			; ne = yes, no scrolling
        call    mscru                   ; scroll up text one line
        loop    dnwp1
dnwp2:  pop	cx
	clc
        ret
dnwpg   endp

; home viewing window
homwnd  proc    near
	push	cx
        mov     cx,twnd.lcnt            ; all top window lines [dlk]
        jmp     upwp0                   ; join upwpg
homwnd  endp

upone   proc    near                    ; move text down one line [jrd]
	push	cx
        mov     cx,1
        jmp     upwp0
upone   endp

; scroll viewing window up (text moves down) a page (24 lines)
upwpg   proc    near
	push	cx
        mov     cl,byte ptr low_rgt+1   ; number of rows, excl status line
        inc     cl                      ; count from 1, not 0
        mov     ch,0
upwp0:                                  ; additional entry point
        cmp     twnd.lcnt,cx            ; enough lines in top line buffer?
        jae     upwp1                   ; ae = at least as many as requested
        mov     cx,twnd.lcnt            ; do only as many as are stored.
upwp1:  jcxz    upwp2                   ; z = no lines to scroll
	cmp	tekflg,0		; Tek mode active?
	jne	upwp2			; ne = yes, no scrolling
        call    mscrd                   ; roll down text one line
        loop    upwp1
upwp2:  pop	cx
	clc
        ret
upwpg   endp


; Put a line into the circular buffer.  Pass the buffer structure in bx.
; Source is vram:si which is the current screen address.
; Rewritten by [jrd]
; Modified for the NEC screen attribute structure -- RFG
putcirc proc    near
        push    es
        mov     cl,crt_cols             ; number of columns
        xor     ch,ch
        mov     es,[bx].orig            ; get segment of memory area
        cmp     bx,offset bwnd          ; bottom buffer?
        je      putci6                  ; e = yes
        mov     di,twnd.pp              ; pick up buffer ptr (offset from es)
        add     di,cx                   ; increment to next available slot
        add     di,cx                   ; char and attribute
        cmp     di,twnd.bend            ; would line extend beyond buffer?
        jb      putci1                  ; b = not beyond end
        mov     di,0                    ; else start at the beginning
putci1: mov     twnd.pp,di              ; update ptr
        cld                             ; set direction to forward
        push    ds                      ; save regular datas seg reg
        push    ax
        mov     ax,vram                 ; video memory segment
        mov     ds,ax                   ; use screen segment for ds:si
putci1z:                                ; NEC mod starts here -- RFG
        movsb                           ; transfer a text byte
        mov     ax,si                   ; remember 'movsb' incremented di
        add     ax,1FFFH                ; point at the attribute
        mov     si,ax
        movsb                           ; transfer an attribute byte
        dec     cx                      ; count one full character
        mov     ax,si
        sub     ax,1FFFH                ; point at the next text
        mov     si,ax
        cmp     cx,0                    ; have we done it all?
        jne     putci1z                 ; no, keep truckin'
;                                       ; end of NEC mod -- RFG
        pop     ax
        pop     ds                      ; restore regular datas segment
        mov     cx,twnd.lmax            ; line capacity of buffer
        dec     cx                      ; minus one work space line
        cmp     twnd.lcnt,cx            ; can we increment line count?
        jae     putci1b                 ; ae = no, keep going
        inc     twnd.lcnt               ; else count this line
putci1b:cmp     bwnd.lcnt,0             ; any lines in bottom buffer?
        je      putci2                  ; e = no
        mov     cx,bwnd.pp              ; see if we overlap bot buf
        cmp     cx,twnd.pp              ; is this line in bot buf area?
        jne     putci2                  ; ne = no
        add     cl,crt_cols             ; move bottom pointer one slot earlier
        adc     ch,0
        add     cl,crt_cols             ; words
        adc     ch,0
        cmp     cx,bwnd.bend            ; beyond end of buffer?
        jb      putci1a                 ; b = no
        mov     cx,0                    ; yes, start at beginning of buffer
putci1a:mov     bwnd.pp,cx              ; new bottom pointer
        dec     bwnd.lcnt               ; one less line in bottom buffer
putci2: pop     es
        ret
putci6:                                 ; bottom buffer
        add     cx,cx                   ; words worth
        cmp     bwnd.lcnt,0             ; any lines in the buffer yet?
        jne     putci7                  ; ne = yes
        mov     di,twnd.pp              ; get latest used slot of top buff
        add     di,cx                   ; where first free (?) slot starts
        cmp     di,bwnd.bend            ; are we now beyond the buffer?
        jb      putci6a                 ; b = no
        mov     di,0                    ; yes, start at beginning of buffer
putci6a:add     di,cx                   ; start of second free (?) slot
        cmp     di,bwnd.bend            ; are we now beyond the buffer?
        jb      putci6b                 ; b = no
        mov     di,0                    ; yes, start at beginning of buffer
putci6b:mov     cx,twnd.lmax            ; buffer line capacity
        sub     cx,twnd.lcnt            ; minus number used by top buffer
        sub     cx,2                    ; minus one work slot and one we need
        cmp     cx,0                    ; overused some slots?
        jge     putci8                  ; ge = enough to share
        add     twnd.lcnt,cx            ; steal these from top window beginning
        jmp     short putci8
putci7: mov     es,bwnd.orig            ; get segment of memory area
        mov     di,bwnd.pp              ; pick up buffer ptr (offset from es)
        cmp     di,0                    ; would line start before buffer?
        jne     putci7a                 ; ne = after start of buffer
        mov     di,bwnd.bend            ; else start at the end minus one slot
        inc     di
putci7a:sub     di,cx
putci8: mov     bwnd.pp,di              ; update ptr (this is latest used slot)
        mov     cl,crt_cols
        xor     ch,ch
        cld                             ; set direction to forward
        push    ds                      ; save regular datas seg reg
        push    ax
        mov     ax,vram                 ; video memory segment
        mov     ds,ax                   ; use screen segment for ds:si
putci8z:                                ; NEC mod starts here -- RFG
        movsb                           ; transfer a text byte
        mov     ax,si
        add     ax,1FFFH                ; point at the attribute
        mov     si,ax
        movsb                           ; transfer an attribute byte
        dec     cx                      ; count one full character
        mov     ax,si
        sub     ax,1FFFH                ; point at the text
        mov     si,ax
        cmp     cx,0                    ; have we done it all?
        jne     putci8z                 ; no, keep truckin'
;                                       ; end of NEC mod -- RFG
        pop     ax
        pop     ds                      ; restore regular datas segment
        mov     cx,bwnd.lmax            ; line capacity of buffer
        cmp     bwnd.lcnt,cx            ; can we increment line count?
        jae     putci8b                 ; ae = no, keep going
        inc     bwnd.lcnt               ; else count this line
putci8b:cmp     twnd.lcnt,0             ; any lines in top line buf?
        je      putci9                  ; e = no
        mov     cx,twnd.pp              ; yes, see if we used last top line
        cmp     cx,bwnd.pp              ; where we just wrote
        jne     putci9                  ; not same place, so all is well
        dec     twnd.lcnt               ; one less line in top window
        cmp     cx,0                    ; currently at start of buffer?
        jne     putci8a                 ; ne = no
        mov     cx,twnd.bend            ; yes
        inc     cx
putci8a:sub     cl,crt_cols             ; back up top window
        sbb     ch,0
        sub     cl,crt_cols             ; by one line
        sbb     ch,0
        mov     twnd.pp,cx              ; next place to read
putci9: pop     es
        ret

putcirc endp

; Get a line from the circular buffer, removing it from the buffer.
; returns with carry on if the buffer is empty.
; Pass the buffer structure in bx.
; Destination preset in es:di which is the current screen address.
; Rewritten by [jrd]
getcirc proc    near
        cmp     [bx].lcnt,0             ; any lines in buffer?
        jne     getci1                  ; ne = yes, ok to take one out.
        stc                             ; else set carry
        ret                             ; and return
getci1:                                 ; top and bottom window common code
        mov     cl,crt_cols             ; # of chars to copy
        xor     ch,ch
        push    cx                      ; save around calls
        mov     si,[bx].pp              ; this is source
        cld                             ; set direction to forward
        push    ds                      ; save original ds
        mov     ds,[bx].orig            ; use seg address of buffer for si
getci1z:                                ; NEC mod starts here -- RFG
        movsb                           ; transfer a text byte
        mov     ax,di                   ; remember 'movsb' incremented di
        add     ax,1FFFH                ; point at the attribute
        mov     di,ax
        movsb                           ; transfer the attribute byte
        dec     cx                      ; count one full character
        mov     ax,di
        sub     ax,1FFFH                ; point at the next text byte
        mov     di,ax
        cmp     cx,0                    ; have we done it all?
        jne     getci1z                 ; no, keep truckin'
;                                       ; NEC mod ends here -- RFG
        pop     ds                      ; recover original data segment
        pop     cx                      ; length for Topview
        push    cx                      ; save again
        mov     si,[bx].pp              ; get ptr again
        pop     cx
        add     cx,cx                   ; words
        cmp     bx,offset bwnd          ; bottom window?
        je      getci6                  ; e = yes
        sub     si,cx                   ; top window, move back
        jnc     getcir2                 ; nc = still in buffer, continue
        mov     si,twnd.bend            ; else use end of buffer
        sub     si,cx                   ; minus length of a piece
        inc     si
getcir2:mov     twnd.pp,si              ; update ptr
        dec     twnd.lcnt               ; decrement # of lines in buffer
        clc                             ; make sure no carry
        ret
getci6:                                 ; bottom window
        add     si,cx                   ; words, move back (bot buf = reverse)
        cmp     si,bwnd.bend            ; still in buffer?
        jb      getci7                  ; b = yes
        mov     si,0                    ; else use beginning of buffer
getci7: mov     bwnd.pp,si              ; update ptr
        dec     bwnd.lcnt               ; decrement # of lines in buffer
        clc                             ; make sure no carry
        ret
getcirc endp

;
; CHKDSP - procedure to check for hardware support of 132 cols [dlk]
;
chgdsp  proc    near
        ret                             ; return to caller
chgdsp  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

code    ends

if1
        %out [End of pass 1]
else
        %out [End of assembly]
endif

        end
