home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / mskermit / msxapc.asm < prev    next >
Assembly Source File  |  2020-01-01  |  65KB  |  1,756 lines

  1.         name msxapc
  2. ; File MSXAPC.ASM
  3. ; Last modification: 20 April 1986
  4.  
  5. ; System dependent module for NEC APC
  6. ; ************ START MSXAPC.ASM ***********************************
  7.  
  8. ; Kermit system dependent module for NEC Advanced Personal Computer (APC)
  9. ; Ron Blanford, University of Washington, August 1984
  10.  
  11. ; Added global entry point vstat for use by Status in mssset.
  12. ; Also trimmed off trailing commas in publics. Joe R. Doupnik 12 March 1986
  13. ; Add global procedures ihosts and ihostr to handle host initialization
  14. ; when packets are to be sent or received by us,resp. 24 March 1986
  15. ; Add global procedure dtrlow (with discon in place of serhng) to force DTR
  16. ; and RTS low in response to Kermit command Hangup. [jrd]
  17. ; Add global procedure Dumpscr, called by Ter in file msster, to dump screen
  18. ;  to a file. Just does a beep for now. 13 April 1986 [jrd]
  19. ; Include modifications by Ron Blanford to Dobaud and Getbaud. 14 April 1986
  20. ; In proc Outchr add override of xon from chkxon sending routine.
  21. ;  This makes a hand typed Xoff supress the xon flow control character sent
  22. ;  automatically as the receiver buffer empties. 20 April 1986 [jrd]
  23. ;
  24. ;
  25. ; Modified to get key scan codes directly from fifo buffer in IO.SYS
  26. ; This version works with MS-DOS Versions 2.00 (000) and 2.11 (001); it
  27. ; should work with future MS-DOS revisions so long as NECIS maintains
  28. ; the configuration table in IO.SYS -  the thing most apt to fail is the
  29. ; key autorepeat because kbrepflg is furthest from a hook in config table.
  30. ; If this happens the equate for offset of kbrepflg will need adjusting.
  31. ; Ian Gibbons, University of Hawaii, 10/26/84
  32.  
  33. ; Fixed incorrect timer command port assignment so that program will run
  34. ;   under MS-DOS 2.00 as well as 2.11.
  35. ; Added autodetermination of color/mono using crttype byte in IO.SYS; this
  36. ;   works only under DOS 2.11 (and future above ?)
  37. ; IG 10/28/84
  38. ; Added direct CRT I/O handling through BIOS in order to increase speed and
  39. ;  flexibility of help menus. It gives only an imitation window but it works
  40. ;  fairly well.
  41. ; IG 10/31/84
  42. ; Added simplified mode line data to the [Connecting to host...]" line which
  43. ;  has been moved here from MSTERM in order to have more system dependent
  44. ;  control.
  45. ; IG 11/4/84
  46. ; Make unredefined break/stop key act as a scroll/noscroll key in telnet by
  47. ;  sending alternately a ^S and a ^Q.
  48. ; IG 11/5/84
  49. ; By now code for this MSXAPC module could well be divided into separate
  50. ;  transmission and terminal modules, but I don't want to spend more time
  51. ;  on it. It's not as readable as it might be, but so far as I know
  52. ;  everything works.IG 11/6/84
  53.  
  54.         public  serini, serrst, clrbuf, outchr, coms, vts, vtstat, dodel
  55.         public  ctlu, cmblnk, locate, lclini, lclrst, prtchr, dobaud
  56.         public  discon, clearl, dodisk, getbaud, beep
  57.         public  count, xofsnt, puthlp, putmod, clrmod, poscur
  58.         public  sendbr, term, machnam, setktab, setkhlp, showkey
  59.         public  ihosts, ihostr, dtrlow, dumpscr                 ; [jrd]
  60.         include mssdef.h
  61.  
  62. false   equ     0
  63. true    equ     1
  64.  
  65. BIOS    EQU     0DCH            ; NEC-APC BIOS interrupt call
  66. fifoclr equ     6               ; clears keyboard fifo buffer
  67. crtcmd  equ     7               ; Direct CRT I/O command call
  68.  
  69. ; port assignments for 8251 serial controllers
  70.  
  71. ;               Standard interface
  72.  
  73. mndata  equ     30H             ; Data port (read/write)
  74. mnst1a  equ     32H             ; Status port (when read)
  75. mncmda  equ     32H             ; Command port (when written)
  76. mnst2a  equ     34H             ; Alternate status port (when read)
  77. mnmska  equ     34H             ; Mask port (when written)
  78. mntdca  equ     36H             ; Transmit disable port (write only)
  79.  
  80. ;               Optional (H14) interface
  81.  
  82. mndatb  equ     31H             ; Data port (read/write)
  83. mnst1b  equ     33H             ; Status port (when read)
  84. mncmdb  equ     33H             ; Command port (when written)
  85. mnst2b  equ     35H             ; Alternate status port (when read)
  86. mnmskb  equ     35H             ; Mask port (when written)
  87. mntdcb  equ     37H             ; Transmit disable port (write only)
  88.  
  89. ; Status bits from mnst1
  90.  
  91. txrdy   equ     01H             ; Bit for output ready.
  92. rxrdy   equ     02H             ; Bit for input ready.
  93.  
  94. ; Command values for mncmd
  95.  
  96. ccmd    equ     37H             ; RTS & DTR high, RX & TX enabled, reset ERR
  97. cbrk    equ     08H             ; break enabled
  98. cmode   equ     40H             ; enable mode reset
  99. mmode   equ     4EH             ; 16x rate, 8 data, no parity, 1 stop
  100.  
  101. ; Mask values for mnmsk
  102.  
  103. txmsk   equ     01H             ; disables transmit ready interrupt
  104. rxmsk   equ     02H             ; disables receive ready interrupt
  105. tbemsk  equ     04H             ; disables transmit buffer empty interrupt
  106.  
  107.  
  108. ; port assignments for 8253 timers
  109.  
  110. ;               Standard interface
  111.  
  112. tmdata  equ     2BH             ; data port
  113. tmcmda  equ     2FH             ; command port  (Was 27H Ian 10/27/84)
  114.  
  115. ;               Optional (H14) interface
  116.  
  117. tmdatb  equ     61H             ; data port
  118. tmcmdb  equ     67H             ; command port
  119.  
  120. ; values for tmcmd which select timer channel and mode
  121.  
  122. tmsela  equ     76H             ; Channel 1, mode 3 (standard port)
  123. tmselb  equ     36H             ; Channel 0, mode 3 (optional port)
  124.  
  125. ; Timer information for current port selection
  126.  
  127. tmrinfo struc
  128. tmdat   dw      0               ; data port
  129. tmcmd   dw      0               ; command port
  130. tmsel   db      0               ; byte which selects channel and mode
  131. tmrinfo ends
  132.  
  133.  
  134. ; port assignments for 8259 interrupt controllers
  135.  
  136. ;               Standard interface
  137.  
  138. intcmda equ     20H             ; Command port (master controller)
  139. intmska equ     22H             ; Mask port
  140. ictmsk  equ     08H             ; Timer interrupt mask (to master)
  141. icsmska equ     02H             ; Standard serial interrupt mask (to master)
  142. icsvcta equ     11H             ; Interrupt vector for standard interface
  143.  
  144. ;               Optional (H14) interface
  145.  
  146. ; The interrupt request vector for the optional (H14) serial interface is
  147. ; jumper-selectable to any of vectors IR2, IR5, IR8, or IR12.  NEC recommends
  148. ; that IR8 be used, so that has been selected as the default here.  To use
  149. ; any of the other vectors, set the following conditionals appropriately.
  150. ; Only one of the following should be true:
  151.  
  152. IR2     equ     false           ; interrupt vector 2
  153. IR5     equ     false           ; interrupt vector 5
  154. IR8     equ     true            ; interrupt vector 8
  155. IR12    equ     false           ; interrupt vector 12
  156.  
  157.         IF IR2
  158. intcmdb equ     20H             ; Command port (master controller)
  159. intmskb equ     22H             ; Mask port
  160. icsmskb equ     04H             ; Interrupt mask
  161. icsvctb equ     12H             ; Interrupt table index
  162.         ENDIF
  163.  
  164.         IF IR5
  165. intcmdb equ     20H             ; Command port (master controller)
  166. intmskb equ     22H             ; Mask port
  167. icsmskb equ     20H             ; Interrupt mask
  168. icsvctb equ     15H             ; Interrupt table index
  169.         ENDIF
  170.  
  171.         IF IR8
  172. intcmdb equ     28H             ; Command port (slave controller)
  173. intmskb equ     2AH             ; Mask port
  174. icsmskb equ     02H             ; Interrupt mask
  175. icsvctb equ     19H             ; Interrupt table index
  176.         ENDIF
  177.  
  178.         IF IR12
  179. intcmdb equ     28H             ; Command port (slave controller)
  180. intmskb equ     2AH             ; Mask port
  181. icsmskb equ     20H             ; Interrupt mask
  182. icsvctb equ     1DH             ; Interrupt table index
  183.         ENDIF
  184.  
  185. crtinfo struc           ; Structure for color/mono formatting info
  186. nrmseq  db      esc,'[0m$'      ; Default
  187. invseq  db      esc,'[7m$000'   ; Inverse (extra space for color)
  188. bldseq  db      esc,'[17m$'     ; Bold video
  189. nrmcrt  dw      8080H           ; Normal data for direct crt i/o
  190. bldcrt  dw      9090H           ; Inverse data for direct crt i/o
  191.  
  192. crtinfo ends
  193.  
  194.  
  195. icEOI   equ     20H             ; generic end of interrupt for intcmd
  196. kbfifosiz equ   64              ; size of fifo buffer in IO.SYS
  197.  
  198.  
  199. ; miscellaneous constants
  200.  
  201. ctrlP   equ     10H             ; ^P.
  202. ctrl_q  equ     11H             ; ^Q
  203. ctrl_s  equ     13H             ; ^S
  204. printkey equ    00FFH           ; Scan code of unshifted PRINT key.
  205. brkstp  equ     0096H           ; Scan code of unshifted break/stop key.
  206. mntrgh  equ     bufsiz*3/4      ; High XON/XOFF trigger = 3/4 of buffer full.
  207.  
  208. ; external variables used:
  209. ; drives - # of disk drives on system
  210. ; flags - global flags as per flginfo structure defined in pcdefs
  211. ; trans - global transmission parameters, trinfo struct defined in pcdefs
  212. ; portval - pointer to current portinfo structure (currently either port1
  213. ;    or port2)
  214. ; port1, port2 - portinfo structures for the corresponding ports
  215.  
  216. ; global variables defined in this module:
  217. ; xofsnt, xofrcv - tell whether we saw or sent an xoff.
  218.  
  219. datas   segment public 'datas'
  220.         extrn   drives:byte,flags:byte, trans:byte
  221.         extrn   portval:word, port1:byte, port2:byte, dmpname:byte ; [jrd]
  222.  
  223. machnam db      'NEC APC$'
  224. nyimsg  db      cr,lf,'Not implemented$'
  225. badbd   db      cr,lf,'Unimplemented baud rate$'
  226. bdkscn  db      cr,lf,'Unable to install key translate table'
  227.         db      cr,lf,'Possibly incompatible MS-DOS version',cr,lf
  228.         db      cr,lf,'(MS-KERMIT can be used without keyboard translation'
  229.         db      ' feature)',cr,lf,'$'
  230. nokbtr  db      cr,lf,'No key translation table is installed$'
  231. hngmsg  db      cr,lf,' The phone should have hungup.',cr,lf,'$' ; [jrd]
  232. hnghlp  db      cr,lf,' The modem control lines DTR and RTS for the current'
  233.         db      ' port are forced low (off)'
  234.         db      cr,lf,' to hangup the phone. Normally, Kermit leaves them'
  235.         db      ' high (on) when it exits.'
  236.         db      cr,lf,'$'                                       ; [jrd]
  237. rdbuf   db      80 dup (?)      ; temp buf [jrd]
  238. prtmsg  db      cr,lf,'You cannot redefine the PRINT key$'
  239. escmsg  db      cr,lf,'You cannot redefine the current CTRL-ESCAPE key$'
  240. hngcfm  db      cr,lf,'Please confirm DISCONNECT command. (Y/N)  $'
  241. dismsg  db      cr,lf,'Disconnecting for 3 seconds',cr,lf,'$'
  242. rcnmsg  db      cr,lf,'Reconnected',cr,lf,'$'
  243. cnmsg   db      cr,lf,'Connecting to host at '
  244. cnmsgb  db      '     '
  245.         db      ' baud on port '
  246. cnmsgp  db      ' ',cr,lf,'(Type $'
  247. cnmsg1  db      ' C  to return to PC)',cr,lf,lf,lf,'$'
  248. crlf    db      cr,lf,'$'
  249. delstr  db      BS,BS,' ',BS,'$'        ; Delete string.
  250. clrlin  db      cr,'$'          ; Clear line (just the cr part).
  251. ceolseq db      esc,'[K$'       ; Clear to end of line
  252. cpseq   db      esc,'=rc'       ; rc replaced by row and column before display
  253. clrseq  db      01EH,01AH,'$'   ; Home cursor and clear screen
  254. lstpos  dw      0               ; column position for printer echoing
  255.  
  256. ; Storage for color and mono formatting strings
  257.  
  258. nrmcol  db      esc,'[0m$'
  259. invcol  db      esc,'[3;21m$'   ; Yellow with green overline
  260. bldcol  db      esc,'[21m$'     ; Yellow
  261. ncrtcol dw      8080H           ; Green
  262. bcrtcol dw      0A0A0H          ; Yellow
  263.  
  264. ;nrmmon db      esc,'[0m$'
  265. ;invmon db      esc,'[7m$000'   ; Inverse video
  266. ;bldmon db      esc,'[17m$'     ; Bold video
  267. ;ncrtmon        dw      8080H           ; Normal green
  268. ;bcrtmon dw     9090H           ; Inverse video
  269.  
  270. formdat crtinfo <>
  271. formdtl db      $-formdat
  272.  
  273. nocur   db      esc,'[>5h$'     ; Disable cursor
  274. recur   db      esc,'[>5l$'     ; Reenable cursor
  275. storcur db      esc,'[s$'       ; Store cursor position
  276. rstcur  db      esc,'[u$'       ; Restore cursor position
  277. upcur   db      esc,'[A$'       ; Move cursor up one line
  278. savcur  dw      0               ; storage for cursor position
  279. msglns  db      0               ; No of lines in help message
  280. rnoc    dw      0               ; Raw NOC for screen write
  281.  
  282. ; Data area for direct CRT I/O
  283.  
  284. EVEN                            ; Force alignment to word boundary
  285. dispadr db      2000 dup (0)    ; Storage for string data
  286. attradr db      2000 dup (0)    ; Storage for attribute data
  287.  
  288. ; Command block for direct CRT I/O
  289.  
  290. cmd     db      0               ; CRT command number
  291. la      db      0               ; Line address   (0-24 binary)
  292. ca      db      0               ; Column address (0-79 binary)
  293. noc     dw      0               ; Number of chars (0-2000 binary)
  294. dispptr dw      dispadr         ; Pointer to string data block
  295. dispseg dw      datas           ;
  296. attrptr dw      attradr         ; Pointer to attribute data block
  297. attrseg dw      datas
  298.  
  299. ourarg  termarg <>
  300. modem   mdminfo <mndata,mnst1a,mncmda,0,0,0,0>
  301. timer   tmrinfo <tmdata,tmcmda,tmsela>
  302.  
  303. ourflgs db      0               ; Flags for telnet options
  304. fprint  equ     80H             ;   echo screen output to printer
  305. movcur  equ     40H             ;   cursor moved - needs resetting
  306. kbtrflg equ     20H             ;   local flag showing if kb trans.is enabled
  307. autorepflg equ  10H             ;   is this an autorepeat cycle
  308. inited  equ     8H              ;   are we initiating first call to term
  309. tlnxof  equ     4H              ;   have we sent a ^S in telnet with brk/stp
  310. savscn  dw      0               ; save last key-in for auto repeat if needed
  311. escscan dw      0               ; scan code for current ctrl-escape key
  312.  
  313. oldsera dw      ?               ; old serial handler for standard port
  314. oldsega dw      ?               ; segment of above
  315. oldmska db      ?               ; old interrupt controller mask
  316. portina db      0               ; Has comm port been initialized.
  317.  
  318. oldserb dw      ?               ; old serial handler for optional port
  319. oldsegb dw      ?               ; segment of same.
  320. oldmskb db      ?               ; old interrupt controller mask
  321. portinb db      0               ; Has comm port been initialized.
  322.  
  323. dosseg  dw      40H             ; Segment  to read IO.SYS
  324. zero    dw      0               ; Use to load segment regs for low core
  325.  
  326. ; Space for addresses in IO.SYS to be calculated at run time in 'lclini'
  327.  
  328. configptr equ   3H              ; Offset of pointer to base of config table
  329. configbas dw    0               ; base address of config table in IO.SYS
  330. fifobas dw      0               ; equ   0A62H for DOS 2.11
  331.  
  332. ; offsets from configbas
  333. statlnptr equ   0CH
  334. kbinptr   equ   2CH             ; kbin addr = base of fifodata area (fifobas)
  335. crtptr    equ   48H
  336.  
  337. ; offsets from fifobas
  338. kbin    equ     0                       ; fifobas
  339. kbout   equ     1                       ; fifobas + 1
  340. kbfifo  equ     2                       ; fifobas + 2
  341. sfkeyflg equ    043H                    ; fifobas + 043H
  342. kbrepflg equ    0D9H                    ; fifobas + 0D9H
  343.  
  344. xofsnt  db      0               ; Say if we sent an XOFF.
  345. xofrcv  db      0               ; Say if we received an XOFF.
  346.  
  347. ; variables for serial interrupt handler
  348. source  db      bufsiz DUP (?)  ; Buffer for data from port.
  349. srcpnt  dw      0               ; Pointer in buffer (DI).
  350. count   dw      0               ; Number of chars in int buffer.
  351. savesi  dw      0               ; Save SI register here.
  352.         dw      80 DUP (?)      ; local stack for interrupt processing
  353. mnstk   dw      ?
  354. mnsp    dw      ?               ; remote stack info
  355. mnsseg  dw      ?
  356.  
  357. shkbuf  db      300 dup (?)     ; room to display key definition
  358. shkmsg  db      '  Scan code: '
  359. shkmln  equ     $-shkmsg
  360. shkms1  db      cr,lf,'  Definition: '
  361. shkm1ln equ     $-shkms1
  362.  
  363. setktab db      24
  364.         mkeyw   'BACKSPACE',9CH
  365.         mkeyw   'F1',80H
  366.         mkeyw   'F2',81H
  367.         mkeyw   'F3',82H
  368.         mkeyw   'F4',83H
  369.         mkeyw   'F5',84H
  370.         mkeyw   'F6',85H
  371.         mkeyw   'F7',86H
  372.         mkeyw   'F8',87H
  373.         mkeyw   'F9',88H
  374.         mkeyw   'F10',89H
  375.         mkeyw   'F11',8AH
  376.         mkeyw   'F12',8BH
  377.         mkeyw   'F13',8CH
  378.         mkeyw   'F14',8DH
  379.         mkeyw   'F15',8EH
  380.         mkeyw   'F16',8FH
  381.         mkeyw   'F17',90H
  382.         mkeyw   'F18',91H
  383.         mkeyw   'F19',92H
  384.         mkeyw   'F20',93H
  385.         mkeyw   'F21',94H
  386.         mkeyw   'F22',95H
  387.         mkeyw   'SCAN',-1
  388.  
  389. setkhlp db      cr,lf,'Either keyname:  Backspace, F1, ...,F22',cr,lf
  390.         db            '  or   "SCAN" followed by scan code'
  391.         db      ' (given by SHOW KEY)',cr,lf,'$'
  392.  
  393. comptab db      7
  394.         mkeyw   '1',1
  395.         mkeyw   '2',0
  396.         mkeyw   'COM1',1
  397.         mkeyw   'COM2',0
  398.         mkeyw   'H14',0
  399.         mkeyw   'OPTIONAL',0
  400.         mkeyw   'STANDARD',1
  401.  
  402. bddat   label   word
  403.         dw      0D30H           ; 45.5 baud
  404.         dw      0C00H           ; 50 baud
  405.         dw      0800H           ; 75 baud
  406.         dw      0574H           ; 110 baud
  407.         dw      0476H           ; 134.5 baud
  408.         dw      0400H           ; 150 baud
  409.         dw      0200H           ; 300 baud
  410.         dw      0100H           ; 600 baud
  411.         dw      0080H           ; 1200 baud
  412.         dw      0055H           ; 1800 baud
  413.         dw      004DH           ; 2000 baud
  414.         dw      0040H           ; 2400 baud
  415.         dw      0020H           ; 4800 baud
  416.         dw      0010H           ; 9600 baud
  417.         dw      0008H           ; 19200 baud
  418.         dw      0004H           ; 38400 baud (not tested - may not work)
  419.  
  420. ; some static data for mode line
  421.  
  422. unkbaud db      ' Unk '                 ; must be 5 chars...
  423. baudn   db      ' 45.5'                 ;               [g4 start]
  424.         db      '  50 '
  425.         db      '  75 '
  426.         db      ' 110 '
  427.         db      ' 135 '
  428.         db      ' 150 '
  429.         db      ' 300 '
  430.         db      ' 600 '
  431.         db      ' 1200'
  432.         db      ' 1800'
  433.         db      ' 2000'
  434.         db      ' 2400'
  435.         db      ' 4800'
  436.         db      ' 9600'
  437.         db      '19200'         ;               [g4 end]
  438. baudnsiz  equ   15              ; # of baud rates known (tbl size / 5)
  439.  
  440. datas   ends
  441.  
  442.  
  443. code    segment public 'code'
  444.         extrn   comnd:near, dopar:near, escprt:near
  445.         extrn   sleep:near                              ; [jrd]
  446.         assume  cs:code,ds:datas
  447.  
  448. ; local initialization routine, called by Kermit initialization.
  449.  
  450. LCLINI  PROC    NEAR
  451.         cld
  452.         mov flags.vtflg,0       ; turn off heath emulation
  453.         push es
  454.         mov es,dosseg
  455.         mov bx,configptr
  456.         mov bx,es:[bx]          ; Get offset of configuration table in IO.SYS
  457.         mov configbas,bx        ; store it
  458.         mov cl,fifoclr          ; Clear fifobuffer in case user has been
  459.         int bios                ;  typing while program was loading
  460.         mov bx,es:[bx].kbinptr  ; Should be address of kbin
  461.         mov cl,es:[bx]          ; Confirm we're in right location
  462.         cmp cl,byte ptr es:1[bx] ; by showing kbin = kbout
  463.         jne lclin1              ; Fails for DOS 2.00 (no kbinptr)
  464.         mov fifobas,bx          ; Kbin is base of fifo area
  465.         or ourflgs,kbtrflg      ; Show we have a key tranlate table
  466.         jmp short lclin2        ; Localization finished
  467. lclin1: mov bx,configbas        ; DOS 2.00 does have pointer to status line
  468.         mov bx,es:[bx].statlnptr ; Address of 'MS-DOS' in status line
  469.         sub bx,6BH                      ; Work back to where kbin should be
  470.         mov cl,es:[bx]                  ; Confirm we're in right location
  471.         cmp cl,byte ptr es:1[bx]        ;  by showing kbin = kbout
  472.         jnz lclin3              ; Nothing else to try - report failure
  473.         mov fifobas,bx          ; We've made it!
  474.         or  ourflgs,kbtrflg     ; Show we have a key tranlate table
  475.         xor ax,ax               ; Set zero flag for mono format default
  476.         jmp short lcli20
  477. lclin2: mov bx,configbas
  478.         mov bx,es:[bx].crtptr           ; Get address of crttype byte
  479.         mov al,es:[bx]                  ; get the crttype byte
  480.         test al,1                       ; Is it a color crt?
  481. lcli20: mov dx,ds                       ; DOS 2.00 has no crt data and
  482.         mov es,dx                       ;   and defaults to mono
  483.         mov cl,formdtl                  ; Length of crt format block
  484.         mov di,offset formdat           ; Where we want data
  485.         jnz lcli21                      ; No, it's color
  486.         jmp short lclin4
  487. lcli21: mov si,offset nrmcol            ; Source of color data
  488.         rep movsb                       ; Move data to working location
  489.         jmp short lclin4
  490. lclin3: mov dx,offset bdkscn
  491.         call tmsg
  492.         and ourflgs,not kbtrflg         ; Show no translate table enabled
  493. lclin4: mov dx,offset formdat.nrmseq    ; set to our normal background color
  494.         call tmsg
  495.         pop es
  496.         ret
  497. LCLINI  ENDP
  498.  
  499. ; Local reset routine, called upon exit from Kermit
  500.  
  501. LCLRST  PROC    NEAR
  502.         ret
  503. LCLRST  ENDP
  504.  
  505. ; this is called by Kermit initialization.  It checks the
  506. ; number of disks on the system, sets the drives variable
  507. ; appropriately.  The only problem is that a value of two
  508. ; is returned for single drive systems to be consistent
  509. ; with the idea of the system having logical drives A and
  510. ; B.  Returns normally.
  511.  
  512. DODISK  PROC    NEAR
  513.         mov ah,gcurdsk          ; current disk value to AL.
  514.         int dos
  515.         mov dl,al               ; put current disk in DL.
  516.         mov ah,seldsk           ; select current disk.
  517.         int dos                 ; get number of drives in AL.
  518.         mov drives,al
  519.         ret
  520. DODISK  ENDP
  521.  
  522. ; show the definition of a key.  The terminal argument block (which contains
  523. ; the address and length of the definition tables) is passed in ax.
  524. ; Returns a string to print in AX, length of same in CX.
  525. ; Returns normally.
  526.  
  527. ; In this version, the complete untranslated key scan codes are obtained
  528. ; from the fifo buffer in IO.SYS. The fifo buffer pointers are then updated
  529. ; to show that the key has been read. Certain key scan codes which are
  530. ; intercepted in the kb interrupt routine give a blank or functional response
  531. ; to SHOW KEY  (eg FNC + CTRL + BREAK-STOP, PRINT, and CTRL + 0...9 )
  532. ; and these cannot be translated.
  533.  
  534. SHOWKEY PROC    NEAR
  535.         push es
  536.         test ourflgs,kbtrflg
  537.         jnz showk0
  538.         push ax                 ; Keep stack balanced
  539.         mov bx,ax
  540.         and [bx].flgs,not havtt ; reset flag
  541.         mov dx,offset nokbtr    ; Inform no table installed and return
  542.         jmp short shoerr
  543.  
  544. showk0: push ax                 ; save the terminal argument block
  545.         mov al,trans.escchr     ; calculate scan code for ctrl-escape key
  546.         add al,40H              ; uncontrolify escape char
  547.         mov ah,2                ; control byte
  548.         mov escscan,ax          ; save it
  549. showk1: call inscan             ; get key-in scan code from IO.SYS
  550.          jmp short showk1       ; Nothing there yet - keep trying
  551.          nop
  552.         call inckbo             ; increment kbout pointer
  553.         cmp al,printkey         ; Is it the print key (any version) ?
  554.         jnz show11
  555.         mov dx,offset prtmsg    ; If so complain
  556.         jmp short shoerr
  557. show11: cmp al,byte ptr escscan ; Is it current ctrl-escape key ?
  558.         jnz show12
  559.         test ah,02              ; With ctrl + anything
  560.         jz show12
  561.         mov dx,offset escmsg    ; Then complain
  562.         jmp short shoerr
  563. show12: cld
  564.         mov cx,ds
  565.         mov es,cx
  566.         push ax                 ; save scan code
  567.         mov di,offset shkbuf    ; move 'Scan code' message to buffer
  568.         mov si,offset shkmsg
  569.         mov cx,shkmln
  570.         rep movsb
  571.         call nout               ; add scan code to buffer
  572.         mov si,offset shkms1    ; move 'Definition' message to buffer
  573.         mov cx,shkm1ln
  574.         rep movsb
  575.         pop ax                  ; retrieve scan code
  576.         pop bx                  ; and terminal argument block
  577.         mov cx,[bx].klen        ; length of translation table
  578.         jcxz showk3             ; no table, key not defined
  579.         push di
  580.         mov di,[bx].ktab        ; get table address
  581.         repne scasw             ; look for scan code
  582.         mov si,di
  583.         pop di
  584.         jne showk3              ; not defined
  585.         sub si,[bx].ktab        ; compute entry offset in table
  586.         sub si,2
  587.         add si,[bx].krpl        ; index to replacement
  588.         mov si,[si]             ; get its address
  589.         mov cl,[si]             ; get its length
  590.         mov ch,0
  591.         inc si
  592.         rep movsb               ; transfer replacement to display buffer
  593. showk3: mov ax,offset shkbuf    ; return address of buffer in ax
  594.         mov cx,di               ; and length in cx
  595.         sub cx,ax
  596.         pop es
  597.         ret
  598. shoerr: call tmsg
  599.         mov cx,0                ;
  600.         pop ax                  ; get rid of junk
  601.         pop es
  602.         ret
  603. SHOWKEY ENDP
  604.  
  605. ; copy numeric value from AX to ASCII buffer indicated by DI.  DI is updated.
  606.  
  607. NOUT    PROC    NEAR
  608.         mov dx,0                ; zero high word
  609.         mov bx,10               ; divide
  610.         div bx
  611.         push dx                 ; save remainder digit
  612.         or ax,ax                ; anything left?
  613.         jz nout1                ; no, start output phase
  614.         call nout
  615. nout1:  pop ax                  ; retrieve a digit
  616.         add al,'0'              ; make it ASCII
  617.         stosb                   ; put it in buffer
  618.         ret
  619. NOUT    ENDP
  620.  
  621. ; skip returns if no character available at port,
  622. ; otherwise returns with char in al, # of chars in buffer in dx.
  623.  
  624. PRTCHR  PROC    NEAR
  625.         call chkxon             ; see if we have to xon the host.
  626.         cmp count,0
  627.         jnz prtch2
  628.         jmp rskp                ; No data - check console.
  629. prtch2: pushf                   ; save current interrupt value
  630.         cli                     ; disable interrupts while manipulating pointers
  631.         mov si,savesi
  632.         lodsb                   ; get a byte
  633.         cmp si,offset source + bufsiz   ; bigger than buffer?
  634.         jb prtch1               ; no, keep going
  635.         mov si,offset source    ; yes, wrap around
  636. prtch1: dec count
  637.         mov savesi,si
  638.         mov dx,count            ; return # of chars in buffer
  639.         popf                    ; restore original interrupt flag
  640.         ret
  641. PRTCHR  ENDP
  642.  
  643. ; local routine to see if we have to transmit an xon
  644.  
  645. CHKXON  PROC    NEAR
  646.         push bx
  647.         mov bx,portval
  648.         cmp [bx].floflg,0       ; doing flow control?
  649.         je chkxo1               ; no, skip all this
  650.         cmp xofsnt,false        ; have we sent an xoff?
  651.         je chkxo1               ; no, forget it
  652.         cmp count,mntrgh        ; below trigger?
  653.         jae chkxo1              ; no, forget it
  654.         mov ax,[bx].flowc       ; ah gets xon
  655.         call outchr             ; send it
  656.          nop                    ;  ignore failure
  657.          nop
  658.          nop
  659.         mov xofsnt,false        ; remember we've sent an xon.
  660. chkxo1: pop bx                  ; restore register
  661.         ret                     ; and return
  662. CHKXON  ENDP
  663.  
  664. ; Put the char in AH to the serial port.  This assumes the
  665. ; port has been initialized.  Should honor xon/xoff.  Skip returns on
  666. ; success, returns normally if the character cannot be written.
  667.  
  668. OUTCHR  PROC    NEAR
  669.         mov bp,portval
  670.         cmp ds:[bp].floflg,0    ; Are we doing flow control.
  671.         je outch2               ; No, just continue.
  672.         sub cx,cx               ; clear counter
  673.         cmp ah,byte ptr [bp].flowc      ; sending xoff? [jrd]
  674.         jne outch1              ; ne = no
  675.         mov xofsnt,false        ; supress xon from chkxon buffer routine
  676. outch1: cmp xofrcv,true         ; Are we being held?
  677.         jne outch2              ; No - it's OK to go on.
  678.         loop outch1             ; held, try for a while
  679.         mov xofrcv,false        ; timed out, force it off and fall thru.
  680. outch2: push dx                 ; Save register.
  681.         sub cx,cx
  682.         mov al,ah               ; Parity routine works on AL.
  683.         call dopar              ; Set parity appropriately.
  684.         mov ah,al               ; Don't overwrite character with status.
  685.         mov dx,modem.mdstat     ; port status register
  686. outch3: in al,dx
  687.         test al,txrdy           ; Transmitter ready?
  688.         jnz outch4              ; Yes
  689.         loop outch3
  690.          jmp outch5             ; Timeout
  691. outch4: mov al,ah               ; Now send it out
  692.         mov dx,modem.mddat
  693.         out dx,al
  694.         pop dx
  695.         jmp rskp
  696. outch5: pop dx
  697.         ret
  698. OUTCHR  ENDP
  699.  
  700. ; IHOSTS - Initialize the host by sending XON, or equivalent, and enter the
  701. ; cycle of clear input buffer, wait 1 second, test if buffer empty then exit
  702. ; else repeat cycle. Requires that the port be initialized before hand.
  703. ; Ihosts is used by the local send-file routine just after initializing
  704. ; the serial port.
  705. ; 22 March 1986 [jrd]
  706.  
  707. IHOSTS  PROC    NEAR
  708.         push    ax              ; save the registers
  709.         push    bx
  710.         push    cx
  711.         push    dx
  712.         mov     bx,portval      ; port indicator
  713.         mov     ax,[bx].flowc   ; put Go-ahead flow control char in ah
  714.         call    outchr          ; send it (release Host's output queue)
  715.          nop                    ; outchr can do skip return
  716.          nop
  717.          nop
  718. ihosts1:call    clrbuf          ; clear out interrupt buffer
  719.         mov     ax,1            ; sleep for 1 second
  720.         call    sleep           ; procedure sleep is in msscom.asm
  721.         call    prtchr          ; check for char at port
  722.          jmp    ihosts1         ; have a char in al, repeat wait/read cycle
  723.          nop                    ; prtchr does skip return on empty buffer
  724.         pop     dx              ; empty buffer. we are done here.
  725.         pop     cx
  726.         pop     bx
  727.         pop     ax
  728.         ret
  729. IHOSTS  ENDP
  730.  
  731. ; IHOSTR - initialize the remote host for our reception of a file by
  732. ; sending the flow-on character (XON typically) to release any held
  733. ; data. Called by receive-file code just after initializing the serial
  734. ; port.         22 March 1986 [jrd]
  735. IHOSTR  PROC    NEAR
  736.         push    ax              ; save regs
  737.         push    bx
  738.         push    cx
  739.         mov     bx,portval      ; port indicator
  740.         mov     ax,[bx].flowc   ; put Go-ahead flow control char in ah
  741.         call    outchr          ; send it (release Host's output queue)
  742.          nop                    ; outchr can do skip return
  743.          nop
  744.          nop
  745.         pop     cx
  746.         pop     bx
  747.         pop     ax
  748.         ret
  749. IHOSTR  ENDP
  750.  
  751. DTRLOW  PROC    NEAR            ; Global proc to Hangup the Phone by making
  752.                                 ; DTR and RTS low.
  753.         mov ah,cmtxt            ; allow text to be able to display help
  754.         mov bx,offset rdbuf     ; dummy buffer
  755.         mov dx,offset hnghlp    ; help message
  756.         call comnd              ; get a confirm
  757.          jmp r
  758.         call discon             ; try using preexisting routine
  759. ; [jrd] call serhng             ; drop DTR and RTS
  760. ; [jrd] mov ah,prstr            ; give a nice message
  761. ; [jrd] mov dx,offset hngmsg
  762. ; [jrd] int dos
  763.         jmp rskp
  764. DTRLOW  ENDP
  765.  
  766. ; Hang up the Phone. Similar to SERRST except it just forces DTR and RTS low
  767. ; to terminate the connection. 29 March 1986 [jrd]
  768. ; Calling this twice without intervening calls to serini should be harmless.
  769. ; Returns normally.
  770. ; SERHNG is Not Yet Implemented. Use existing procedure discon below.
  771.  
  772.  
  773.  
  774. ; Send a break out the current serial port.  Returns normally.
  775.  
  776. SENDBR  PROC    NEAR
  777.         mov dx,modem.mdcom      ; send to command port
  778.         mov al,cbrk+ccmd        ; add break to normal command
  779.         out dx,al
  780.         sub cx,cx               ; wait a while
  781. sndbr1: loop sndbr1
  782.         mov al,ccmd             ; restore normal command
  783.         out dx,al
  784.         ret                     ; and return.
  785. SENDBR  ENDP
  786.  
  787. DISCON  PROC    NEAR
  788.         mov dx,offset hngcfm
  789.         call besure             ; Get confimation of command
  790.          jmp short discn1
  791.          nop
  792.         mov dx,offset dismsg    ; Say what we're doing
  793.         call tmsg
  794.         mov al,CCMD
  795.         xor al,2                ; Reset bit to drop DTR.
  796.         mov dx,modem.mdcom
  797.         out dx,al
  798.         mov bx,05H              ; Set outer counter  5 X --> 3sec.
  799. pause2: xor cx,cx
  800. pause3: push bx                 ; Waste time for 600ms.
  801.         pop bx
  802.         loop pause3             ; Loop on inner loop.
  803.         dec bx
  804.         jnz pause2              ; Loop on outer loop.
  805.         or al,2                 ; Set bit to enable DTR again.
  806.         out dx,al
  807.         mov dx,offset rcnmsg
  808.         call tmsg
  809. discn1: ret
  810. DISCON  ENDP
  811.  
  812. BESURE  PROC    NEAR            ; Receives addr of prompt in DX.
  813.         call tmsg
  814.         mov ah,conin
  815.         int dos
  816.         and al,137Q             ; Convert to upper case if necessary.
  817.         cmp al,'Y'
  818.         jz besur1               ; We must return rskp for a 'Y'/'y'
  819.         mov dx,offset crlf      ; For any other character input send a cr/lf.
  820.         call tmsg
  821.         ret                     ; And return.
  822. besur1: jmp rskp
  823. BESURE  ENDP
  824.  
  825.  
  826. ; Clear the input buffer. This throws away all the characters in the
  827. ; serial interrupt buffer.  This is particularly important when
  828. ; talking to servers, since NAKs can accumulate in the buffer.
  829. ; Returns normally.
  830.  
  831. CLRBUF  PROC    NEAR
  832.         pushf                   ; save current interrupt value
  833.         cli                     ; disable interrupts
  834.         mov ax,offset source    ; reset pointers to beginning of buffer
  835.         mov srcpnt,ax
  836.         mov savesi,ax
  837.         mov count,0
  838.         popf                    ; restore original interrupt value
  839.         ret
  840. CLRBUF  ENDP
  841.  
  842. ; Set the baud rate for the current port, based on the value in the
  843. ; portinfo structure.  On entry, previous value of baud rate is saved in AX.
  844. ; Returns normally.
  845.  
  846. DOBAUD  PROC    NEAR
  847.         push ax                 ; save regs. [jrd]
  848.         push bx
  849.         push dx
  850.         push bp
  851.         mov bp,portval
  852.         mov bx,ds:[bp].baud     ;make sure new value is valid
  853.         cmp bx,BAUDSIZ          ; [RB] don't get stuck at 1200 baud
  854.         jae dobd0               ; [RB]
  855.         shl bx,1
  856.         add bx,offset bddat
  857.         cmp word ptr [bx],0FFH
  858.         jne dobd1               ; [RB]
  859. dobd0:  mov ds:[bp].baud,ax     ; [RB] replace bad rate with previous value
  860.         mov dx,offset badbd
  861.         jmp tmsg
  862. dobd1:  mov dx,timer.tmcmd      ; [RB] timer command port
  863.         mov al,timer.tmsel      ;select proper channel and mode
  864.         out dx,al
  865.         mov ax,[bx]             ;get timer initializer for this rate
  866.         mov dx,timer.tmdat      ;timer data port
  867.         out dx,al               ;output low byte
  868.         mov al,ah
  869.         out dx,al               ;output high byte
  870.         pop bp                  ; [jrd]
  871.         pop dx
  872.         pop bx
  873.         pop ax
  874.         ret
  875. DOBAUD  ENDP
  876.  
  877. ; Get the current baud rate from the serial card and set it
  878. ; in the portinfo structure for the current port.  Returns normally.
  879. ; This is called any time the baud rate is to be displayed.
  880.  
  881. ; We can't determine the baud rate on the APC, so just set it
  882. ; to the default of 1200 if the value is currently illegal.
  883.  
  884. GETBAUD PROC    NEAR
  885.         push bx                 ; [jrd]
  886.         push bp                 ; Additions by Ron Blanford 14 April 1986
  887.         mov bp,portval
  888.         mov bx,ds:[bp].baud
  889.         cmp bx,BAUDSIZ
  890.         jae getbd2
  891.         shl bx,1
  892.         add bx,offset bddat
  893.         cmp word ptr [bx],0FFh
  894.         jne getbd3
  895. getbd2: mov ds:[bp].baud,B1200
  896. getbd3: pop bp
  897.         pop bx                  ; [jrd]
  898.         ret
  899. GETBAUD ENDP
  900.  
  901. ; Set the mode for the current port.  This is part of the serial
  902. ; initialization routine.
  903.  
  904. DOMODE  PROC    NEAR
  905.         mov dx,modem.mdcom      ;send 3 zeros to command port to reset chip
  906.         mov al,0
  907.         out dx,al
  908.         mov al,0
  909.         out dx,al
  910.         mov al,0
  911.         out dx,al
  912.         mov al,cmode            ;enable mode setting
  913.         out dx,al
  914.         push ax                 ;allow 8251 time to reset
  915.         pop ax
  916.         push ax
  917.         pop ax
  918.         mov al,mmode            ;mode: 16x rate, 8 data, no parity, 1 stop
  919.         out dx,al
  920.         mov al,ccmd             ;RTS & DTR high, RX & TX enabled, reset errors
  921.         out dx,al
  922.         ret
  923. DOMODE  ENDP
  924.  
  925. ; Reassure user about connection to the host.  Tell him what escape
  926. ; sequence to use to return and the communications port and baud
  927. ; rate being used.   [19b]
  928.  
  929. DOMSG   PROC    NEAR
  930.         push    ax                      ; save regs. [jrd]
  931.         push    bx
  932.         push    cx
  933.         push    si
  934.         mov     bx,offset ourarg        ; get argument block
  935.         mov     al,[bx].baudb           ; get baud bits
  936.         mov     si,offset unkbaud       ; Assume unknown baud.
  937.         cmp     al,baudnsiz             ; too big?
  938.         jnb     dmsg12                  ; yes, use default
  939.         mov     cl,2                    ; each is 5 bytes long
  940.         shl     al,cl                   ; 4 X
  941.         add     al,[bx].baudb           ; make 4+1 = 5
  942.         mov     ah,0
  943.         add     ax,offset baudn
  944.         mov     si,ax
  945. dmsg12: mov     cx,5                    ; length of baud space
  946.         mov     di,offset cnmsgb
  947.         rep     movsb                   ; copy in baud rate
  948.         mov     al,'1'
  949.         cmp     ourarg.prt,1            ; One means port 1
  950.         je      dmsg15                  ; yes, keep going
  951.         mov     al,'2'                  ; Zero means port 2
  952. dmsg15: mov     cnmsgp,al               ; fill in port number
  953.         mov dx,offset cnmsg
  954.         call tmsg
  955.         call escprt                     ; in MSSET
  956.         mov dx,offset cnmsg1
  957.         call tmsg
  958.         pop     si                      ; [jrd]
  959.         pop     cx
  960.         pop     bx
  961.         pop     ax
  962.         ret
  963. DOMSG   ENDP
  964.  
  965. ; set the current port.
  966.  
  967. COMS    PROC    NEAR
  968.         mov dx,offset comptab   ;get port selection
  969.         mov bx,0
  970.         mov ah,cmkey
  971.         call comnd
  972.          jmp r
  973.         push bx
  974.         mov ah,cmcfm            ;get a confirmation
  975.         call comnd
  976.          jmp comx
  977.          nop
  978.         pop bx
  979.         mov flags.comflg,bl     ;save port selection
  980.         cmp flags.comflg,1
  981.         jne coms2
  982.         mov ax,offset port1     ;set to run on port 1
  983.         mov portval,ax
  984.         call resetb             ;reset port 2, if in use
  985.         call inita              ;set up port 1
  986.         ret
  987. coms2:  mov ax,offset port2     ;set to run on port 2
  988.         mov portval,ax
  989.         call reseta             ;reset port 1, if in use
  990.         call initb              ;set up port 2
  991.         ret
  992. comx:   pop bx
  993.         ret
  994. COMS    ENDP
  995.  
  996. ; initialization for using serial port.  This routine performs
  997. ; any initialization necessary for using the serial port, including
  998. ; setting up interrupt routines, setting buffer pointers, etc.
  999. ; Doing this twice in a row should be harmless (this version checks
  1000. ; a flag and returns if initialization has already been done).
  1001. ; SERRST below should restore any interrupt vectors that this changes.
  1002. ; Returns normally.
  1003.  
  1004. SERINI  PROC    NEAR
  1005.         cmp flags.comflg,1
  1006.         jne seri2
  1007.         call resetb
  1008.         call inita
  1009.         ret
  1010. seri2:  call reseta
  1011.         call initb
  1012.         ret
  1013. SERINI  ENDP
  1014.  
  1015. ; Reset the serial port.  This is the opposite of serini.  Calling
  1016. ; this twice without intervening calls to serini should be harmless.
  1017. ; Returns normally.
  1018.  
  1019. SERRST  PROC    NEAR
  1020.         call reseta             ;reset port 1
  1021.         call resetb             ;reset port 2
  1022.         mov dx,offset recur     ; Reenable cursor display
  1023.         call tmsg
  1024.         and ourflgs,not inited  ; Reset init flag for term usage
  1025.         ret
  1026. SERRST  ENDP
  1027.  
  1028. ; Local routine to initialize the standard serial port
  1029.  
  1030. INITA   PROC    NEAR
  1031.         cmp portina,1           ; Did we initialize port already? [21c]
  1032.         je inita0               ; Yes, so just leave. [21c]
  1033.         push es
  1034.         cli                     ; Disable interrupts
  1035.         mov ax,offset port1
  1036.         mov portval,ax
  1037.         xor ax,ax               ; Address low memory
  1038.         mov es,ax
  1039.         mov ax,es:[4*icsvcta]   ; save standard port interrupt vector
  1040.         mov oldsera,ax
  1041.         mov ax,es:[4*icsvcta+2]
  1042.         mov oldsega,ax
  1043.         mov ax,offset serint    ; point to our routine
  1044.         mov es:[4*icsvcta],ax   ; point at our serial routine
  1045.         mov es:[4*icsvcta+2],cs ; our segment
  1046.         mov dx,intmska          ; set up standard port...
  1047.         in al,dx
  1048.         mov oldmska,al          ; save old master controller mask
  1049.  
  1050. ;       NEC recommends that the timer interrupt be disabled during interrupt-
  1051. ;       driven serial I/O, but this disables the clock display and keyboard
  1052. ;       repeat.  I have not had any problems leaving it enabled, so I will
  1053. ;       leave it alone here.  If problems develop, uncomment the following
  1054. ;       line to disable timer interrupts. -- RonB
  1055.  
  1056. ;       or al,ictmsk            ; disable timer interrupt
  1057.         and al,not icsmska      ; enable serial interrupt at master controller
  1058.         out dx,al
  1059.         mov dx,mnmska           ; enable serial interrupt at port
  1060.         mov al,txmsk+tbemsk     ; disable tx and tbe interrupts (enable rx)
  1061.         out dx,al
  1062.         mov dx,mntdca           ; enable operation of serial port
  1063.         mov al,0
  1064.         out dx,al
  1065.         mov modem.mddat,mndata
  1066.         mov modem.mdstat,mnst1a
  1067.         mov modem.mdcom,mncmda
  1068.         mov timer.tmdat,tmdata
  1069.         mov timer.tmcmd,tmcmda
  1070.         mov timer.tmsel,tmsela
  1071.         call domode
  1072.         call dobaud
  1073.         mov portina,1           ; Remember port has been initialized.
  1074.         call clrbuf             ; Clear input buffer.
  1075.         sti                     ; Allow interrupts
  1076.         pop es
  1077. inita0: ret
  1078. INITA   ENDP
  1079.  
  1080. ; Local routine to initialize the optional (H14) serial port
  1081.  
  1082. INITB   PROC    NEAR
  1083.         cmp portinb,1           ; Did we initialize port already? [21c]
  1084.         je initb0               ; Yes, so just leave. [21c]
  1085.         push es
  1086.         cli                     ; Disable interrupts
  1087.         mov ax,offset port2
  1088.         mov portval,ax
  1089.         xor ax,ax               ; Address low memory
  1090.         mov es,ax
  1091.         mov ax,es:[4*icsvctb]   ; save optional port interrupt vector
  1092.         mov oldserb,ax
  1093.         mov ax,es:[4*icsvctb+2]
  1094.         mov oldsegb,ax
  1095.         mov ax,offset serint    ; point to our routine
  1096.         mov es:[4*icsvctb],ax   ; point at our serial routine
  1097.         mov es:[4*icsvctb+2],cs ; our segment
  1098.         mov dx,intmskb          ; set up optional port...
  1099.         in al,dx
  1100.         mov oldmskb,al          ; save old master or slave controller mask
  1101.         and al,not icsmskb      ; enable serial interrupt at controller
  1102.         out dx,al
  1103.         mov dx,mnmskb           ; enable serial interrupt at port
  1104.         mov al,txmsk+tbemsk     ; disable tx and tbe interrupts (enable rx)
  1105.         out dx,al
  1106.         mov dx,mntdcb           ; enable operation of serial port
  1107.         mov al,0
  1108.         out dx,al
  1109.         mov modem.mdstat,mnst1b
  1110.         mov modem.mddat,mndatb
  1111.         mov modem.mdcom,mncmdb
  1112.         mov timer.tmdat,tmdatb
  1113.         mov timer.tmcmd,tmcmdb
  1114.         mov timer.tmsel,tmselb
  1115.         call domode
  1116.         call dobaud
  1117.         mov portinb,1           ; Remember port has been initialized.
  1118.         call clrbuf             ; Clear input buffer.
  1119.         sti                     ; Allow interrupts
  1120.         pop es
  1121. initb0: ret
  1122. INITB   ENDP
  1123.  
  1124. ; Reset standard serial port
  1125.  
  1126. RESETA  PROC    NEAR
  1127.         cmp portina,0           ; Did we reset port already?
  1128.         je rsta0                ; Yes, so just leave.
  1129.         push es
  1130.         cli                     ; Disable interrupts
  1131.         xor ax,ax               ; Address low memory
  1132.         mov es,ax
  1133.         mov ax,oldsera          ; Restore interrupt vector
  1134.         mov es:[4*icsvcta],ax
  1135.         mov ax,oldsega
  1136.         mov es:[4*icsvcta+2],ax
  1137.         mov dx,intmska          ; restore old master controller mask
  1138.         mov al,oldmska
  1139.         out dx,al
  1140.         mov dx,mnmska           ; disable serial interrupts at port
  1141.         mov al,txmsk+rxmsk+tbemsk
  1142.         out dx,al
  1143.         mov portina,0           ; Remember port has been reset
  1144.         sti                     ; Allow interrupts
  1145.         pop es
  1146. rsta0:  ret
  1147. RESETA  ENDP
  1148.  
  1149. ; Reset optional (H14) serial port
  1150.  
  1151. RESETB  PROC    NEAR
  1152.         cmp portinb,0           ; Did we reset port already?
  1153.         je rstb0                ; Yes, so just leave.
  1154.         push es
  1155.         cli                     ; Disable interrupts
  1156.         xor ax,ax               ; Address low memory
  1157.         mov es,ax
  1158.         mov ax,oldserb          ; Restore interrupt vector
  1159.         mov es:[4*icsvctb],ax
  1160.         mov ax,oldsegb
  1161.         mov es:[4*icsvctb+2],ax
  1162.         mov dx,intmskb          ; restore old slave controller mask
  1163.         mov al,oldmskb
  1164.         out dx,al
  1165.         mov dx,mnmskb           ; disable serial interrupts at port
  1166.         mov al,txmsk+rxmsk+tbemsk
  1167.         out dx,al
  1168.         mov portinb,0           ; Remember port has been reset
  1169.         sti                     ; Allow interrupts
  1170.         pop es
  1171. rstb0:  ret
  1172. RESETB  ENDP
  1173.  
  1174.  
  1175. ; serial port interrupt routine.  This is not accessible outside this
  1176. ; module, handles serial port receiver interrupts.
  1177.  
  1178. SERINT  PROC  NEAR
  1179.         push ds                 ; save these on remote stack
  1180.         push ax
  1181.         mov ax,seg datas        ; get our own data segment
  1182.         mov ds,ax
  1183.         mov mnsp,sp             ; save remote stack information
  1184.         mov mnsseg,ss
  1185.         mov sp,offset mnstk     ; switch to local stack
  1186.         mov ss,ax
  1187.         push es                 ; and save remaining registers
  1188.         push bp
  1189.         push di
  1190.         push si
  1191.         push dx
  1192.         push cx
  1193.         push bx
  1194.         mov es,ax
  1195.         call mnproc             ; process the interrupt
  1196.         mov al,icEOI
  1197.         cmp flags.comflg,1      ; If using standard port
  1198.         je intr1
  1199.         mov dx,intcmdb          ;    or H14 vectored to master
  1200.         cmp dx,intcmda
  1201.         je intr1                ;    only signal End of Interrupt to master,
  1202.         out dx,al               ; otherwise signal to both slave and master.
  1203. intr1:  mov dx,intcmda
  1204.         out dx,al
  1205.         pop bx                  ; restore registers from stack
  1206.         pop cx
  1207.         pop dx
  1208.         pop si
  1209.         pop di
  1210.         pop bp
  1211.         pop es
  1212.         mov ax,mnsseg           ; switch back to remote stack
  1213.         mov ss,ax
  1214.         mov ax,mnsp
  1215.         mov sp,ax
  1216.         pop ax
  1217.         pop ds
  1218.         iret
  1219.  
  1220. ; handler for serial input
  1221.  
  1222. mnproc: cld
  1223.         mov di,srcpnt           ; get buffer pointer
  1224.         mov dx,modem.mdstat     ; is data available?
  1225.         in al,dx
  1226.         test al,rxrdy
  1227.         jz mnpro7
  1228.         mov dx,modem.mddat      ; read data
  1229.         in al,dx
  1230.         or al,al
  1231.         jz mnpro7               ; Ignore nulls.
  1232.         cmp al,7FH              ; Ignore rubouts, too.
  1233.         jz mnpro7
  1234.         mov ah,al
  1235.         and ah,7fH              ; only consider low-order 7 bits for flow ctl.
  1236.         mov bp,portval
  1237.         cmp ds:[bp].floflg,0    ; Doing flow control?
  1238.         je mnpro4               ; Nope.
  1239.         mov bx,ds:[bp].flowc    ; Flow control char (BH = XON, BL = XOFF).
  1240.         cmp ah,bl               ; Is it an XOFF?
  1241.         jne mnpro3              ; Nope, go on.
  1242.         mov xofrcv,true         ; Set the flag.
  1243.         jmp short mnpro7
  1244. mnpro3: cmp ah,bh               ; Get an XON?
  1245.         jne mnpro4              ; No, go on.
  1246.         mov xofrcv,false        ; Clear our flag.
  1247.         jmp mnpro7
  1248. mnpro4: stosb
  1249.         cmp di,offset source + bufsiz
  1250.         jb mnpro5               ; not past end...
  1251.         mov di,offset source    ; wrap buffer around
  1252. mnpro5: mov srcpnt,di           ; update ptr
  1253.         inc count
  1254.         cmp ds:[bp].floflg,0    ; Doing flow control?
  1255.         je mnpro7               ; No, just leave.
  1256.         cmp xofsnt,true         ; Have we sent an XOFF?
  1257.         je mnpro7               ; Yes.
  1258.         cmp count,mntrgh        ; Past the high trigger point?
  1259.         jbe mnpro7              ; No, we're within our limit.
  1260.         mov ah,bl               ; Get the XOFF.
  1261.         call outchr             ; Send it.
  1262.          nop                    ;   ignore failure.
  1263.          nop
  1264.          nop
  1265.         mov xofsnt,true         ; Remember we sent it.
  1266. mnpro7: ret
  1267.  
  1268. SERINT  ENDP
  1269.  
  1270. ; Dumb terminal emulator.  Anyone wishing to enhance it is encouraged
  1271. ; to do so.
  1272.  
  1273. TERM    PROC    NEAR
  1274.         push es
  1275.         test ourflgs,inited     ; Have we been here before
  1276.         jnz  term01             ; if so, skip this stuff
  1277.         or  ourflgs,inited      ; show we've been here
  1278.         test ourflgs,kbtrflg
  1279.         jnz term0
  1280.         mov bx,ax
  1281.         and [bx].flgs,not havtt ; If no table then reset flag
  1282. term0:  mov si,ax               ; save argument block locally
  1283.         mov di,offset ourarg
  1284.         mov ax,ds
  1285.         mov es,ax
  1286.         mov cx,size termarg
  1287.         rep movsb
  1288.         mov al,trans.escchr     ; Calculate scan code for cntrl-escape char
  1289.         add al,40H              ; Uncontollify escape char
  1290.         mov ah,02H              ; Control byte for escape scan code
  1291.         mov escscan,ax          ; save it
  1292.         call domsg              ; tell user how we're connecting.
  1293. term01: test ourflgs,movcur      ; Do we need to reset cursor position
  1294.         jz term1
  1295.         mov dx,offset cmd
  1296.         mov cx,savcur
  1297.         mov word ptr la,cx
  1298.         mov noc,0
  1299.         mov cmd,1               ; Bios  move cursor call
  1300.         mov cl,crtcmd
  1301.         int bios
  1302.         and ourflgs, not movcur
  1303. term1:  call prtchr             ; Serial port input processor
  1304.          jmp short term2        ;  ...have a char
  1305.          nop
  1306.         jmp term4               ; no char, continue
  1307. term2:  and al,7FH              ; only use ASCII in terminal mode
  1308.         push ax
  1309.         mov dl,al
  1310.         mov ah,conout
  1311.         int dos                 ; display char
  1312.         pop ax
  1313.         test ourarg.flgs,capt   ; are we capturing output?
  1314.         jz term3
  1315.         push ax
  1316.         call ourarg.captr
  1317.         pop ax
  1318. term3:  test ourflgs,fprint     ; are we echoing to printer?
  1319.         jz term4
  1320.         call lstchr
  1321.  
  1322. term4:  test ourflgs,kbtrflg
  1323.         jz term50
  1324.         call inscan
  1325.          jmp  short term1
  1326.          nop
  1327.         cmp al,printkey         ; All shifts of print key do special duty.
  1328.         jne term41
  1329.         cmp ah,0
  1330.         jne term40              ; but toggle printer only if unshifted print
  1331.         xor ourflgs,fprint      ; go toggle printer
  1332. term40: call inckbo             ; increment kbout pointer
  1333.         jmp term1
  1334. term41: cmp al,byte ptr escscan ; Is it current escape key
  1335.         jne  term42
  1336.         test ah,02              ;  with ctrl + anything ?
  1337.         jz  term42
  1338.         call inckbo
  1339.         jmp short termx         ; it's ctrl-escape key so just return
  1340. term42: call trnout             ; Returns rskp if char not sent.
  1341.          jmp short term1        ; Translation found and already sent.
  1342.          nop                    ; no translation so move char via DCONIO
  1343.         cmp ax,brkstp           ; is it unredefined/unshifted break/stop key
  1344.         jnz term50              ; if not, just continue
  1345.         mov ax,ctrl_s           ; get a ^S ready
  1346.         test ourflgs,tlnxof     ; have we already sent a ^S ?
  1347.         jz term43               ; no, we can just set flag and send the ^S
  1348.         mov ax,ctrl_q           ; yes, so now we need a ^Q
  1349. term43: xor ourflgs,tlnxof      ; change the flag in either case
  1350.         call sndhst             ; send our  ^S/ ^Q - IO.SYS 2.11 won't do it
  1351.         mov ah,dconio           ; do a dummy read to clear IO.SYS flush flag
  1352.         mov dl,0FFH
  1353.         int dos
  1354.         jmp term1               ; and go back for more
  1355. term50: mov ah,dconio           ; Keyboard input processor
  1356.         mov dl,0FFH
  1357.         int dos                 ; check console
  1358.         jnz term51
  1359.         jmp term1               ; no char, continue .Too far for rel jmp.
  1360. term51: cmp al,ourarg.escc      ; is it the escape char?
  1361.         je termx                ; allows use of unredef left arrow key to esc
  1362.         call sndhst             ; no translation, just send it out
  1363. ;  Check if it is a function key that user has defined in MS-DOS
  1364.         mov es,dosseg
  1365.         mov bx,fifobas
  1366.         cmp es:byte ptr sfkeyflg[bx],0
  1367.         jnz term50              ; if so, go back to dconio for rest of chars
  1368.         jmp term1               ; and go back for more
  1369. termx:  pop es
  1370.         ret
  1371.  
  1372.  
  1373. ; do appropriate translations on input key, and transmit
  1374. ; if translation entry found it sends char(s) to sndhst and returns normally
  1375. ; if no translation entry is found, returns rskp with unsent scan code in ax
  1376. ;  so that CONIN in IO.SYS can do its translation if neessary.
  1377.  
  1378. trnout: test ourflgs,kbtrflg    ; is there a translation table?
  1379.         jz trnou3
  1380.         mov cx,ourarg.klen      ; get table length and origin
  1381.         mov di,ourarg.ktab
  1382.         push es
  1383.         mov bx,ds
  1384.         mov es,bx
  1385.         jcxz trnou3             ; Needed for case of table zero length
  1386.         repne scasw             ; look for key
  1387.         jne trnou3              ; if not found, return rskp
  1388.         sub di,ourarg.ktab      ; reset to offset of replacement
  1389.         sub di,2
  1390.         add di,ourarg.krpl
  1391.         mov si,[di]
  1392.         mov cl,[si]             ; get length of replacement
  1393.         mov ch,0
  1394.         jcxz trnou3             ; if length is zero, send nothing
  1395.         inc si
  1396. trnou1: lodsb                   ; get replacement character
  1397.         push si
  1398.         push cx
  1399.         call sndhst             ; send it to port
  1400.         pop cx
  1401.         pop si
  1402.         loop trnou1             ; continue until translation complete
  1403. trnou2: call inckbo             ; increment kbout pointer
  1404.         pop es
  1405.         ret                     ; return after translating and sending
  1406. trnou3: pop es
  1407.         jmp rskp                ; plain characters return rskp
  1408.  
  1409. ; get key-in scan code from fifo buffer in IO.SYS
  1410. ; if gets a key-in, skip returns with scan code in ax
  1411. ; returns normally if no key-in
  1412.  
  1413. inscan: push es
  1414.         mov es,dosseg           ; Address IO.SYS segment with es
  1415.         and ourflgs,not autorepflg      ; Reset auto repeat flag
  1416.         mov bx,fifobas          ; Offset of fifobas in IO.SYS (from LCLINI)
  1417. insca1: mov al,es:[bx].kbout    ; Get value of kbin pointer
  1418.         cmp al,es:[bx].kbin     ; Compare value of kbout pointer
  1419.         jz  insca2              ; If equal, no key-in yet so exit
  1420.         sub ah,ah
  1421.         add bx,ax               ; Calculate address pointed to (-2)
  1422.         mov ax,es:2[bx]         ; Get scan code pointed to by kbout.
  1423.         xchg ah,al              ; Get control byte -> ah, data byte -> al.
  1424.         mov savscn,ax           ; Save scan data in case key repeat needed.
  1425.         pop es
  1426.         jmp rskp
  1427. insca2: mov bx,fifobas
  1428.         cmp byte ptr es:[bx].kbrepflg,0  ; Is it time to repeat last key-in
  1429.         jz inscax                       ; Nope so exit
  1430.         mov ax,savscn                   ; Get last key-in
  1431.         or ourflgs,autorepflg           ; Show we are on auto repeat cycle
  1432.         pop es                          ; And make it look like new
  1433.         jmp rskp
  1434. inscax: pop es
  1435.         ret
  1436.  
  1437. ; increments kbout pointer (with reset to zero) and returns normally
  1438. ;   (on auto repeat cycles resets kbrepflg and returns )
  1439.  
  1440. inckbo: push es
  1441.         mov es,dosseg
  1442.         mov bx,fifobas
  1443.         test ourflgs,autorepflg ; new key-in or autorepeat
  1444.         jnz inckb2
  1445.         mov cl,0                ; Update kbout pointer to fifo
  1446.         cli
  1447.         cmp byte ptr es:[bx].kbout,kbfifosiz-2          ; End of fifo buff ?
  1448.         je  inckb1              ; Yes, so start back at beginning
  1449.         mov cl,es:[bx].kbout    ; No, just update our place
  1450.         add cl,2
  1451. inckb1: mov es:[bx].kbout,cl    ; Write back new pointer value
  1452.         sti
  1453.         jmp short inckbx
  1454. inckb2: mov byte ptr es:[bx].kbrepflg,0 ; Reset autorepeat flag in IO.SYS
  1455. inckbx: pop es
  1456.         ret
  1457.  
  1458. ; send character in AL to port, with possible local echo
  1459.  
  1460. sndhst: push ax
  1461.         mov ah,al
  1462.         call outchr             ; send char to port
  1463.          nop                    ;  ...don't care if it fails
  1464.          nop
  1465.          nop
  1466.         pop ax
  1467.         test ourarg.flgs,lclecho ; doing local echo?
  1468.         jz sndhs2
  1469.         mov dl,al
  1470.         mov ah,conout
  1471.         int dos                 ;  if so, display char
  1472. sndhs2: ret
  1473.  
  1474. ; send character to printer.  The only special case is the tab, which must
  1475. ; be expanded to spaces because MS-DOS doesn't.
  1476.  
  1477. lstchr: cmp al,tab
  1478.         jne lstch2
  1479.         mov ax,lstpos           ; current column position
  1480.         mov cx,8                ; # of spaces = 8 - (column % 8)
  1481.         div cl
  1482.         sub cl,ah
  1483.         add lstpos,cx           ; update the column position
  1484.         mov al,' '
  1485. lstch1: call lstch4             ; print all the spaces
  1486.         loop lstch1
  1487.         ret
  1488. lstch2: cmp al,cr               ; CR returns column count to zero
  1489.         jne lstch3
  1490.         mov lstpos,0
  1491. lstch3: cmp al,' '              ; only printable characters are counted
  1492.         jb lstch4
  1493.         cmp al,del
  1494.         je lstch4
  1495.         inc lstpos
  1496. lstch4: mov dl,al               ; print the character in any case
  1497.         mov ah,lstout
  1498.         int dos
  1499.         ret
  1500.  
  1501. TERM    ENDP
  1502.  
  1503. ; Set heath emulation on/off.
  1504.  
  1505. VTS     PROC    NEAR
  1506.         mov dx,offset nyimsg
  1507.         jmp tmsg
  1508. VTS     ENDP
  1509.  
  1510. ; Save the screen to a buffer and then append buffer to a disk file. [jrd]
  1511. ; Default filename is Kermit.scn; actual file can be a device too. Filename
  1512. ; is determined by mssset and is passed as pointer dmpname.
  1513.  
  1514. VTSTAT  PROC    NEAR            ; For Status display [jrd]
  1515.         ret                     ; no emulator status to display
  1516. VTSTAT  ENDP
  1517.  
  1518. ; Save the screen to a buffer and then append buffer to a disk file. [jrd]
  1519. ; Default filename is Kermit.scn; actual file can be a device too. Filename
  1520. ; is determined by mssset and is passed as pointer dmpname.
  1521.  
  1522. DUMPSCR PROC    NEAR    ; Dumps screen contents to a file. Just Beeps here
  1523.         call beep       ; [jrd]
  1524.         ret
  1525. DUMPSCR ENDP
  1526.  
  1527.  
  1528. ; Position the cursor according to contents of DX:
  1529. ; DH contains row, DL contains column.  Returns normally.
  1530.  
  1531. POSCUR  PROC    NEAR
  1532.         push ax                 ; save regs. [jrd]
  1533.         push cx
  1534.         push si
  1535.         cmp dh,25               ; out of range just assumes high value
  1536.         jb poscu1
  1537.         mov dh,24
  1538. poscu1: cmp dl,80
  1539.         jb poscu2
  1540.         mov dl,79
  1541. poscu2: add dx,2020H            ; add offset for ADM cursor addressing
  1542.         mov cpseq+2,dh
  1543.         mov cpseq+3,dl
  1544.         mov si,offset cpseq     ; print sequence (ESC=rc)
  1545.         mov cx,4
  1546. posc1:  lodsb
  1547.         mov dl,al
  1548.         mov ah,conout
  1549.         int dos
  1550.         loop posc1
  1551.         pop si
  1552.         pop cx                  ; [jrd]
  1553.         pop ax
  1554.         ret
  1555. POSCUR  ENDP
  1556.  
  1557. ; Locate; homes cursor position and disables its display. Returns normally.
  1558.  
  1559. LOCATE  PROC    NEAR
  1560.         mov dx,offset nocur     ; Disable cursor
  1561.         call tmsg
  1562.         mov dx,0                ; Go to top left corner of screen.
  1563.         jmp poscur
  1564. LOCATE  ENDP
  1565.  
  1566. ; Delete a character from the terminal.  This works by printing
  1567. ; backspaces and spaces.  Returns normally.
  1568.  
  1569. DODEL   PROC    NEAR
  1570.         mov dx,offset delstr    ; Erase weird character.
  1571.         jmp tmsg
  1572. DODEL   ENDP
  1573.  
  1574. ; Move the cursor to the left margin, then clear to end of line.
  1575. ; Returns normally.
  1576.  
  1577. CTLU    PROC    NEAR
  1578.         mov dx,offset clrlin    ; this just goes to left margin...
  1579.         call tmsg
  1580.         jmp clearl              ; now clear line
  1581. CTLU    ENDP
  1582.  
  1583. ; Clear to the end of the current line.  Returns normally.
  1584.  
  1585. CLEARL  PROC    NEAR
  1586.         mov dx,offset ceolseq   ; clear sequence
  1587.         jmp tmsg
  1588. CLEARL  ENDP
  1589.  
  1590. ; This routine blanks the screen and homes the cursor.  Returns normally.
  1591.  
  1592. CMBLNK  PROC    NEAR
  1593.         mov dx,offset clrseq    ; clear screen and home cursor sequence
  1594.         jmp tmsg
  1595. CMBLNK  ENDP
  1596.  
  1597. ; write a line in inverse video at the bottom of the screen...
  1598. ; the line is passed in dx, terminated by a $.  Returns normally.
  1599.  
  1600. PUTMOD  PROC    NEAR
  1601.         push dx                 ; preserve message
  1602.         mov dx,24*100H          ; line 24
  1603.         call poscur
  1604.         mov dx,offset formdat.invseq    ; put into inverse video
  1605.         call tmsg
  1606.         pop dx                  ; print the message
  1607.         call tmsg
  1608.         mov dx,offset formdat.nrmseq    ; normal video
  1609.         jmp tmsg                ; Jump to return
  1610. PUTMOD  ENDP
  1611.  
  1612. ; clear the mode line written by putmod.  Returns normally.
  1613.  
  1614. CLRMOD  PROC    NEAR
  1615.         mov dx,24*100H
  1616.         call poscur
  1617.         mov dx,offset ceolseq
  1618.         jmp tmsg
  1619. CLRMOD  ENDP
  1620.  
  1621. ; Put a help message in a box at the top of the screen.
  1622. ; This one uses inverse video (or yellow if color)
  1623. ; Pass the message in ax, terminated by a null.  Returns normally.
  1624.  
  1625. PUTHLP  PROC    NEAR
  1626.         cld
  1627.         mov dx,ax               ; Prepare to pass message to 'getnoc'
  1628.         call getnoc             ;
  1629.         mov rnoc,cx             ; This is unformatted NOC in message
  1630.         mov  cx,5               ; Calculate formatted area needed (in words)
  1631.         rol  bx,cl              ; BX is no of lf's.
  1632.         mov  NOC,bx
  1633.         mov cx,2
  1634.         ror bx,cl
  1635.         add NOC,bx              ; This is Lines X 40
  1636.         add NOC,80              ; Current line + one more
  1637.         mov cx,NOC
  1638.         mov si,dx               ; Source of message  given us
  1639.         mov di,attrptr          ; Pointer to screen attrib area
  1640.         mov ax,formdat.bldcrt   ; Need bold attribute
  1641.         rep stosw               ; Cover attribute area needed
  1642.         mov ax,formdat.nrmcrt   ; Rest of screen needs normal color
  1643.         mov cx,1000             ; Whole screen
  1644.         sub cx,NOC              ; Attribute area left to cover
  1645.         rep stosw               ; Do it
  1646.         mov cx,1000             ; Fill screen data area with null bytes
  1647.         mov di,dispptr          ; Pointer to screen data area
  1648.         xor ax,ax               ; This is source of null bytes
  1649.         rep stosw               ; Prepare clean screen data area
  1650.         mov cx,rnoc             ; No of unformatted data bytes
  1651.         mov di,dispptr          ; Destination is screen data area
  1652. pthlp0: push di                 ; Save start of current line
  1653. pthlp1: lodsb                   ; Load data bytes 1-by-1
  1654.         cmp al,cr               ; Is this one an eol?
  1655.         jz pthlp2               ; Yep - handle cr/lf's ourselves
  1656.         stosb                   ; No - move character
  1657.         loop  pthlp1            ; And go back for next
  1658.         jmp short pthlp3        ; Finished moving chars, so exit.
  1659. pthlp2: dec cx                  ; Account for cr and lf
  1660.         dec cx
  1661.         inc si                  ; Skip the lf
  1662.         pop di                  ; Get start of current line.
  1663.         add di,80               ; Adjust pointer to next line
  1664.         jmp short pthlp0        ; And go back for more
  1665. pthlp3: pop di
  1666.         mov noc,2000            ; We are going to write over whole screen
  1667.         mov cmd,2               ; Get cursor position before writing
  1668.         mov dx,offset cmd
  1669.         mov cl,crtcmd
  1670.         int bios                ; Get cursor call
  1671.         mov cx,word ptr la
  1672.         mov savcur,cx           ; Store cursor position
  1673.         mov la,24               ; Prepare to roll down 24 lines
  1674.         mov ca,0
  1675.         mov cmd,3               ; Screen roll down command
  1676.         mov dx,offset cmd
  1677.         mov cl,crtcmd
  1678.         int bios                ; Do it!
  1679.         mov la,0                ; Begin our msg on top line of screen
  1680.         mov cmd,1               ; String write command
  1681.         int bios                ; Write it.
  1682.         mov dx,offset upcur
  1683.         call tmsg
  1684.         mov dx,offset upcur     ; Put cursor up onto clean screen
  1685.         call tmsg
  1686.         or  ourflgs,movcur      ; Tell that we've moved the cursor
  1687.         ret
  1688. PUTHLP  ENDP
  1689.  
  1690. ; Receives message pointer in DX, terminating character in CL
  1691. ; Returns with message ptr in DX, NOC in CX, and number of lf's in BX.
  1692.  
  1693. GETNOC  PROC    NEAR
  1694.         cld
  1695.         mov di,dx
  1696.         mov al,cl                       ; Move terminator to AL
  1697.         mov cx,2000                     ; Longest acceptible message.
  1698.         repnz scasb                     ; Look for terminator
  1699.         jz gtnoc1
  1700.         xor cx,cx
  1701.         ret                             ; Error return
  1702. gtnoc1: sub di,dx                       ; Calculate NOC
  1703.         mov cx,di                       ; Move it to counter
  1704.         dec cx                          ; Discount terminator
  1705.         push cx                         ; Save NOC
  1706.         mov di,dx
  1707.         mov al,lf
  1708.         xor bx,bx
  1709. gtnoc2: repnz scasb                     ; Now count lf's
  1710.         jcxz gtnoc3                     ; If the counter ran out
  1711.         inc bx
  1712.         jmp short gtnoc2
  1713. gtnoc3: pop cx                          ; Recover NOC
  1714.         ret
  1715. GETNOC  ENDP
  1716.  
  1717.  
  1718.  
  1719. ; Produce a short beep.  Returns normally.
  1720.  
  1721. BEEP    PROC    NEAR
  1722.         mov dl,bell
  1723.         mov ah,conout
  1724.         int dos
  1725.         ret
  1726. BEEP    ENDP
  1727.  
  1728. ; Prints $-terminated message in dx, for local use only
  1729.  
  1730. TMSG    PROC    NEAR
  1731.         mov ah,prstr
  1732.         int dos
  1733.         ret
  1734. TMSG    ENDP
  1735.  
  1736. ; Jumping to this location is like retskp.  It assumes the instruction
  1737. ;   after the call is a jmp addr.
  1738.  
  1739. RSKP    PROC    NEAR
  1740.         pop bp
  1741.         add bp,3
  1742.         push bp
  1743.         ret
  1744. RSKP    ENDP
  1745.  
  1746. ; Jumping here is the same as a ret.
  1747.  
  1748. R       PROC    NEAR
  1749.         ret
  1750. R       ENDP
  1751.  
  1752. code    ends
  1753.         end
  1754.  
  1755. ; END OF MSXAPC.ASM
  1756.