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

  1.     NAME    msg55x
  2. ; File MSG55X.ASM
  3. ; Kermit system dependent module for Sanyo MBC-55x
  4. ; Sanyo mods by Robert W. Babcock and Joseph H. White
  5. ; Tektronix emulator for use with MS Kermit/IBM.
  6. ; Edit history:
  7. ; Last edit 19 April 1988, strip out code for other than CGA boards
  8. ; 1 Jan 1988 version 2.30
  9. ; 31 Dec 1987 change name from msvibm to msgibm for final release. [jrd]
  10. ; 29 Dec 1987 Add ESC [ ? 3 8 l     as exit Tek mode command, from VT340's.[jrd]
  11. ; 26 Dec 1987 Add test to absorb echo of crosshairs report. [jrd]
  12. ; 22 Dec 1987 Revise parsing rules to make an escape sequence be a temporary
  13. ;  interruption to the current command (except Clear Screen seq). [jrd]
  14. ; Add Control-C and Control-Break as non-reporting exits from GIN mode. [jrd]
  15. ; 21 Dec 1987 Add AT&T 6300, Olivetti M24 presence tests and run code. [jrd]
  16. ; 16 Dec 1987 Correct screen coloring for 64KB mono/med res color egas. [jrd]
  17. ; 4 Dec 1987 Add quirks for Environments, such as TopView, Windows. [jrd]
  18. ; 3 Dec 1987 Let 128KB EGA boards save screens. [jrd]
  19. ; 30 Nov 1987 Add relative plotting, thanks to help from Bob Parks. [jrd]
  20. ; 24 Nov 1987 Add dashed line patterns. [jrd]
  21. ; 21 Nov 1987 Add full color background. [jrd]
  22. ; 15 Nov 1987 Do screen clears manually because a Bios mode-set keeps
  23. ;  interrupts off long enough to miss serial port characters. Make crosshairs
  24. ;  smaller. [jrd]
  25. ; 8 Nov 1987 Modularize line drawing using Bresneham's algorithm, use pointers
  26. ;  to action routines for different board types. Add screen save/restore.
  27. ;  Do display board presence tests. Add FS as point plot introducer. Allow
  28. ;  for virtual screens when operating under Environments (Windows, etc). [jrd]
  29. ; 1 Nov 1987 Heavy rewrite to integrate code into regular MS Kermit/IBM
  30. ;  material. [jrd]
  31. ;==============================================================================
  32. ; Original version for TI Pro computers by
  33. ; 12-Dec-84  Joe Smith, CSM Computing Center, Golden CO 80401
  34. ; Converted to IBM PCs by Brian Holley, Cambridge Univ.
  35. ; Upgraded and integrated into MS Kermit 2.30 by Joe Doupnik, Utah State Univ.
  36. ;
  37. ;           Description of Tektronix commands
  38. ;
  39. ; ESCAPE-CONTROL-E (ENQ) requests a status report
  40. ; ESCAPE-FORMFEED erases the screen.
  41. ; ESCAPE-CONTROL-Z turns on the crosshairs (not on 4006 or 4025)
  42. ; ESCAPE [ ? 3 8 l  exits Tek mode and returns to host text terminal type
  43. ;  (VT102 if none defined yet). This is an extension from DEC VT340's.
  44. ; CONTROL-] (GS) turns on plot mode, the first move will be with beam off.
  45. ; CONTROL-^ (RS) turns on incremental plot mode. RS space means move pen up
  46. ;  RS P means move pen down, following letters:A, E, D, F, B, J, H, I mean
  47. ;  move right, right and up, up, left and up, left, left and down, down, and
  48. ;  right and down, respectively. Ex: RS <space> J J J  means move three Tek
  49. ;  positions left and down with the pen up (invisibly).
  50. ; CONTROL-UNDERLINE (US) turns off plot mode, as does CR (for all but 4025).
  51. ; CONTROL-X switches from TEKTRONIX sub mode to NORMAL alpha mode but is
  52. ;  ignored if we are emulating a full Tek terminal rather than a sub mode
  53. ;  of DEC or Heath.
  54. ; FF erases screen.
  55. ; ESCAPE letter, where letter is accent grave (`), a-e sets the line drawing
  56. ;   pattern until reset to solid lines (same as escape accent) by command or
  57. ;   a terminal reset.
  58. ; where
  59. ;    ENQ = Control E
  60. ;    ESC = Control [ (left square bracket)
  61. ;    FF = Control L
  62. ;    FS = Control \ (backslash)
  63. ;    GS = Control ] (right square bracket)
  64. ;    RS = Control ^ (caret)
  65. ;    US = Control _ (underscore)
  66. ;
  67. ; The plot commands are characters which specify the absolute position to move
  68. ; the beam.  All moves except the one immediately after the GS character
  69. ; (Control-]) are with a visible trace.
  70. ;
  71. ; For 4010-like devices - The positions are from 0 to 1023 for both X and Y,
  72. ; although only 0 to 780 are visible for Y due to screen geometry.  The screen
  73. ; is 10.23 by 7.80 inches, and coordinates are sent as 1 to 4 characters.
  74. ;
  75. ; For 4014-like devices - The positions are from 0 to 4096, but each movement
  76. ; is a multiple of 4 positions unless the high-resolution LSBXY are sent.  This
  77. ; makes it compatible with the 4010 in that a full sized plot fills the screen.
  78. ;
  79. ; HIX,HIY = High-order 5 bits of position
  80. ; LOX,LOY = Middle-order 5 bits of position
  81. ; LSBXY      = Low-order 2 bits of X + low-order 2 bits of Y (4014 mode)
  82. ;
  83. ; Hi Y      Lo Y      Hi X      LSBXY      Characters sent (Lo-X always sent)
  84. ; ----      ----      ----      -----      ----------------------------------
  85. ; Same      Same      Same      Same                 Lo-X
  86. ; Same      Same      Same      Diff        LSB, Lo-Y,     Lo-X    4014
  87. ; Same      Same      Diff      Same             Lo-Y, Hi-X, Lo-X
  88. ; Same      Same      Diff      Diff        LSB, Lo-Y, Hi-X, Lo-X    4014
  89. ; Same      Diff      Same      Same             Lo-Y,     Lo-X
  90. ; Same      Diff      Same      Diff        LSB, Lo-Y,     Lo-X    4014
  91. ; Same      Diff      Diff      Same             Lo-Y, Hi-X, Lo-X
  92. ; Same      Diff      Diff      Diff        LSB, Lo-Y, Hi-X, Lo-X    4014
  93. ; Diff      Same      Same      Same      Hi-Y,             Lo-X
  94. ; Diff      Same      Same      Diff      Hi-Y, LSB, Lo-Y,     Lo-X    4014
  95. ; Diff      Same      Diff      Same      Hi-Y,         Lo-Y, Hi-X, Lo-X
  96. ; Diff      Same      Diff      Diff      Hi-Y, LSB, Lo-Y, Hi-X, Lo-X    4014
  97. ; Diff      Diff      Same      Same      Hi-Y,         Lo-Y,     Lo-X
  98. ; Diff      Diff      Same      Diff      Hi-Y, LSB, Lo-Y,     Lo-X    4014
  99. ; Diff      Diff      Diff      Same      Hi-y,         Lo-Y, Hi-X, Lo-X
  100. ; Diff      Diff      Diff      Diff      Hi-y, LSB, Lo-Y, Hi-X, Lo-X    4014
  101. ; Offset for byte:          20h    60h  60h   20h     40h
  102. ;
  103. ; Note that LO-Y must be sent if HI-X has changed so that the TEKTRONIX knows
  104. ; the HI-X byte (in the range of 20h-3fh) is HI-X and not HI-Y.     LO-Y must
  105. ; also be sent if LSBXY has changed, so that the 4010 will ignore LSBXY and
  106. ; accept LO-Y.    The LSBXY byte is 60h + MARGIN*10h + LSBY*4 + LSBX. (MARGIN=0)
  107. ;
  108. ;==============================================================================
  109. ;
  110. ; External variable tekflg and calls to tekini, tekemu, tekesc, tekcls:
  111. ; Byte TEKFLG is non-zero when the Tek emulator is active; it is set by the
  112. ; startup code in tekini and is maintained in this file. Internal variable
  113. ; inited remembers if we have a graphics screen saved, etc.
  114. ; TEKINI must be called when entering the emulator to establish the graphics
  115. ; screen mode and to calculate the screen dimensions.
  116. ; TEKESC is called from say mszibm.asm to invoke Tek emulation when the
  117. ; external procedures have detected an Escape Control-L sequence. An implicit
  118. ; initialization is done if necessary.
  119. ; TEKEMU is the normal entry point to pass a received character to the emulator.
  120. ; It too will do an implicit initialization, if required.
  121. ; TEKCLS clears the graphics screen, but only if the emulator is active.
  122. ; The emulator remains active during Connect mode Help, Status, and other
  123. ; interrupts which do not change the terminal type.
  124. ; =============================================================================
  125. ;
  126. ; - ctrl-g (BEL) from line gives beep in tek mode
  127. ; - characters better placed in relation to current beam position
  128. ;    in EGA and Hercules modes
  129. ;   characters OR-ed into place rather than overwriting
  130. ; - add SET TERMINAL GRAPHICS NONE -    this ignores the start-up ESC-FF
  131. ;                    for Tektronix
  132. ; - add MonoEGA mode for monochrome graphics on an EGA
  133. ;
  134. ; version 2.29/t3
  135. ;  changes - stop control characters from echoing to screen in TEKEMU
  136. ;       - show version on name in MSSDEF.H
  137. ; version 2.29b
  138. ; changes with this version:  - faster line drawing, using direct write to
  139. ;                memory rather than BIOS calls
  140. ;                  - support for Hercules, Olivetti, EGA
  141. ;                  - minor bug fixes
  142.  
  143. ; adapted to IBM PC June 1987 by    Brian Holley,
  144. ;                    Faculty of Economics and Politics
  145. ;                    University of Cambridge, England
  146. ;                    Email: BJH6@UK.AC.CAM.PHX
  147.  
  148.     public    tekemu,tekini,tekend    ; Terminal emulation routines
  149.     public    tekcls, tekesc, tekflg    ; used by msz file
  150.  
  151.     include mssdef.h
  152.  
  153. ENQ    equ    05h            ; ^E ENQ for TEK enquiries
  154. CAN    equ    18h            ; ^X to return to ANSI mode
  155. ESCZ    equ    1Ah            ; SUB, ESC-^Z triggers crosshairs
  156. VT    equ    0bh            ; ^K go up one line
  157. FS    equ    1ch            ; ^\ for point plot mode
  158. GS    equ    1Dh            ; ^] draw line (1st move is invisible)
  159. RS    equ    1Eh            ; ^^ for incremental line plot mode
  160. US    equ    1Fh            ; ^_ (underscore) returns to text mode
  161. accent    equ    60h            ; accent grave
  162.  
  163. txtmode equ    4            ; text mode for TEKTRONIX status
  164. maxtekx equ    1024            ; horizontal and
  165. maxteky equ    780            ; vertical resolution of TEK 4010
  166.  
  167. screen    equ    10h            ; bios screen call
  168.  
  169. uparr    equ    72            ; DOS scan codes for arrow keys
  170. dnarr    equ    80
  171. lftarr    equ    75
  172. rgtarr    equ    77
  173. homscn    equ    71            ; DOS home screen scan code
  174. shuparr equ    '8'            ; ascii codes for shifted arrows
  175. shdnarr equ    '2'
  176. shlftarr equ    '4'
  177. shrgtarr equ    '6'
  178.  
  179.                     ; Graph_mode for different systems:
  180. cga    equ    6            ; highest resolution mode for CGA
  181. mono    equ    7            ; real monochrome display adapter
  182. colorega equ    14            ; Low-res mode, color EGA
  183. monoega equ    15            ; mono ega needs mode 15
  184. ega    equ    16            ; Hi-res mode - EGA
  185. olivetti equ    72            ; Olivetti's Hi-res - 50 lines text
  186. hercules equ    255            ; pseudo mode for Hercules graphics
  187. ; Note: IBM VGA mode 18, 640 by 480, can be used by setting "ega" above
  188. ; to 18 and modify ybot to be 479 and ymult to be 48 at label tekin5.
  189. ; The code will scale everything appropriately for the new screen size, but
  190. ; there will be insufficient memory to retain the entire graphics image.
  191. ; Do this at your own risk, please, until PS/2 Tech Refs are available. [jrd]
  192.  
  193. segega    equ    0a000h            ; segments of display memory, EGA
  194. segcga    equ    0b800h            ; CGA, AT&T/Olivetti
  195. seghga    equ    0b000h            ; HGA
  196. segmono equ    0b000h            ; Monochrome
  197.  
  198.                     ; Hercules equates:
  199. index    equ    03b4h            ; 6845 index register
  200. cntrl    equ    03b8h            ; Display mode control port
  201. hstatus equ    03bah            ; status port
  202. scrn_on equ    8            ; bit to turn screen on
  203. grph    equ    2            ; graphics mode
  204. text    equ    20h            ; text mode
  205. config    equ    03bfh            ; configuration port
  206. genable equ    1            ; enable graphics, page 0 only
  207.  
  208. hiy    equ    1            ; codes for Tek graphics components
  209. loy    equ    2
  210. hix    equ    4
  211. lox    equ    3
  212.  
  213. datas    segment public 'datas'
  214.     extrn    flags:byte, portval:word, rxtable:byte, vtemu:byte
  215.     extrn    tv_mode:byte
  216.  
  217. xmult    dw    ?            ; scaling factor for x is
  218. xdiv    dw    ?            ;     xmult/xdiv
  219. ymult    dw    ?            ; scaling factor for y is
  220. ydiv    dw    ?            ;     ymult/ydiv
  221. xmax    dw    ?            ;
  222. ybot    dw    ?            ;
  223.  
  224. ttstate dw    tektxt            ; state machine control pointer
  225. prestate dw    0            ; previous state, across interruptions
  226. visible db    0            ; 0 to move, 1 to draw a line
  227. tek_hiy dw    0            ; Y coordinate in Tektronix mode
  228. tek_loy db    0
  229. tek_hix dw    0            ; X coordinate in Tektronix mode
  230. tek_lox db    0
  231. tek_lsb db    0            ; Low-order 2 bits of X + low Y
  232.                     ;    (4014 mode)
  233. status    db    0
  234. lastc    db    0            ; last x/y coord fragment seen
  235. masktab db    80h,40h,20h,10h,8,4,2,1 ; quicker than calculations!
  236.                     ; dashed line patterns
  237. linetab dw    0ffffh            ; ESC accent    11111111 11111111
  238.     dw    0aaaah            ; ESC a        10101010 10101010
  239.     dw    0f0f0h            ; ESC b        11110000 11110000
  240.     dw    0fafah            ; ESC c        11111010 11111010
  241.     dw    0ffcch            ; ESC d        11111111 11001100
  242.     dw    0fc92h            ; ESC e        11111100 10010010
  243.  
  244. linepat dw    0ffffh            ; active line pattern, from above
  245.  
  246. ;End of init data
  247. IDSEQ    dw    tekem            ; address of response to terminal
  248. CTLTAB    dw    0            ; .. inquiry
  249. tekem    db    'IBM_TEK'        ; .. and the response
  250.     db    escape,'/Z',0
  251. x_coord dw    0            ; Tek text char X coordinate
  252. y_coord dw    8            ; Tek text char Y coordinate
  253. xcross    dw    0            ; cross hairs to start at centre
  254. ycross    dw    0
  255. oldx    dw    0            ; Tek coordinates of last point
  256. oldy    dw    767            ;  initially top left
  257. scalex    dw    0            ; PC coord for scaled x value
  258. scaley    dw    0            ;  for scaled y value
  259. curmode db    0            ; screen mode before graphics
  260.                 ; local variables for LINE plotting routine
  261. graph_mode db    0            ; graphics video mode, default is none
  262. cursor    dw    0            ; saved text cursor
  263. inited    db    0            ; non-zero if inited (retains page)
  264. tekflg    db    0            ; Tek mode active flag
  265. yflags    db    0            ; flags byte from msy
  266. flow    dw    0            ; flow control word
  267. gpage    db    0            ; display adapter graphics page
  268. gfcol    db    15            ; graphics foreground colour
  269. gbcol    db    0            ; graphics background color
  270. moremsg db    ' More >'
  271. mormsglen equ    $-moremsg        ; length of message
  272. ccode    db    0            ; temp for holding plot color code
  273. linelen dw    0            ; offset increment between scan lines
  274. putc    dw    mputc            ; ptr to plot a character routine
  275. psetup    dw    psetupc            ; ptr to plot setup routine
  276. pfin    dw    pfinc            ; ptr to plot cleanup routine
  277. pincy    dw    pincyc            ; ptr to inc y routine
  278. plotptr dw    pltcga            ; ptr to dot plot routine
  279. segscn    dw    0b800h            ; actual screen segment to use
  280. ; ANSI Escape sequence to turn off Media Copy (Print Controller Off)
  281. tkoff    db    escape,'[?38l'        ; Exit Tek mode escape sequence
  282. tkofflen equ    $-tkoff            ; length of sequence
  283. tkoffs    db    6 dup (0)        ; received chars in rcv'd sequence
  284. tkcnt    dw    0            ; counter of matched char in tkoffs
  285. repbuf    db    6 dup (0)        ; crosshairs report buf
  286. repcnt    db    0            ; number of untouched chars in repbuf
  287. temp    dw    0
  288.  
  289. ; 8*8 font for Hercules, CGA, and EGA TEK mode
  290. ; - allows 43 lines, and 80 (90 for Hercules) chars per line.
  291. ; all printing (?) characters from <space> to <del> - two characters per line
  292. ; 8 bits per scan line, given top line first, 8 scan lines.
  293. font    db    0,0,0,0,0,0,0,0,           18h,18h,18h,18h,18h,0,18h,0
  294.     db    6ch,6ch,6ch,0,0,0,0,0,           36h,36h,7fh,36h,7fh,36h,36h,0
  295.     db    0ch,3fh,68h,3eh,0bh,7eh,18h,0, 60h,66h,0ch,18h,30h,66h,06h,0
  296.     db    38h,6ch,6ch,38h,6dh,66h,3bh,0, 0ch,18h,30h,0,0,0,0,0
  297.     db    0ch,18h,30h,30h,30h,18h,0ch,0, 30h,18h,0ch,0ch,0ch,18h,30h,0
  298.     db    0,18h,7eh,3ch,7eh,18h,0,0,     0,18h,18h,7eh,18h,18h,0,0
  299.     db    0,0,0,0,0,18h,18h,30h,           0,0,0,7eh,0,0,0,0
  300.     db    0,0,0,0,0,18h,18h,0,           0,06h,0ch,18h,30h,60h,0,0
  301.     db    3ch,66h,6eh,7eh,76h,66h,3ch,0, 18h,38h,18h,18h,18h,18h,7eh,0
  302.     db    3ch,66h,06h,0ch,18h,30h,7eh,0, 3ch,66h,06h,1ch,06h,66h,3ch,0
  303.     db    0ch,1ch,3ch,6ch,7eh,0ch,0ch,0, 7eh,60h,7ch,06h,06h,66h,3ch,0
  304.     db    1ch,30h,60h,7ch,66h,66h,3ch,0, 7eh,06h,0ch,18h,30h,30h,30h,0
  305.     db    3ch,66h,66h,3ch,66h,66h,3ch,0, 3ch,66h,66h,3eh,06h,0ch,38h,0
  306.     db    0,0,18h,18h,0,18h,18h,0,       0,0,18h,18h,0,18h,18h,30h
  307.     db    0ch,18h,30h,60h,30h,18h,0ch,   0,0,0,7eh,0,7eh,0,0,0
  308.     db    30h,18h,0ch,06h,0ch,18h,30h,   0,3ch,66h,0ch,18h,18h,0,18h,0
  309.     db    3ch,66h,6eh,6ah,6eh,60h,3ch,   0,3ch,66h,66h,7eh,66h,66h,66h,0
  310.     db    7ch,66h,66h,7ch,66h,66h,7ch,   0,3ch,66h,60h,60h,60h,66h,3ch,0
  311.     db    78h,6ch,66h,66h,66h,6ch,78h,   0,7eh,60h,60h,7ch,60h,60h,7eh,0
  312.     db    7eh,60h,60h,7ch,60h,60h,60h,   0,3ch,66h,60h,6eh,66h,66h,3ch,0
  313.     db    66h,66h,66h,7eh,66h,66h,66h,   0,7eh,18h,18h,18h,18h,18h,7eh,0
  314.     db    3eh,0ch,0ch,0ch,0ch,6ch,38h,   0,66h,6ch,78h,70h,78h,6ch,66h,0
  315.     db    60h,60h,60h,60h,60h,60h,7eh,   0,63h,77h,7fh,6bh,6bh,63h,63h,0
  316.     db    66h,66h,76h,7eh,6eh,66h,66h,   0,3ch,66h,66h,66h,66h,66h,3ch,0
  317.     db    7ch,66h,66h,7ch,60h,60h,60h,   0,3ch,66h,66h,66h,6ah,6ch,36h,0
  318.     db    7ch,66h,66h,7ch,6ch,66h,66h,   0,3ch,66h,60h,3ch,06h,66h,3ch,0
  319.     db    7eh,18h,18h,18h,18h,18h,18h,   0,66h,66h,66h,66h,66h,66h,3ch,0
  320.     db    66h,66h,66h,66h,66h,3ch,18h,   0,63h,63h,6bh,6bh,7fh,77h,63h,0
  321.     db    66h,66h,3ch,18h,3ch,66h,66h,   0,66h,66h,66h,3ch,18h,18h,18h,0
  322.     db    7eh,06h,0ch,18h,30h,60h,7eh,   0,7ch,60h,60h,60h,60h,60h,7ch,0
  323.     db    0,60h,30h,18h,0ch,06h,0,0,     3eh,06h,06h,06h,06h,06h,3eh,0
  324.     db    18h,3ch,66h,42h,0,0,0,0,       0,0,0,0,0,0,0,0ffh
  325.     db    30h,18h,0ch,0,0,0,0,0,           0,0,3ch,06h,3eh,66h,3eh,0
  326.     db    60h,60h,7ch,66h,66h,66h,7ch,0, 0,0,3ch,66h,60h,66h,3ch,0
  327.     db    06h,06h,3eh,66h,66h,66h,3eh,0, 0,0,3ch,66h,7eh,60h,3ch,0
  328.     db    0eh,18h,18h,3ch,18h,18h,18h,0, 0,0,3eh,66h,66h,3eh,06h,3ch
  329.     db    60h,60h,7ch,66h,66h,66h,66h,0, 18h,0,38h,18h,18h,18h,3ch,0
  330.     db    18h,0,38h,18h,18h,18h,18h,70h, 60h,60h,66h,6ch,78h,6ch,66h,0
  331.     db    38h,18h,18h,18h,18h,18h,3ch,0, 0,0,76h,7fh,6bh,6bh,63h,0
  332.     db    0,0,7ch,66h,66h,66h,66h,0,     0,0,3ch,66h,66h,66h,3ch,0
  333.     db    0,0,7ch,66h,66h,7ch,60h,60h,0, 0,3eh,66h,66h,3eh,06h,07h
  334.     db    0,0,6ch,76h,60h,60h,60h,0,     0,0,3eh,60h,3ch,06h,7ch,0
  335.     db    30h,30h,7ch,30h,30h,30h,1ch,0, 0,0,66h,66h,66h,66h,3eh,0
  336.     db    0,0,66h,66h,66h,3ch,18h,0,     0,0,63h,6bh,6bh,7fh,36h,0
  337.     db    0,0,66h,3ch,18h,3ch,66h,0,     0,0,66h,66h,66h,3eh,06h,3ch
  338.     db    0,0,7eh,0ch,18h,30h,7eh,0,     0ch,18h,18h,70h,18h,18h,0ch,0
  339.     db    18h,18h,18h,0,18h,18h,18h,0,   30h,18h,18h,0eh,18h,18h,30h,0
  340.     db    31h,6bh,46h,0,0,0,0,0,           8 dup (0ffh)
  341. datas    ends
  342.  
  343. code    segment public 'code'
  344.     extrn    outchr:near, beep:near, scrseg:near, cmblnk:near
  345.     extrn    clrmod:near, savescr:near, cptchr:near, pcwait:near
  346.     extrn    restscr:near, getflgs:near, clrbuf:near, vtans52:near
  347.  
  348.     assume    cs:code, ds:datas, es:nothing
  349.  
  350. ; Initialise TEK mode by setting high resolution screen, etc
  351.  
  352. ;The IBM PC CGA card has (639,199) as the coordinate of the lower-right corner.
  353. ;Calculate endpoint X=(5/8)*(HIX*32+LOX), Y=199-(10/39)*(HIY*32+LOY)
  354.  
  355. tekini    PROC NEAR
  356.     push    ax            ; do presence tests. [jrd]
  357.     push    bx
  358.     push    cx
  359.     push    dx
  360.     push    si
  361.     push    di
  362.     push    es
  363.     mov    bx,portval        ; get port flow control chars:
  364.     mov    bx,[bx].flowc        ; bh=xon, bl=xoff or both are nulls
  365.     mov    flow,bx            ; save here
  366.     mov    ax,bx            ; get flow control word
  367.     cmp    al,0            ; able to do xoff?
  368.     je    tekin0            ; e = no
  369.     call    outmodem        ; tell host xoff while we change modes
  370. tekin0: mov    bx,vtemu.att_ptr    ; emulator screen color ptr
  371.     mov    al,[bx]
  372.     mov    gfcol,al        ; save foreground color
  373.     and    gfcol,0fh        ; save just foreground bits
  374.     and    al,70h            ; select background color, no bold
  375.     mov    cl,4
  376.     shr    al,cl            ; get background colors
  377.     mov    gbcol,al        ; set graphics background color
  378.  
  379.     mov    ah,15            ; get current screen mode
  380.     int    screen
  381.     cmp    al,3            ; in a mono/color text mode (2/3)?
  382.     jbe    tekin1            ; be = yes
  383.     cmp    al,mono            ; mono text mode (7)?
  384.     je    tekin1            ; e = yes
  385.     cmp    tekflg,0        ; are we active as Tek device now?
  386.     je    tekin1            ; e = no
  387.     jmp    tekin13            ; yes, don't redo graphics setup
  388. tekin1: mov    curmode,al        ; save mode here
  389.     mov    ah,3            ; get cursor position
  390.     xor    bh,bh            ; page 0
  391.     int    screen
  392.     mov    cursor,dx        ; save position
  393.     call    savescr            ; save text screen
  394.                     ; Presence tests.
  395. tekin2: mov    graph_mode,cga        ; Color. Assume CGA
  396.     mov    segscn,segcga        ; assume cga screen segment
  397.     mov    gpage,0            ; graphics page 0 but no page 1
  398.     mov    putc,offset gputc    ; CGA character display routine
  399.     mov    psetup,offset psetupc    ; CGA plot setup routine
  400.     mov    plotptr,offset pltcga    ; CGA dot plot routine
  401.     mov    pfin,offset pfinc    ; CGA cleanup routine
  402.     mov    pincy,offset pincyc    ; CGA inc y routine
  403.     mov    xmult,5            ; CGA. Scale TEK to PC by 640/1024
  404.     mov    xdiv,8            ;  so that 0-1023 converts to 0-639
  405.     mov    xmax,640-8        ; x-coord of rightmost character
  406.     mov    ymult,10        ; vertical scale for IBM is 200/780
  407.     mov    ydiv,39            ;
  408.     mov    ybot,199        ; Bottom of screen is Y=199
  409.                     ; test for CGA
  410. tekin11:mov    graph_mode,cga        ; set CGA high resolution graphics
  411.     mov    segscn,segcga        ; CGA screen segment
  412.     jmp    tekin13
  413.  
  414.                     ; Set Graphics mode
  415. tekin13:
  416. tekin14:mov    ah,0            ; set screen mode
  417.     mov    al,graph_mode        ;  to this screen mode
  418.     cmp    gpage,0            ; only page 0 available?
  419.     je    tekin15            ; e = yes, and watch for Bios errors
  420.     cmp    inited,0        ; first time through?
  421.     je    tekin15            ; e = yes, clear the page of old junk
  422.     or    al,80h            ; save regen buffer (save area too)
  423. tekin15:int    screen            ; Bios Set Mode.
  424.  
  425. tekin16:mov    tekflg,1        ; starting Tek sub mode
  426.     cmp    inited,0        ; inited yet?
  427.     jne    tekin19            ; ne = yes, restore screen
  428.     mov    ttstate,offset tektxt    ; do displayable text
  429.     mov    prestate,offset tektxt    ; set a previous state of text
  430.     mov    inited,1        ; say we have initialized
  431.     call    tekcls            ; clear screen, for ega coloring
  432.     jmp    short tekin20
  433. tekin19:call    tekrest            ; restore old graphics screen
  434. tekin20:mov    ax,flow            ; get flow control word
  435.     xchg    ah,al            ; get xon into al
  436.     cmp    al,0            ; able to send xon?
  437.     je    tekin21            ; e = no
  438.     call    outmodem        ; tell host xon
  439. tekin21:clc                ; clear carry for success
  440.     jmp    short tekin23
  441. tekin22:stc                ; set carry for failure
  442. tekin23:pop    es
  443.     pop    di
  444.     pop    si
  445.     pop    dx
  446.     pop    cx
  447.     pop    bx
  448.     pop    ax
  449.     ret
  450. tekini    ENDP
  451.  
  452. ;Terminal emulation. Enter with received character in AL.
  453.  
  454. TEKEMU PROC    NEAR            ; main emulator
  455.     cmp    tekflg,0        ; Tek mode active yet? (msz call)
  456.     jne    tektt1            ; ne = yes
  457.     call    tekini            ; init now
  458.     mov    ttstate,offset tektxt    ; initial state
  459.     mov    prestate,offset tektxt    ; set a previous state of text
  460.     jnc    tektt1            ; nc = succeeded
  461.     ret                ; else failed to init, just return
  462. tektt1: and    al,7fh            ; force Tek chars to be 7 bits.
  463.     cmp    al,0            ; NUL char?
  464.     je    tekign            ; e = yes, ignore it before logging
  465.     push    ax
  466.     call    getflgs            ; get msy yflags into al
  467.     mov    yflags,al
  468.     test    al,capt            ; capturing output?
  469.     pop    ax
  470.     jz    tektt4            ; z = no, forget this part
  471.     push    ax            ; save char
  472.     call    cptchr            ; give it captured character
  473.     pop    ax            ; restore character and keep going
  474. tektt4: test    yflags,trnctl        ; debug? if so use tty mode
  475.     jz    tektt5            ; z = no
  476.     cmp    al,DEL            ; DEL char?
  477.     jne    tektt4a            ; ne = no
  478.     mov    al,5eh            ; make DEL a caret query mark
  479.     call    outscrn
  480.     mov    al,3fh            ; the query mark
  481.     call    outscrn
  482.     jmp    short tekign
  483. tektt4a:cmp    al,' '            ; control char?
  484.     jae    tektt4b            ; ne = no
  485.     push    ax
  486.     mov    al,5eh            ; caret
  487.     call    outscrn
  488.     pop    ax
  489.     add    al,'A'-1        ; make char printable
  490. tektt4b:call    outscrn
  491.  
  492. tekign: ret                ; Ignore this character
  493.  
  494. tektt5: call    tkscan            ; scan for "ESC [ ? 3 8 l" exit code
  495.     cmp    al,0            ; null char response?
  496.     je    tekign            ; e = yes, ignore the character
  497.                     ; check for echo of crosshair report
  498.     cmp    repcnt,0        ; any chars need matching in report?
  499.     je    tektt5a            ; e = no
  500.     push    bx            ; yes
  501.     mov    bx,6            ; number of bytes in crosshairs rpt
  502.     sub    bl,repcnt        ; number of chars needing matching
  503.     cmp    al,repbuf[bx]        ; received same as current rpt char?
  504.     pop    bx
  505.     jne    tektt5a            ; ne = mismatch, stop echo test
  506.     dec    repcnt            ; say one more matched
  507.     clc                ; absorb without comment
  508.     ret                ; stay in this state
  509. tektt5a:mov    repcnt,0        ; clear report count
  510.     cmp    al,' '            ; control code?
  511.     jb    tektt6            ; b = yes, decode
  512.     jmp    ttstate            ; no, do current state
  513.                     ; Control characters:
  514. tektt6: cmp    al,GS            ; Line plot command?
  515.     jne    tektt7            ; ne = no
  516.     mov    visible,0        ; Next move is invisible
  517.     and    status,not txtmode    ; set status report byte
  518.     mov    ttstate,offset tekline    ; expect coordinates next
  519.     jmp    tektt12
  520. tektt7: cmp    al,RS            ; Incremental dot command?
  521.     jne    tektt8            ; ne = no
  522.     and    status,not txtmode    ; set status report
  523.     mov    ttstate,offset tekrlin    ; expect pen command next
  524.     jmp    tektt12
  525. tektt8: cmp    al,FS            ; Point plot command?
  526.     jne    tektt9            ; ne = no
  527.     mov    visible,0        ; next move is invisible
  528.     and    status,not txtmode    ; set status report byte
  529.     mov    ttstate,offset tekpnt
  530.     jmp    tektt12
  531. tektt9: cmp    al,US            ; assert text mode? [bjh]
  532.     jne    tektt10            ; ne = no
  533.     or    status,txtmode        ; set status report byte
  534.     mov    ttstate,offset tektxt    ; Go to TEKTXT next time
  535.     jmp    tektt12
  536. tektt10:cmp    al,ESCAPE        ; Escape?
  537.     jne    tektt11            ; ne = no
  538.     or    status,txtmode        ; set status report byte
  539.     cmp    ttstate,offset tekesc    ; already in escape state?
  540.     je    tektt14            ; e = yes, nest no further
  541.     push    ttstate            ; current state
  542.     pop    prestate        ; save here as previous state
  543.     mov    ttstate,offset tekesc    ; next state parses escapes
  544.     ret
  545. tektt11:cmp    al,CAN            ; Control X? (exits Tek sub mode)
  546.     jne    tektt13            ; ne = no, stay in current state
  547.     mov    ttstate,offset tektxt    ; back to text mode
  548.     test    flags.vtflg,tttek    ; main Tek emulator?
  549.     jnz    tektt12            ; nz = yes, ignore the ^X
  550.     call    tekend            ; else exit sub mode
  551.     mov    tekflg,0        ; clear Tek sub mode flag
  552. tektt12:mov    prestate,offset tektxt    ; make previous state text
  553. tektt14:ret
  554. tektt13:jmp    ttstate            ; let someone else worry about this
  555. TEKEMU    ENDP
  556.  
  557. ; End TEK emulation, recover previous screen
  558.  
  559. TEKEND    PROC    NEAR
  560.     cmp    tekflg,0        ; Tek sub mode active?
  561.     jne    teknd0            ; ne = yes
  562.     ret                ; else return as is.
  563. teknd0: call    teksave            ; save graphics screen to page 1
  564. teknd1: mov    ah,0            ; set video mode
  565.     mov    al,curmode        ; restore previous screen mode
  566.     int    screen            ; revert to text screen
  567.     call    restscr            ; restore text screen
  568.     mov    dx,cursor        ; saved cursor position
  569.     mov    bh,0            ; page 0
  570.     mov    ah,2            ; set cursor
  571.     int    screen
  572.     ret
  573. TEKEND    ENDP
  574.  
  575. ; State machine active while Tek is active. Senses ESC [ ? 3 8 l to exit
  576. ; Tek mode and return to either non-sub mode terminal or to a VT102.
  577. ; Plays back unmatched escape sequences. Enter with character in al.
  578.  
  579. tkscan    proc    near
  580.     and    al,7fh            ; strip high bit
  581.     cmp    al,byte ptr tkoff    ; start of Tek Off sequence?
  582.     jne    tkscn1            ; ne = no
  583.     call    tkscn4            ; playback previously matched chars
  584.     mov    tkcnt,1            ; count matched chars (one now)
  585.     mov    tkoffs,al        ; save full character, with high bit
  586.     mov    al,0            ; our temporary response
  587.     jmp    short tkscnx        ;  and exit
  588.  
  589. tkscn1: push    bx            ; check for char in Tek Off sequence
  590.     mov    bx,tkcnt        ; number of chars matched in Tek Off
  591.     mov    tkoffs[bx],al        ; save this char
  592.     cmp    al,byte ptr tkoff[bx]    ; match expected char in sequence?
  593.     pop    bx
  594.     jne    tkscn3            ; ne = no, play back partial match
  595.     inc    tkcnt            ; count new match
  596.     mov    al,0            ; our temporary response
  597.     cmp    tkcnt,tkofflen        ; matched all char in sequence?
  598.     jne    tkscnx            ; ne = not yet, wait for more
  599.     mov    tkcnt,0            ; clear counter
  600.     cmp    flags.vtflg,tttek    ; are we a full Tek terminal now?
  601.     jne    tkscn2            ; ne = no, a submode
  602.     call    vtans52            ; toggle terminal type, in msyibm
  603. tkscn2: mov    al,CAN            ; simulate arrival of Control-X
  604.     jmp    short tkscnx        ;  all done
  605.  
  606. tkscn3: call    tkscn4            ; playback previously matched chars
  607.     mov    tkcnt,0            ; reset to no match and exit
  608. tkscnx: ret                ; common exit
  609.  
  610.                     ; local worker procedure
  611. tkscn4: push    ax            ; save break char (in al)
  612.     push    cx            ; playback partial sequence to printer
  613.     mov    cx,tkcnt        ; number of chars matched before break
  614.     jcxz    tkscn4b            ; z = none
  615.     push    si
  616.     mov    si,offset tkoffs    ; string to be played back
  617. tkscn4a:cld
  618.     lodsb                ; get a char into al
  619.     push    cx
  620.     push    si            ; save these around tektt5a work
  621.     call    tektt5a            ; use it
  622.     pop    si
  623.     pop    cx
  624.     loop    tkscn4a            ; do all that came in previously
  625.     pop    si
  626. tkscn4b:pop    cx
  627.     pop    ax            ; recover break char
  628.     ret
  629. tkscan    endp
  630.  
  631.  
  632. TEKTXT    proc    near            ; Dispatch on text characters
  633.     cmp    al,DEL            ; RUBOUT?
  634.     jne    tektx1            ; ne = no
  635.     mov    al,bs            ; make <BS>
  636. tektx1: cmp    al,CR            ; ^M Carriage return?
  637.     je    tektx7            ; e = yes
  638. tektx2: cmp    al,LF            ; ^J LineFeed?
  639.     je    tektx7            ; e = yes
  640. tektx3: cmp    al,FF            ; ^L Formfeed?
  641.     jne    tektx4            ; ne = no
  642.     call    tekcls            ; clear the screen
  643.     jmp    short tektx8
  644. tektx4: cmp    al,VT            ; ^K vertical tab?
  645.     je    tektx7
  646.     cmp    al,bell            ; ^G bell on line?
  647.     jne    tektx5            ; ne = no
  648.     call    beep
  649.     jmp    short tektx8
  650. tektx5: cmp    al,Tab            ; Tab?
  651.     jne    tektx6            ; ne = no
  652.     mov    al,' '            ; make it a space
  653. tektx6: cmp    al,BS            ; ^H backspace?
  654.     je    tektx7            ; e = yes
  655.     cmp    al,' '            ; control char?
  656.     jb    tektx8            ; b = yes, ignore it
  657. tektx7: call    OUTSCRN            ; output character to the screen
  658. tektx8: ret
  659. TEKTXT    endp
  660.  
  661. ; Process escape sequences. Callable from msz terminal emulator.
  662. ; Enter with received character in AL. Escape sequences are generally
  663. ; treated as interruptions to the current plotting/text command. Screen
  664. ; clearing is the exception by causing a general emulator reset.
  665. TEKESC    PROC    NEAR
  666.     mov    ttstate,offset tekesc    ; in case get here from msz file
  667.     cmp    tekflg,0        ; Tek mode active yet? (msz call)
  668.     jne    tekesc1            ; ne = yes
  669.     call    tekini            ; init now
  670.     mov    prestate,offset tektxt    ; set a previous state of text
  671.     jnc    tekesc1            ; nc = succeeded
  672.     ret                ; else failed to init, just return
  673.  
  674. tekesc1:cmp    al,'Z'            ; ESC-Z Identify?
  675.     jne    tekesc2            ; ne = no
  676.     call    SENDID            ; Send terminal identification
  677.     jmp    tekescx
  678.  
  679. tekesc2:cmp    al,FF            ; ESC-FF Clear screen?
  680.     jne    tekesc3            ; ne = no
  681.     call    tekcls            ; Clear screen
  682.     mov    prestate,offset tektxt    ; make previous state text mode
  683.     jmp    tekescx            ; Return to text mode after ESC-FF
  684.  
  685. tekesc3:cmp    al,ESCZ            ; ESC-^Z Enter GIN mode?
  686.     jne    tekesc4            ; ne = no
  687.     cmp    graph_mode,mono        ; Monochrome text mode?
  688.     je    tekesc3a        ; e = yes, no crosshairs in text mode
  689.     call    CROSHAIR        ; Activate the cross-hairs
  690.     jmp    tekescx
  691. tekesc3a:call    beep            ; tell the user we are unhappy
  692.     jmp    tekescx            ; and ignore the command
  693.  
  694. tekesc4:cmp    al,ENQ            ; ESC-^E Enquiry for cursor position?
  695.     jne    tekesc5            ; ne = no
  696.     call    SENDSTAT        ; send status
  697.     jmp    tekescx
  698.  
  699. tekesc5:cmp    al,accent        ; accent grave, line pattern series?
  700.     jb    tekescx            ; b = no
  701.     cmp    al,65h            ; lowercase e?
  702.     ja    tekescx            ; a = beyond line pattern series
  703.     push    bx
  704.     mov    bl,al
  705.     sub    bl,accent        ; remove bias
  706.     mov    bh,0
  707.     shl    bx,1            ; make this a word index
  708.     mov    bx,linetab[bx]        ; get line pattern word
  709.     mov    linepat,bx        ; save in active word
  710.     pop    bx            ; return to previous mode
  711.  
  712. tekescx:push    ax
  713.     mov    ax,prestate        ; get previous state
  714.     mov    ttstate,ax        ; restore it
  715.     or    ax,ax            ; test for none
  716.     pop    ax
  717.     jz    go2text            ; z = none, use text mode
  718.     clc
  719.     ret                ; resume previous state
  720.  
  721. go2text:mov    ttstate,offset tektxt    ; Go to TEKTXT next time
  722.     mov    lastc,0            ; clear last drawing coordinate flag
  723.     or    status,txtmode        ; set text mode in status byte
  724.     clc
  725.     ret
  726.  
  727. TEKESC    ENDP
  728.  
  729. TEKLINE proc    near            ; GS line drawing
  730.     call    tekxyc            ; parse coordinates from input bytes
  731.     jnc    teklin1            ; nc = not done yet
  732.     mov    cl,visible        ; get moveto or drawto variable
  733.     call    tekdraw            ; move that point
  734.     mov    visible,1        ; say next time we draw
  735. teklin1:ret
  736. TEKLINE endp
  737.  
  738. TEKPNT    proc    near            ; FS plot single point
  739.     call    tekxyc            ; parse coordinates
  740.     jnc    tekpnt1            ; nc = not done yet
  741.     mov    cl,0            ; do not draw
  742.     call    tekdraw            ; move to the point
  743.     mov    ax,si            ; copy starting point to end point
  744.     mov    bx,di            ; ax,bx,si,di are in PC coordinates
  745.     mov    cl,1            ; make plot visible
  746.     call    line            ; draw the dot
  747.     mov    visible,0        ; return to invisibility
  748. tekpnt1:ret
  749. TEKPNT    endp
  750.  
  751. ; Decode graphics x,y components. Returns carry set to say have all
  752. ; components for a line, else carry clear. Understands 4014 lsb extensions.
  753. ; Permits embedded escape sequences.
  754. TEKXYC    proc    near
  755.     cmp    al,CR            ; Exit drawing on CR,LF,RS,US,FS,CAN
  756.     je    go2text            ; e = yes, a cr
  757.     cmp    al,LF            ; these terminate line drawing cmds
  758.     je    go2text
  759.     cmp    al,FS            ; <FS>
  760.     je    go2text
  761.     cmp    al,RS            ; <RS>
  762.     je    go2text
  763.     cmp    al,US            ; <US>
  764.     je    go2text
  765.     cmp    al,CAN            ; and <CAN>
  766.     je    go2text            ; BUT ignore other control chars
  767.     cmp    al,20h            ; Control char?
  768.     jb    tekgh0            ; b = yes, ignore it
  769.     cmp    al,40h
  770.     jb    tekgh2            ; 20-3F are HIX or HIY
  771.     cmp    al,60h            ; 40-5F are LOX (causes beam movement)
  772.     jb    tekgh4            ; 60-7F are LOY
  773.  
  774.                     ; Extract low-order 5 bits of Y coord
  775.     mov    ah,tek_loy        ; Copy previous LOY to MSB (4014)
  776.     mov    tek_lsb,ah
  777.     and    al,1Fh            ; LOY is 5 bits
  778.     mov    tek_loy,al
  779.     cmp    lastc,loy        ; 2nd LOY in a row?
  780.     je    tekgh1            ; Yes, then LSB is valid
  781.     mov    tek_lsb,0        ; 1st one, clear LSB
  782. tekgh1: mov    lastc,loy        ; LOY seen, expect HIX (instead of HIY)
  783. tekgh0: clc                ; c clear = not completed yet
  784.     ret
  785.               ; Extract high-order 5 bits (X or Y, depending on lastc)
  786. tekgh2: and    ax,1Fh            ; Just 5 bits
  787.     mov    cl,5
  788.     shl    ax,cl            ; Shift over 5 bits
  789.     cmp    lastc,loy        ; was last coordinate a low-y?
  790.     je    tekgh3            ; e = yes, parse hix
  791.     mov    tek_hiy,ax        ; this byte has HIY
  792.     mov    lastc,hiy
  793.     clc
  794.     ret
  795. tekgh3: mov    tek_hix,ax        ; This byte has HIX
  796.     mov    lastc,hix
  797.     clc
  798.     ret
  799. tekgh4: and    al,1Fh            ; Just 5 bits
  800.     mov    tek_lox,al
  801.     mov    lastc,lox
  802.     mov    ax,tek_hix        ; Combine HIX*32
  803.     or    al,tek_lox        ;  with LOX
  804.     mov    bx,tek_hiy        ; Same for Y
  805.     or    bl,tek_loy
  806.     stc                ; set c to say completed operation
  807.     ret
  808. TEKXYC    endp
  809.  
  810. TEKRLIN proc    near            ; RS relative line drawing
  811.     cmp    al,' '            ; Pen up command?
  812.     jne    tekrli1            ; ne = no, try pen down
  813.     mov    visible,0        ; do invisible movements
  814.     jmp    short tekrli2        ; do the command
  815. tekrli1:cmp    al,'P'            ; pen down command?
  816.     jne    tekrli3            ; ne = no, return to text mode
  817.     mov    visible,1        ; set visible moves
  818.  
  819. tekrli2:mov    ax,x_coord        ; PC x coordinate of pen
  820.     mov    bx,y_coord        ;    y coordinate
  821.     call    pctotek            ; get current pen position in Tek coor
  822.     mov    cl,0            ; invisible, moveto
  823.     call    tekdraw            ; move that point, set oldx and oldy
  824.     mov    ttstate,offset tekinc    ; next get incremental movement cmds
  825.     ret
  826.  
  827. tekrli3:mov    visible,0        ; bad char, reset visibility
  828.     push    prestate
  829.     pop    ttstate            ; restore previous state
  830.     jmp    tektt5            ; deal with the break char
  831. TEKRLIN endp
  832.                     ; interpret RS inc plot command byte
  833. TEKINC    proc    near            ; get movement character and do cmd
  834.     cmp    al,'A'            ; move right?
  835.     jne    tekinc1            ; ne = no
  836.     inc    oldx            ; adjust beam position
  837.     jmp    short tekinc9
  838. tekinc1:cmp    al,'E'            ; move right and up?
  839.     jne    tekinc2            ; ne = no
  840.     inc    oldx
  841.     inc    oldy
  842.     jmp    short tekinc9
  843. tekinc2:cmp    al,'D'            ; move up?
  844.     jne    tekinc3            ; ne = no
  845.     inc    oldy
  846.     jmp    short tekinc9
  847. tekinc3:cmp    al,'F'            ; move left and up?
  848.     jne    tekinc4            ; ne = no
  849.     dec    oldx
  850.     inc    oldy
  851.     jmp    short tekinc9
  852. tekinc4:cmp    al,'B'            ; move left?
  853.     jne    tekinc5            ; ne = no
  854.     dec    oldx
  855.     jmp    short tekinc9
  856. tekinc5:cmp    al,'J'            ; move left and down?
  857.     jne    tekinc6            ; ne = no
  858.     dec    oldx
  859.     dec    oldy
  860.     jmp    short tekinc9
  861. tekinc6:cmp    al,'H'            ; move down?
  862.     jne    tekinc7            ; ne = no
  863.     dec    oldy
  864.     jmp    short tekinc9
  865. tekinc7:cmp    al,'I'            ; move right and down?
  866.     jne    tekincb            ; ne = no, bad command
  867.     inc    oldx
  868.     dec    oldy
  869. tekinc9:cmp    oldx,0            ; too far left?
  870.     jge    tekinc10        ; ge = no
  871.     mov    oldx,0            ; else stop at the left margin
  872. tekinc10:cmp    oldx,maxtekx-1        ; too far left?
  873.     jle    tekinc11        ; le = no
  874.     mov    oldx,maxtekx-1        ; else stop that the left margin
  875. tekinc11:cmp    oldy,maxteky-1        ; above the top?
  876.     jle    tekinc12        ; le = no
  877.     mov    oldy,maxteky-1        ; else stop at the top
  878. tekinc12:cmp    oldy,0            ; below the bottom?
  879.     jge    tekinc13        ; ge = no
  880.     mov    oldy,0            ; else stop at the bottom
  881. tekinc13:mov    ax,oldx            ; ax is vector x end point
  882.     mov    bx,oldy            ; bx is vector y end point
  883.     mov    cl,visible
  884.     call    tekdraw            ; move/draw to that point
  885.     ret
  886. tekincb:push    prestate        ; bad character, exit inc plot mode
  887.     pop    ttstate            ; new state is previous state
  888.     mov    visible,0
  889.     jmp    tektt5            ; reparse the bad char
  890. TEKINC    endp
  891.  
  892.  
  893. ; Routine to trigger the crosshairs, wait for a key to be struck, and send
  894. ; the typed char (if printable ascii) plus four Tek encoded x,y position
  895. ; coordinates and then a carriage return.
  896. ; ax, by, xcross, ycross operate in PC coordinates.
  897.  
  898. CROSHAIR PROC NEAR
  899.     push    linepat            ; save line drawing pattern
  900.     mov    linepat,0ffffh        ; reset line type to solid
  901.  
  902. crosha0:mov    ax,xmax            ; right margin minus 7 dots
  903.     add    ax,7
  904.     mov    temp,ax            ; right margin dot
  905.     shr    ax,1            ; central position
  906.     mov    xcross,ax        ; save PC coord for crosshair
  907.     mov    ax,ybot            ; last scan line
  908.     shr    ax,1
  909.     mov    ycross,ax        ; this is the center of the screen
  910. crosha1:call    crosdraw        ; draw the cross-hairs
  911.     mov    ah,coninq        ; DOS, quiet read char
  912.     int    dos
  913.     push    ax            ; save char for later
  914.     call    crosdraw        ; erase cross hairs
  915.     pop    ax
  916.     or    al,al            ; ascii or scan code returned
  917.     jnz    arrow5            ; nz = ascii char returned
  918.  
  919.     mov    ah,coninq        ; read scan code
  920.     int    dos
  921.     cmp    al,0            ; Control-Break?
  922.     jne    crosha3            ; ne = no, something else
  923. crosha2:pop    linepat            ; restore line pattern
  924.     ret                ; exit crosshairs mode
  925.  
  926. crosha3:cmp    al,homscn        ; is it 'home'?
  927.     je    crosha0            ; e = yes
  928.     jmp    short arrow1        ; else try the arrow keys
  929.  
  930. arrow1: cmp    al,lftarr        ; left arrow?
  931.     jne    arrow2            ; ne = no
  932.     mov    cx,-1            ; left shift
  933.     jmp    short xkeys
  934. arrow2: cmp    al,rgtarr        ; right arrow?
  935.     jne    arrow3            ; ne = no
  936.     mov    cx,1            ; right shift
  937.     jmp    short xkeys
  938. arrow3: cmp    al,uparr        ; up arrow?
  939.     jne    arrow4            ; ne = no
  940.     mov    cx,-1            ; up shift
  941.     jmp    short vertkey
  942. arrow4: cmp    al,dnarr        ; down arrow?
  943.     jne    badkey            ; ne = no, ignore it
  944.     mov    cx,1            ; down shift
  945.     jmp    short vertkey
  946.  
  947. badkey: call    beep            ; tell user we don't understand
  948.     jmp    crosha1            ; keep going
  949.  
  950.                     ; Shifted keys yield ascii keycodes
  951. arrow5: cmp    al,'C' and 1fh        ; Control-C?
  952.     je    crosha2            ; e = yes, exit crosshairs mode now
  953.     cmp    al,shlftarr        ; shifted left arrow?
  954.     jne    arrow6            ; ne = no
  955.     mov    cx,-64            ; big left shift
  956.     jmp    short xkeys
  957. arrow6: cmp    al,shrgtarr        ; shifted right arrow?
  958.     jne    arrow7            ; ne = no
  959.     mov    cx,64            ; big right shift
  960.     jmp    short xkeys
  961. arrow7: cmp    al,shuparr        ; shifted up arrow?
  962.     jne    arrow8            ; ne = no
  963.     mov    cx,-32            ; big up shift
  964.     jmp    short vertkey
  965. arrow8: cmp    al,shdnarr        ; shifted down arrow?
  966.     jne    charkey            ; ne = no, send this key as is
  967.     mov    cx,32            ; big down shift
  968.     jmp    short vertkey
  969.  
  970. xkeys:    add    cx,xcross        ; add increment
  971.     jns    noxc            ; gone too far negative?
  972.     mov    cx,0            ; yes - then make it 0
  973. noxc:    cmp    cx,temp            ; too far right?
  974.     jb    xdraw9            ; b = no
  975.     mov    cx,temp            ; yes - then make it the right
  976. xdraw9: mov    xcross,cx        ; new x value for cross hairs
  977.     jmp    crosha1            ; and redraw
  978.  
  979. vertkey:add    cx,ycross        ; adjust cx
  980.     jns    noyc            ; gone negative?
  981.     mov    cx,0            ; yes then make 0
  982. noyc:    cmp    cx,ybot            ; too high?
  983.     jb    yok
  984.     mov    cx,ybot            ; make it maximum
  985. yok:    mov    ycross,cx        ; save new y crosshair
  986.     jmp    crosha1            ; and redraw
  987.  
  988. charkey:call    clrbuf            ; purge received data to date
  989.     mov    repcnt,6        ; set length of report string
  990.     mov    repbuf,al        ; store first report character
  991.     call    outmodem        ; send the break character
  992.     mov    ax,xcross        ; set beam to xcross,ycross
  993.     mov    bx,ycross        ; must convert to Tek coordinates
  994.     call    pctotek            ; scale from PC screen coord to Tek
  995.     push    ax            ; save around drawing
  996.     push    bx
  997.     mov    cx,0            ; just a move
  998.     call    tekdraw            ; moveto ax,bx in Tek coord
  999.     pop    bx            ; recover Tek y
  1000.     pop    ax            ; recover Tek x
  1001.     call    sendpos            ; send position report to host
  1002.     pop    linepat            ; recover current line drawing pattern
  1003.     ret
  1004. CROSHAIR ENDP
  1005.  
  1006. ; CROSDRAW draws cross-hairs by XORing cross with picture.
  1007. ; xcross and ycross are in PC coordinates.
  1008. CROSDRAW PROC    NEAR
  1009.     mov    si,xcross        ; move to (xcross, ycross-12)
  1010.     mov    di,ycross
  1011.     sub    di,12            ; half the size of the cross
  1012.     jns    crosd1            ; no sign bit means ok
  1013.     mov    di,0            ; else limit to start of screen
  1014. crosd1: mov    ax,si            ; next, draw to (xcross, ycross+12)
  1015.     mov    bx,ycross        ; make bottom stroke
  1016.     add    bx,12
  1017.     cmp    bx,ybot            ; too large?
  1018.     jbe    crosd2            ; be = no
  1019.     mov    bx,ybot            ; vertical line to (xcross,ybot)
  1020. crosd2: mov    cx,0ffh            ; invert pixels
  1021.     call    line            ; and draw vertical
  1022.     sub    si,12            ; move to (xcross-12, ycross)
  1023.     jns    crosd3            ; no sign means ok
  1024.     mov    si,0            ; else limit to start of line
  1025. crosd3: mov    di,ycross
  1026.     mov    bx,di
  1027.     mov    ax,xcross        ; draw to (xcross+12, ycross)
  1028.     add    ax,12
  1029.     cmp    ax,temp            ; temp is right margin, too large?
  1030.     jbe    crosd4            ; be = no, ok
  1031.     mov    ax,temp            ; max x value
  1032. crosd4: mov    cx,0ffh            ; set XOR code
  1033.     call    line            ; draw to (xcross+12, ycross)
  1034.     ret
  1035. CROSDRAW ENDP
  1036.  
  1037. ; SENDPOS sends position of cross-hairs to the host.
  1038. ; ax has Tek X and bx has Tek Y coord of center of crosshair
  1039. SENDPOS PROC NEAR
  1040.     push    bx            ; preserve register
  1041.     call    sendxy            ; send x coord
  1042.     mov    word ptr repbuf+1,ax    ; first word
  1043.     pop    ax
  1044.     call    sendxy            ; send y coord
  1045.     mov    word ptr repbuf+3,ax    ; second word
  1046.     mov    al,cr            ; follow up with cr
  1047.     mov    repbuf+5,al        ; last report character
  1048.     call    outmodem
  1049.     ret
  1050. SENDPOS ENDP
  1051.  
  1052. ; SENDXY sends value of ax as Tek encoded bytes
  1053. ; ax is in Tek coordinates
  1054. SENDXY    PROC    NEAR
  1055.     shl    ax,1
  1056.     shl    ax,1            ; move all but lower 5 bits to ah
  1057.     shl    ax,1
  1058.     shr    al,1
  1059.     shr    al,1            ; move low five bits to low 5 bits
  1060.     shr    al,1
  1061.     or    ah,20h            ; make it a printing char as per TEK
  1062.     xchg    al,ah            ; send high 5 bits first
  1063.     call    outmodem
  1064.     xchg    al,ah            ; then low five bits
  1065.     or    al,20h
  1066.     call    outmodem
  1067.     xchg    ah,al            ; al is first sent byte
  1068.     ret
  1069. SENDXY    ENDP
  1070.  
  1071.  
  1072. SENDID    PROC NEAR            ; Pretend VT100 with graphics option
  1073.     mov    bx,IDSEQ        ; Get addr of string
  1074. sndid1: mov    al,[bx]            ; Get char from sequence
  1075.     cmp    al,0            ; End of sequence?
  1076.     jz    sndid0            ; Yes, return
  1077.     call    OUTMODEM        ; Send it out the port
  1078.     inc    bx
  1079.     jmp    sndid1
  1080. sndid0: ret
  1081. SENDID    ENDP
  1082.  
  1083. ; SENDSTAT - send status and cursor position to host
  1084.  
  1085. SENDSTAT PROC NEAR
  1086.     mov    al,STATUS        ; get tek status
  1087.     or    al,20h            ; make it printable
  1088.     call    OUTMODEM        ; and send it
  1089.     mov    ax,oldx            ; now send x coordinate (oldx is Tek)
  1090.     call    SENDXY
  1091.     mov    ax,oldy            ; and y coordinate (oldy is Tek coord)
  1092.     call    SENDXY
  1093.     mov    al,cr            ; end with a cr
  1094.     call    OUTMODEM
  1095.     ret
  1096. SENDSTAT ENDP
  1097.  
  1098. ; routine to send al to the modem port
  1099.  
  1100. OUTMODEM PROC    NEAR
  1101.     push    ax
  1102.     mov    ah,al
  1103.     call    outchr            ; outchr reads from ah
  1104.      nop                ; ignore errors
  1105.      nop
  1106.      nop
  1107.     pop    ax
  1108.     ret
  1109. OUTMODEM ENDP
  1110.  
  1111. ; Convert X and Y from PC coordinates to Tek coordinates. AX = X, BX = Y
  1112. ; for both input and output.
  1113. pctotek proc    near
  1114.     mul    xdiv            ; scale from PC screen coord to Tek
  1115.     div    xmult
  1116.     xchg    bx,ax            ; save Tek x coord in bx
  1117.     neg    ax            ; y axis. Turn upside down for Tek
  1118.     add    ax,ybot
  1119.     mul    ydiv            ; scale y from PC screen coord to Tek
  1120.     div    ymult
  1121.     xchg    ax,bx            ; ax has X, bx has Y in Tek coords
  1122.     ret
  1123. pctotek endp
  1124.  
  1125. ; Routine to output character in AL to the screen.
  1126.  
  1127. OUTSCRN PROC NEAR            ; Output one character to the screen
  1128.                     ; Set Translation Input filter
  1129.     cmp    rxtable+256,0        ; translation turned off?
  1130.     je    outsct            ; e = yes, no translation
  1131.     push    bx
  1132.     mov    bx,offset rxtable    ; address of translate table
  1133.     xlatb                ; new char is in al
  1134.     and    al,7fh            ; retain only lower seven bits
  1135.     pop    bx
  1136. outsct: mov    si,ybot            ; get last scan line
  1137.     inc    si            ; number of scan lines
  1138.     sub    si,y_coord        ; minus where char bottom needs to go
  1139.     jnc    outscc            ; nc = enough space for char
  1140.                     ; else give "More >" message
  1141.     push    ax            ; save current char
  1142.     mov    ax,mormsglen        ; characters in More message
  1143.     shl    ax,1
  1144.     shl    ax,1
  1145.     shl    ax,1            ; times 8 bits/character
  1146.     neg    ax            ; (note: leave last char cell empty)
  1147.     add    ax,xmax            ; right justify
  1148.     mov    x_coord,ax        ; set starting x dot
  1149.     mov    ax,ybot
  1150.     mov    y_coord,ax        ; set starting y line
  1151.     mov    ah,gfcol        ; get screen coloring
  1152.     mov    al,gbcol
  1153.     push    ax            ; save it
  1154.     xchg    ah,al            ; interchange colors for message
  1155.     mov    gfcol,ah
  1156.     mov    gbcol,al
  1157.     mov    si,offset moremsg    ; give More message
  1158.     push    cx
  1159.     mov    cx,mormsglen
  1160. outsclf:cld
  1161.     lodsb                ; read a byte from string
  1162.     call    putc            ; display the string
  1163.     loop    outsclf            ; repeat for all string chars
  1164.     pop    cx
  1165.     pop    ax            ; restore normal video
  1166.     mov    gfcol,ah
  1167.     mov    gbcol,al
  1168.     mov    ah,coninq        ; read keyboad via DOS
  1169.     int    dos            ; wait for keystroke
  1170.     or    al,al            ; scan code being returned?
  1171.     jne    outscl3            ; ne = no
  1172.     mov    ah,coninq        ; clear away scan code too
  1173.     int    dos
  1174. outscl3:call    tekcls            ; clear the screen
  1175.     pop    ax            ; recover current character
  1176.     cmp    al,lf            ; just a line feed?
  1177.     jne    outscc            ; ne = no, display it
  1178.     ret                ;  else ignore the line feed
  1179.  
  1180. outscc: push    ax
  1181.     mov    ax,xmax
  1182.     cmp    x_coord,ax        ; beyond right margin?
  1183.     jbe    outsc3            ; be = no
  1184.     mov    al,cr            ; else simulate cr/lf
  1185.     call    putc            ; before displaying current char
  1186.     mov    al,lf
  1187.     call    putc
  1188. outsc3: pop    ax
  1189.     call    putc            ; routine to draw characters
  1190.     ret
  1191. OUTSCRN ENDP
  1192.  
  1193.  
  1194. ; TEKCLS routine to clear the screen.
  1195. ; Entry point tekcls1 clears screen without resetting current point.
  1196. TEKCLS    PROC    NEAR
  1197.     cmp    tekflg,0        ; Tek sub mode active yet?
  1198.     jne    tekcls0            ; ne = yes
  1199.     ret                ; else ignore this call
  1200. tekcls0:mov    x_coord,0        ; starting text coordinates
  1201.     mov    y_coord,8
  1202.     mov    oldx,0            ; assumed cursor starting location
  1203.     mov    oldy,maxteky        ;  top right corner (Tek coord)
  1204.     mov    scalex,0        ; clear last plotted point (PC coord)
  1205.     mov    scaley,0
  1206.     mov    lastc,0            ; last parsed x,y coordinate
  1207.     mov    visible,0        ; make lines invisible
  1208.     mov    linepat,0ffffh        ; reset line pattern to solid
  1209.     mov    ccode,1            ; reset to ordinary writing
  1210.     mov    ttstate,offset tektxt    ; do displayable text
  1211.  
  1212. tekcls1:push    ax            ; save registers
  1213.     push    cx
  1214.  
  1215. tekcls2:mov    di,0            ; point to start of screen, di=row
  1216.     call    psetup            ; setup graphics routine and es:di
  1217.     mov    cx,4000h        ; CGA, 200 lines times 80 bytes worth
  1218. tekcls3:cld                ; clear screen directly of text stuff
  1219.     mov    al,0            ; color is black
  1220.     rep    stosb            ; clear the bytes
  1221.     jmp    short tekcls7
  1222.  
  1223. tekcls6:push    es            ; clear screen by scrolling up
  1224.     call    cmblnk            ; clear screen, for Environments
  1225.     pop    es
  1226.  
  1227. tekcls7:mov    si,0            ; starting x  (in case screen is
  1228.     mov    di,0            ; starting y    cleared by user)
  1229.     pop    cx
  1230.     pop    ax
  1231.     ret
  1232. TEKCLS    ENDP
  1233.  
  1234. ; Routine to draw a line on the screen, using TEKTRONIX coordinates.
  1235. ; X coordinate in AX, 0=left edge of screen, 1023=right edge of screen.
  1236. ; Y coordinate in BX, 0=bottom of screen, 779=top of screen.
  1237. ; CL=0 - invisible move, CL=1 - draw a line, CL=0FFh - invert pixels on line
  1238.  
  1239. TEKDRAW PROC NEAR
  1240.     mov    si,scalex        ; get old x already scaled
  1241.     mov    di,scaley        ; get old y already scaled
  1242.     call    scale            ; scale new end point to PC coords
  1243.     cmp    cl,0            ; invisible drawing?
  1244.     je    moveto            ; z = just move, skip draw part
  1245.     call    LINE            ; draw the line
  1246. moveto: mov    x_coord,ax        ; update text coordinates to match
  1247.     mov    y_coord,bx        ;  last drawn point
  1248.     ret
  1249. TEKDRAW ENDP
  1250.  
  1251. ; scale TEKTRONIX coordinates to the currently defined screen coordinates
  1252. ; AX holds X axis, BX holds Y axis. Both are changed from Tektronix coord
  1253. ; to PC coordinates by this procedure.
  1254. SCALE    PROC    NEAR
  1255.     push    dx
  1256.     push    si
  1257.     mov    oldx,ax            ; save current Tek x for next draw
  1258.     mov    oldy,bx            ; save current Tek y for next draw
  1259.     mul    xmult            ; scale x-coord
  1260.     mov    si,xdiv            ; get the divisor
  1261.     shr    si,1            ; halve it
  1262.     add    ax,si            ; add in - to round to nearest integer
  1263.     adc    dx,0
  1264.     div    xdiv
  1265.     push    ax
  1266.     mov    ax,bx
  1267.     mul    ymult            ; scale y-coord
  1268.     mov    si,ydiv            ; get divisor
  1269.     shr    si,1            ; halve it
  1270.     add    ax,si            ; add in - to round to nearest integer
  1271.     adc    dx,0
  1272.     div    ydiv
  1273.     mov    bx,ybot
  1274.     sub    bx,ax            ; Put new Y in right reg
  1275.     jns    scale3            ; ns = not too far
  1276.     mov    bx,0
  1277. scale3: pop    ax            ; Put new X in right reg
  1278.     mov    scalex,ax        ; save scaled values
  1279.     mov    scaley,bx
  1280.     pop    si
  1281.     pop    dx
  1282.     ret
  1283. SCALE    ENDP
  1284.  
  1285. ; LINE    Subroutine to plot a line with endpoints in AX,BX and SI,DI.
  1286. ;    fast line drawing routine for the IBM PC
  1287. ;
  1288. ; Registers at CALL
  1289. ; -----------------
  1290. ; SI=Start X coord, all in PC coordinates
  1291. ; DI=Start Y coord
  1292. ; AX=End X coord
  1293. ; BX=End Y coord
  1294. ; CL=Color code: 1=draw foreground, 0=draw background, 0ffh=invert
  1295. ; BP= line drawing pattern (is changed here by rotation)
  1296. ; registers are all unchanged
  1297.  
  1298. LINE    PROC    NEAR
  1299.     push    ax
  1300.     push    bx
  1301.     push    cx
  1302.     push    dx
  1303.     push    si
  1304.     push    di
  1305.     push    es
  1306.     mov    bp,linepat        ; store active line pattern word in BP
  1307.     mov    ccode,cl    ; save color code in ccode for use by plot()
  1308.             ; first get coord to achieve increasing x; deltax >= 0
  1309.     sub    ax,si            ; deltax = x2 - x1
  1310.     jge    line1            ; ge = going to the right, as desired
  1311.     neg    ax            ; make deltax non-negative
  1312.     sub    si,ax            ; swap the x coordinates
  1313.     xchg    bx,di            ; swap the y coordinates too
  1314.                 ; second, compute deltay. ax = deltax, si = x1
  1315. line1:    sub    bx,di            ; deltay = y2 - y1
  1316.     call    psetup            ; setup display adapter for plotting
  1317.                     ;  and setup es:di to screen memory
  1318.   ; Choose algorithm based on |deltay| < |deltax| (use shallow) else steep.
  1319.   ; We arrange matters such that both deltas are non-negative.
  1320.     cmp    bx,0            ; deltay
  1321.     jge    line2            ; ge = non-negative
  1322.     neg    linelen
  1323.     neg    bx            ; make non-negative
  1324. line2:    cmp    bx,ax            ; |deltay| versus |deltax|
  1325.     jbe    shallow            ; be = do shallow algorithm
  1326.     jmp    steep            ; else do steep algorithm
  1327.  
  1328.     ; shallow algorithm, move along x, di=y1, bx=deltay, si=x1, ax=deltax
  1329. shallow:add    bx,bx            ; bx = 2*deltay
  1330.     mov    cx,ax            ; cx = number of steps (deltax here)
  1331.     inc    cx            ; loop dec's cx before testing
  1332.     mov    dx,bx            ; dx holds error
  1333.     sub    dx,ax            ; error = 2*deltay - deltax
  1334.     add    ax,ax            ; ax = 2*|deltax|
  1335. shal1:    call    plotptr            ; Plot(x,y)
  1336.     cmp    dx,0
  1337.     jle    shal2            ; le =     error <= 0
  1338.     call    pincy            ; increment y by one scan line
  1339.     sub    dx,ax            ; error = error - 2*deltax
  1340. shal2:    add    dx,bx            ; error = error + 2*deltay
  1341.     inc    si            ; x = next dot right
  1342.     loop    shal1
  1343. shal3:    jmp    plotex
  1344.  
  1345.     ; steep algorithm, move along y, di=y1, bx=deltay, si=x1, ax=deltax
  1346. steep:    add    ax,ax            ; ax = 2*deltax
  1347.     mov    dx,ax            ; dx holds error
  1348.     sub    dx,bx            ; error = 2*deltax(bx) - deltay (bx)
  1349.     mov    cx,bx            ; cx = number of steps (deltay here)
  1350.     inc    cx            ; loop dec's cx before testing
  1351.     add    bx,bx            ; bx = 2*|deltay|
  1352. stee1:    call    plotptr            ; Plot(x,y) x = ax, y = di
  1353.     cmp    dx,0
  1354.     jle    stee2            ; le  error <= 0
  1355.     inc    si            ; x = next dot right
  1356.     sub    dx,bx            ; error = error - 2*deltay
  1357. stee2:    add    dx,ax            ; error = error + 2*deltax
  1358.     call    pincy            ; increment y
  1359.     loop    stee1
  1360. stee3:    jmp    plotex
  1361.  
  1362. plotex: call    pfin            ; cleanup boards after plotting
  1363.     mov    ccode,1            ; reset to do foreground coloring
  1364.     pop    es
  1365.     pop    di
  1366.     pop    si
  1367.     pop    dx            ; restore the world
  1368.     pop    cx
  1369.     pop    bx
  1370.     pop    ax
  1371.     ret
  1372. LINE    ENDP
  1373.  
  1374. ;;;;;;;;;;;;;;;;;;;;;;;;;; CGA plot support routines
  1375. ; The CGA graphics memory mapping in mode 6 (640 by 200) is 8 dots per byte,
  1376. ; left most dot in the high bit, 80 bytes per scan line, scan line segments
  1377. ; alternating between 0b800h (even lines 0, 2, ...) and 0ba00h (odd lines).
  1378. psetupc proc    near            ; CGA setup for plotting
  1379.     push    ax
  1380.     push    cx
  1381.     mov    linelen,80        ; 80 bytes per scan line
  1382.     mov    cx,segscn
  1383.     mov    es,cx
  1384.     mov    cx,di            ; save copy of di, start y line
  1385.                     ; compute starting point in regen buff
  1386.     shr    di,1            ; half the lines in each bank
  1387.     mov    ax,80            ; 80 bytes per line
  1388.     mul    di
  1389.     mov    di,ax            ; di = di * 80 / 2
  1390.     test    cx,1            ; even or odd line
  1391.     jz    psetc1            ; z = even
  1392.     add    di,2000h        ; offset to odd bank (seg 0ba00h)
  1393. psetc1: and    di,3fffh
  1394.     pop    cx
  1395.     pop    ax
  1396.     ret
  1397. psetupc endp
  1398.  
  1399. pincyc    proc    near            ; CGA inc y
  1400.     cmp    linelen,0        ; increasing or decreasing y?
  1401.     jl    pinyc2            ; l = decreasing
  1402.     cmp    di,2000h        ; in upper bank now?
  1403.     jb    pinyc1            ; b = no, in lower bank
  1404.     add    di,linelen        ; add a line
  1405. pinyc1: add    di,2000h        ; switch banks
  1406.     and    di,3fffh        ; roll over address
  1407.     ret
  1408. pinyc2: cmp    di,2000h        ; in upper bank now?
  1409.     jae    pinyc4            ; ae = yes
  1410.     add    di,linelen        ; subtract a line
  1411. pinyc4: add    di,2000h        ; switch banks
  1412.     and    di,3fffh        ; roll over address
  1413.     ret
  1414. pincyc    endp
  1415.  
  1416. pfinc    proc    near            ; CGA end of plot board cleanup
  1417.     ret
  1418. pfinc    endp
  1419.  
  1420. pltcga    proc    near        ; CGA plot(x,y). x is in si, y is in di
  1421.     push    bx        ; used for HGA plot also.
  1422.     push    si
  1423.     push    di
  1424.     rol    bp,1            ; rotate line pattern
  1425.     jnc    pltcg3            ; nc = no bit to be plotted
  1426.     mov    bx,si            ; want si/8 for bytes along line
  1427.     shr    si,1
  1428.     shr    si,1
  1429.     shr    si,1
  1430.     add    di,si            ; starting point in regen buffer
  1431.     and    bx,0007h        ; leave lower 3 bits for bit in byte
  1432.                     ; di = offset in regen buffer
  1433.     mov    bh,masktab[bx]        ; 0-7 into bit mask in byte. x position
  1434.     mov    bl,ccode        ; get line type code
  1435.     cmp    bl,1            ; draw the bit?
  1436.     jne    pltcg1            ; ne = no
  1437.     or    es:[di],bh        ; drawn
  1438.     jmp    short pltcg3
  1439. pltcg1: cmp    bl,0            ; draw in background (erase)?
  1440.     jne    pltcg2            ; ne = no
  1441.     not    bh
  1442.     and    es:[di],bh        ; erase the dots
  1443.     jmp    short pltcg3
  1444. pltcg2: xor    es:[di],bh        ; xor in this color
  1445. pltcg3: pop    di
  1446.     pop    si
  1447.     pop    bx
  1448.     ret
  1449. pltcga    endp
  1450.  
  1451. ; GPUTC - a routine to send text characters from font to true graphics boards
  1452. ; such as EGA, Hercules or CGA. Char is in al.
  1453.  
  1454. gputc    proc    near
  1455.     cmp    al,' '            ; control character?
  1456.     jae    gputc1            ; ae = no, display the char
  1457.     jmp    putctrl            ; else handle controls at putctrl
  1458. gputc1: push    bx            ; first save some registers
  1459.     push    cx
  1460.     push    es
  1461.     push    di
  1462.     mov    bl,al            ; now BL has char to be displayed
  1463.     and    bl,7fh            ; no high bits allowed here
  1464.                     ; set board mode
  1465.     mov    di,y_coord        ; get current y coord (char bottom)
  1466.     sub    di,8            ; start 8 lines higher
  1467.     jnc    gputc2            ; nc = ok
  1468.     mov    di,0            ; move up to first line
  1469.     mov    y_coord,8        ; and reset scan line indicator
  1470. gputc2: call    psetup        ; enter with di=line number, sets es:di to
  1471.                 ; start of line in display buf and
  1472.                 ; sets byte-wide plot mode
  1473.     mov    ax,x_coord        ; compute regen buffer byte
  1474.     shr    ax,1            ; want x_coord/8 for bytes along line
  1475.     shr    ax,1
  1476.     shr    ax,1
  1477.     add    di,ax            ; byte in regen buffer
  1478.     xor    bh,bh
  1479.     sub    bx,32            ; characters in font start at 32
  1480.     shl    bx,1
  1481.     shl    bx,1            ; 8 bytes per char - hence * 8
  1482.     shl    bx,1
  1483.     mov    cx,8            ; 8 bytes (scan lines) to transfer
  1484.  
  1485. gputc4: mov    al,font[bx]        ; Non-EGA systems: get bits from font
  1486.     mov    es:[di],al        ; write desired pattern (no overwrite)
  1487.     inc    bx            ; point to next byte of char pattern
  1488.     call    pincy            ; inc to next line (linelen is preset)
  1489.     loop    gputc4            ; and repeat 'til complete
  1490. gputx:    call    incx            ; move to next char position
  1491.     pop    di
  1492.     pop    es
  1493.     pop    cx
  1494.     pop    bx
  1495.     ret
  1496. gputc    endp
  1497.  
  1498. putctrl proc    near            ; CONTROL CHARS = cursor movement
  1499.     cmp    al,FF            ; formfeed?
  1500.     jne    putct0            ; ne = no
  1501.     call    TEKCLS            ; FF clears the screen
  1502.     ret
  1503. putct0: cmp    al,BS            ; BS? sends (logical) cursor back one
  1504.     jne    putct2            ; ne = no, try next
  1505.     mov    ax,x_coord
  1506.     sub    ax,8            ; so delete 8 dots (move left)
  1507.     jns    putct1            ; ns = non-negative
  1508.     mov    ax,0            ; but not less than 0
  1509. putct1: mov    x_coord,ax        ; and replace x coordinate
  1510.     mov    al,' '            ; send a space
  1511.     call    putc
  1512.     sub    x_coord,8        ; restore cursor
  1513.     ret
  1514. putct2: cmp    al,tab            ; tabs move forward one char position
  1515.     jne    putct4            ; ne = not a tab
  1516.     mov    ax,x_coord
  1517.     add    ax,8            ; so add 8
  1518.     cmp    ax,xmax            ; zero if off edge of screen
  1519.     jbe    putct3
  1520.     mov    x_coord,0
  1521.     mov    al,lf
  1522.     jmp    short putct5        ; process our new line feed
  1523. putct3: mov    x_coord,ax
  1524.     ret
  1525. putct4: cmp    al,cr            ; <CR> means go to beginning of line
  1526.     jne    putct5
  1527.     mov    x_coord,0        ; zero the x coordinate
  1528.     ret
  1529. putct5: cmp    al,lf            ; <LF> means go down 8 pixels (1 line)
  1530.     jne    putct7            ; ne = not LF
  1531.     add    y_coord,8        ; border managed by outscrn and incx
  1532.     ret
  1533. putct7: cmp    al,vt            ; <VT> move up screen 1 line (8 pixels)
  1534.     jne    putctx
  1535.     sub    y_coord,8        ; - so subtract 8
  1536.     jnc    putctx            ; nc = space left
  1537.     mov    y_coord,8        ; else set to top of screen
  1538. putctx: ret
  1539. putctrl endp
  1540.  
  1541. mputc    proc    near            ; MONO put char in AL via Bios
  1542.     push    ax            ; updates x_coord,y_coord with
  1543.     push    bx            ; new cursor position
  1544.     push    cx
  1545.     push    dx
  1546.     mov    ah,0            ; marker for cursor setting not needed
  1547.     cmp    al,' '            ; control code?
  1548.     jae    mputc1            ; ae = no, printable
  1549.     call    putctrl            ; do cursor arithmetic
  1550.     mov    ah,1            ; marker to set cursor but no display
  1551.  
  1552. mputc1: push    ax            ; save char and marker
  1553.     mov    cl,3            ; char cell is 8 x 8 dots
  1554.     mov    ax,x_coord        ; get resulting cursor PC positions
  1555.     shr    ax,cl
  1556.     mov    dl,al            ; column
  1557.     mov    ax,y_coord
  1558.     sub    ax,8            ; minus 8 dots, like other modes
  1559.     jnc    mputc2            ; nc = non-negative
  1560.     mov    ax,0            ; else start at the top
  1561.     mov    y_coord,8        ; here too
  1562. mputc2: shr    ax,cl
  1563.     mov    dh,al            ; row
  1564.     mov    ah,2            ; set cursor to x_coord,y_coord
  1565.     mov    bh,0            ; page 0
  1566.     int    screen
  1567.     pop    ax
  1568.     cmp    ah,0            ; write a char in al?
  1569.     jne    mputcx            ; ne = no
  1570.     mov    ah,09h            ; write char at cursor postion
  1571.     mov    cx,1            ; just one char
  1572.     mov    bh,0            ; page 0
  1573.     mov    bl,gfcol        ; foreground coloring
  1574.     int    screen
  1575.     inc    dl            ; next column
  1576.     mov    ah,2            ; set real cursor ahead of last char
  1577.     int    screen
  1578.     call    incx            ; move logical cursor
  1579. mputcx: pop    dx
  1580.     pop    cx
  1581.     pop    bx
  1582.     pop    ax
  1583.     ret
  1584. mputc    endp
  1585.  
  1586. incx    proc    near            ; move the logical cursor right
  1587.     mov    ax,x_coord        ; shift the (logical) cursor right
  1588.     add    ax,8            ;  one character cell
  1589.     mov    x_coord,ax
  1590.     cmp    ax,xmax            ; at end of the line?
  1591.     jbe    incx1            ; b = no
  1592.     mov    x_coord,0        ; wrap to next line
  1593.     add    y_coord,8        ; next row
  1594.     mov    ax,ybot            ; last scan line
  1595.     cmp    ax,y_coord        ; below bottom line?
  1596.     jge    incx1            ; ge = no
  1597.     mov    y_coord,ax        ; set to bottom row
  1598.     mov    al,lf            ; simulate a line feed operation
  1599.     call    outscrn            ; invoke More message
  1600. incx1:    ret
  1601. incx    endp
  1602.  
  1603.  
  1604. teksave proc    near        ; saves graphics screen from page 0 to page 1
  1605.     push    si
  1606.     push    di
  1607.     cmp    gpage,0        ; only graphics page 0 on display board?
  1608.     je    teksavx        ; e = yes, no saving possible here
  1609.     mov    si,segscn    ; segment (!) of current screen
  1610. teksavx:pop    di
  1611.     pop    si
  1612.     ret
  1613. teksave endp
  1614.  
  1615. tekrest proc    near        ; saves graphics screen of page 0 in page 1
  1616.     push    si
  1617.     push    di
  1618.     cmp    gpage,0        ; only graphics page 0 on display board?
  1619.     jne    tekres0        ; ne = no, more so work to do here
  1620.     call    tekcls1        ;  else clear the screen to color it
  1621.     jmp    short tekresx    ;  and exit
  1622. tekres0:mov    di,segscn    ; segment (!) of new graphics screen
  1623. tekresx:pop    di
  1624.     pop    si
  1625.     ret
  1626. tekrest endp
  1627.  
  1628. code    ends
  1629.     end
  1630.