home *** CD-ROM | disk | FTP | other *** search
/ Phoenix CD 2.0 / Phoenix_CD.cdr / 01e / msk230s1.zip / MSGIBM.ASM next >
Assembly Source File  |  1988-02-12  |  110KB  |  2,240 lines

  1.         Name msgibm
  2. ; File MSGIBM.ASM
  3. ; Tektronix emulator for use with MS Kermit/IBM.
  4. ; Edit history:
  5. ; Last edit 1 Jan 1988
  6. ; 1 Jan 1988 version 2.30
  7. ; 31 Dec 1987 change name from msvibm to msgibm for final release. [jrd]
  8. ; 29 Dec 1987 Add ESC [ ? 3 8 l  as exit Tek mode command, from VT340's.[jrd]
  9. ; 26 Dec 1987 Add test to absorb echo of crosshairs report. [jrd]
  10. ; 22 Dec 1987 Revise parsing rules to make an escape sequence be a temporary
  11. ;  interruption to the current command (except Clear Screen seq). [jrd]
  12. ; Add Control-C and Control-Break as non-reporting exits from GIN mode. [jrd]
  13. ; 21 Dec 1987 Add AT&T 6300, Olivetti M24 presence tests and run code. [jrd]
  14. ; 16 Dec 1987 Correct screen coloring for 64KB mono/med res color egas. [jrd]
  15. ; 4 Dec 1987 Add quirks for Environments, such as TopView, Windows. [jrd]
  16. ; 3 Dec 1987 Let 128KB EGA boards save screens. [jrd]
  17. ; 30 Nov 1987 Add relative plotting, thanks to help from Bob Parks. [jrd]
  18. ; 24 Nov 1987 Add dashed line patterns. [jrd]
  19. ; 21 Nov 1987 Add full color background. [jrd]
  20. ; 15 Nov 1987 Do screen clears manually because a Bios mode-set keeps
  21. ;  interrupts off long enough to miss serial port characters. Make crosshairs
  22. ;  smaller. [jrd]
  23. ; 8 Nov 1987 Modularize line drawing using Bresneham's algorithm, use pointers
  24. ;  to action routines for different board types. Add screen save/restore.
  25. ;  Do display board presence tests. Add FS as point plot introducer. Allow
  26. ;  for virtual screens when operating under Environments (Windows, etc). [jrd]
  27. ; 1 Nov 1987 Heavy rewrite to integrate code into regular MS Kermit/IBM
  28. ;  material. [jrd]
  29. ;==============================================================================
  30. ; Original version for TI Pro computers by
  31. ; 12-Dec-84  Joe Smith, CSM Computing Center, Golden CO 80401
  32. ; Converted to IBM PCs by Brian Holley, Cambridge Univ.
  33. ; Upgraded and integrated into MS Kermit 2.30 by Joe Doupnik, Utah State Univ.
  34. ;
  35. ;                  Description of Tektronix commands
  36. ;
  37. ; ESCAPE-CONTROL-E (ENQ) requests a status report
  38. ; ESCAPE-FORMFEED erases the screen.
  39. ; ESCAPE-CONTROL-Z turns on the crosshairs (not on 4006 or 4025)
  40. ; ESCAPE [ ? 3 8 l  exits Tek mode and returns to host text terminal type
  41. ;  (VT102 if none defined yet). This is an extension from DEC VT340's.
  42. ; CONTROL-] (GS) turns on plot mode, the first move will be with beam off.
  43. ; CONTROL-^ (RS) turns on incremental plot mode. RS space means move pen up
  44. ;  RS P means move pen down, following letters:A, E, D, F, B, J, H, I mean
  45. ;  move right, right and up, up, left and up, left, left and down, down, and
  46. ;  right and down, respectively. Ex: RS <space> J J J  means move three Tek
  47. ;  positions left and down with the pen up (invisibly).
  48. ; CONTROL-UNDERLINE (US) turns off plot mode, as does CR (for all but 4025).
  49. ; CONTROL-X switches from TEKTRONIX sub mode to NORMAL alpha mode but is
  50. ;  ignored if we are emulating a full Tek terminal rather than a sub mode
  51. ;  of DEC or Heath.
  52. ; FF erases screen.
  53. ; ESCAPE letter, where letter is accent grave (`), a-e sets the line drawing
  54. ;   pattern until reset to solid lines (same as escape accent) by command or
  55. ;   a terminal reset.
  56. ; where
  57. ;       ENQ = Control E
  58. ;       ESC = Control [ (left square bracket)
  59. ;       FF = Control L
  60. ;       FS = Control \ (backslash)
  61. ;       GS = Control ] (right square bracket)
  62. ;       RS = Control ^ (caret)
  63. ;       US = Control _ (underscore)
  64. ;
  65. ; The plot commands are characters which specify the absolute position to move
  66. ; the beam.  All moves except the one immediately after the GS character
  67. ; (Control-]) are with a visible trace.
  68. ;
  69. ; For 4010-like devices - The positions are from 0 to 1023 for both X and Y,
  70. ; although only 0 to 780 are visible for Y due to screen geometry.  The screen
  71. ; is 10.23 by 7.80 inches, and coordinates are sent as 1 to 4 characters.
  72. ;
  73. ; For 4014-like devices - The positions are from 0 to 4096, but each movement
  74. ; is a multiple of 4 positions unless the high-resolution LSBXY are sent.  This
  75. ; makes it compatible with the 4010 in that a full sized plot fills the screen.
  76. ;
  77. ; HIX,HIY = High-order 5 bits of position
  78. ; LOX,LOY = Middle-order 5 bits of position
  79. ; LSBXY   = Low-order 2 bits of X + low-order 2 bits of Y (4014 mode)
  80. ;
  81. ; Hi Y    Lo Y    Hi X    LSBXY   Characters sent (Lo-X always sent)
  82. ; ----    ----    ----    -----   ----------------------------------
  83. ; Same    Same    Same    Same                           Lo-X
  84. ; Same    Same    Same    Diff          LSB, Lo-Y,       Lo-X   4014
  85. ; Same    Same    Diff    Same               Lo-Y, Hi-X, Lo-X
  86. ; Same    Same    Diff    Diff          LSB, Lo-Y, Hi-X, Lo-X   4014
  87. ; Same    Diff    Same    Same               Lo-Y,       Lo-X
  88. ; Same    Diff    Same    Diff          LSB, Lo-Y,       Lo-X   4014
  89. ; Same    Diff    Diff    Same               Lo-Y, Hi-X, Lo-X
  90. ; Same    Diff    Diff    Diff          LSB, Lo-Y, Hi-X, Lo-X   4014
  91. ; Diff    Same    Same    Same    Hi-Y,                  Lo-X
  92. ; Diff    Same    Same    Diff    Hi-Y, LSB, Lo-Y,       Lo-X   4014
  93. ; Diff    Same    Diff    Same    Hi-Y,      Lo-Y, Hi-X, Lo-X
  94. ; Diff    Same    Diff    Diff    Hi-Y, LSB, Lo-Y, Hi-X, Lo-X   4014
  95. ; Diff    Diff    Same    Same    Hi-Y,      Lo-Y,       Lo-X
  96. ; Diff    Diff    Same    Diff    Hi-Y, LSB, Lo-Y,       Lo-X   4014
  97. ; Diff    Diff    Diff    Same    Hi-y,      Lo-Y, Hi-X, Lo-X
  98. ; Diff    Diff    Diff    Diff    Hi-y, LSB, Lo-Y, Hi-X, Lo-X   4014
  99. ; Offset for byte:                20h   60h  60h   20h   40h
  100. ;
  101. ; Note that LO-Y must be sent if HI-X has changed so that the TEKTRONIX knows
  102. ; the HI-X byte (in the range of 20h-3fh) is HI-X and not HI-Y.  LO-Y must
  103. ; also be sent if LSBXY has changed, so that the 4010 will ignore LSBXY and
  104. ; accept LO-Y.  The LSBXY byte is 60h + MARGIN*10h + LSBY*4 + LSBX. (MARGIN=0)
  105. ;
  106. ;==============================================================================
  107. ;
  108. ; External variable tekflg and calls to tekini, tekemu, tekesc, tekcls:
  109. ; Byte TEKFLG is non-zero when the Tek emulator is active; it is set by the
  110. ; startup code in tekini and is maintained in this file. Internal variable
  111. ; inited remembers if we have a graphics screen saved, etc.
  112. ; TEKINI must be called when entering the emulator to establish the graphics
  113. ; screen mode and to calculate the screen dimensions.
  114. ; TEKESC is called from say mszibm.asm to invoke Tek emulation when the
  115. ; external procedures have detected an Escape Control-L sequence. An implicit
  116. ; initialization is done if necessary.
  117. ; TEKEMU is the normal entry point to pass a received character to the emulator.
  118. ; It too will do an implicit initialization, if required.
  119. ; TEKCLS clears the graphics screen, but only if the emulator is active.
  120. ; The emulator remains active during Connect mode Help, Status, and other
  121. ; interrupts which do not change the terminal type.
  122. ; =============================================================================
  123. ;
  124. ; - ctrl-g (BEL) from line gives beep in tek mode
  125. ; - characters better placed in relation to current beam position
  126. ;       in EGA and Hercules modes
  127. ;   characters OR-ed into place rather than overwriting
  128. ; - add SET TERMINAL GRAPHICS NONE -    this ignores the start-up ESC-FF
  129. ;                                       for Tektronix
  130. ; - add MonoEGA mode for monochrome graphics on an EGA
  131. ;
  132. ; version 2.29/t3
  133. ;  changes - stop control characters from echoing to screen in TEKEMU
  134. ;          - show version on name in MSSDEF.H
  135. ; version 2.29b
  136. ; changes with this version:  - faster line drawing, using direct write to
  137. ;                               memory rather than BIOS calls
  138. ;                             - support for Hercules, Olivetti, EGA
  139. ;                             - minor bug fixes
  140.  
  141. ; adapted to IBM PC June 1987 by        Brian Holley,
  142. ;                                       Faculty of Economics and Politics
  143. ;                                       University of Cambridge, England
  144. ;                                       Email: BJH6@UK.AC.CAM.PHX
  145.  
  146.         public  tekemu,tekini,tekend    ; Terminal emulation routines
  147.         public  tekcls, tekesc, tekflg  ; used by msz file
  148.  
  149.         include mssdef.h
  150.  
  151. ENQ     equ     05h                     ; ^E ENQ for TEK enquiries
  152. CAN     equ     18h                     ; ^X to return to ANSI mode
  153. ESCZ    equ     1Ah                     ; SUB, ESC-^Z triggers crosshairs
  154. VT      equ     0bh                     ; ^K go up one line
  155. FS      equ     1ch                     ; ^\ for point plot mode
  156. GS      equ     1Dh                     ; ^] draw line (1st move is invisible)
  157. RS      equ     1Eh                     ; ^^ for incremental line plot mode
  158. US      equ     1Fh                     ; ^_ (underscore) returns to text mode
  159. accent  equ     60h                     ; accent grave
  160.  
  161. txtmode equ     4                       ; text mode for TEKTRONIX status
  162. maxtekx equ     1024                    ; horizontal and
  163. maxteky equ     780                     ; vertical resolution of TEK 4010
  164.  
  165. screen  equ     10h                     ; bios screen call
  166.  
  167. uparr   equ     72                      ; DOS scan codes for arrow keys
  168. dnarr   equ     80
  169. lftarr  equ     75
  170. rgtarr  equ     77
  171. homscn  equ     71                      ; DOS home screen scan code
  172. shuparr equ     '8'                     ; ascii codes for shifted arrows
  173. shdnarr equ     '2'
  174. shlftarr equ    '4'
  175. shrgtarr equ    '6'
  176.  
  177.                                         ; Graph_mode for different systems:
  178. cga     equ     6                       ; highest resolution mode for CGA
  179. mono    equ     7                       ; real monochrome display adapter
  180. colorega equ    14                      ; Low-res mode, color EGA
  181. monoega equ     15                      ; mono ega needs mode 15
  182. ega     equ     16                      ; Hi-res mode - EGA
  183. olivetti equ    72                      ; Olivetti's Hi-res - 50 lines text
  184. hercules equ    255                     ; pseudo mode for Hercules graphics
  185. ; Note: IBM VGA mode 18, 640 by 480, can be used by setting "ega" above
  186. ; to 18 and modify ybot to be 479 and ymult to be 48 at label tekin5.
  187. ; The code will scale everything appropriately for the new screen size, but
  188. ; there will be insufficient memory to retain the entire graphics image.
  189. ; Do this at your own risk, please, until PS/2 Tech Refs are available. [jrd]
  190.  
  191. segega  equ     0a000h                  ; segments of display memory, EGA
  192. segcga  equ     0b800h                  ; CGA, AT&T/Olivetti
  193. seghga  equ     0b000h                  ; HGA
  194. segmono equ     0b000h                  ; Monochrome
  195.  
  196.                                         ; Hercules equates:
  197. index   equ     03b4h                   ; 6845 index register
  198. cntrl   equ     03b8h                   ; Display mode control port
  199. hstatus equ     03bah                   ; status port
  200. scrn_on equ     8                       ; bit to turn screen on
  201. grph    equ     2                       ; graphics mode
  202. text    equ     20h                     ; text mode
  203. config  equ     03bfh                   ; configuration port
  204. genable equ     1                       ; enable graphics, page 0 only
  205.  
  206. hiy     equ     1                       ; codes for Tek graphics components
  207. loy     equ     2
  208. hix     equ     4
  209. lox     equ     3
  210.  
  211. datas   segment public 'datas'
  212.         extrn   flags:byte, portval:word, rxtable:byte, vtemu:byte
  213.         extrn   tv_mode:byte
  214.  
  215. xmult   dw      ?                       ; scaling factor for x is
  216. xdiv    dw      ?                       ;     xmult/xdiv
  217. ymult   dw      ?                       ; scaling factor for y is
  218. ydiv    dw      ?                       ;     ymult/ydiv
  219. xmax    dw      ?                       ;
  220. ybot    dw      ?                       ;
  221.  
  222. ; required for Hercules screen handling
  223.  
  224. gtable  db      35h,2dh,2eh,07h         ; bytes for 6845 controller
  225.         db      5bh,02h,57h,57h         ; - graphics mode
  226.         db      02h,03h,0,0
  227.  
  228. ttable  db      61h,50h,52h,0fh         ; bytes for 6845 controller
  229.         db      19h,06h,19h,19h         ; - text mode
  230.         db      02h,0dh,0bh,0ch
  231.  
  232. attlogo db      'OLIVETTI'              ; Olivetti M24, AT&T 6300 rom id
  233. attlen  equ     $-attlogo               ; length
  234.  
  235. ttstate dw      tektxt                  ; state machine control pointer
  236. prestate dw     0                       ; previous state, across interruptions
  237. visible db      0                       ; 0 to move, 1 to draw a line
  238. tek_hiy dw      0                       ; Y coordinate in Tektronix mode
  239. tek_loy db      0
  240. tek_hix dw      0                       ; X coordinate in Tektronix mode
  241. tek_lox db      0
  242. tek_lsb db      0                       ; Low-order 2 bits of X + low Y
  243.                                         ;       (4014 mode)
  244. status  db      0
  245. lastc   db      0                       ; last x/y coord fragment seen
  246. masktab db      80h,40h,20h,10h,8,4,2,1 ; quicker than calculations!
  247.                                         ; dashed line patterns
  248. linetab dw      0ffffh                  ; ESC accent    11111111 11111111
  249.         dw      0aaaah                  ; ESC a         10101010 10101010
  250.         dw      0f0f0h                  ; ESC b         11110000 11110000
  251.         dw      0fafah                  ; ESC c         11111010 11111010
  252.         dw      0ffcch                  ; ESC d         11111111 11001100
  253.         dw      0fc92h                  ; ESC e         11111100 10010010
  254.  
  255. linepat dw      0ffffh                  ; active line pattern, from above
  256.  
  257. ;End of init data
  258. IDSEQ   dw      tekem                   ; address of response to terminal
  259. CTLTAB  dw      0                       ; .. inquiry
  260. tekem   db      'IBM_TEK'               ; .. and the response
  261.         db      escape,'/Z',0
  262. x_coord dw      0                       ; Tek text char X coordinate
  263. y_coord dw      8                       ; Tek text char Y coordinate
  264. xcross  dw      0                       ; cross hairs to start at centre
  265. ycross  dw      0
  266. oldx    dw      0                       ; Tek coordinates of last point
  267. oldy    dw      767                     ;  initially top left
  268. scalex  dw      0                       ; PC coord for scaled x value
  269. scaley  dw      0                       ;  for scaled y value
  270. curmode db      0                       ; screen mode before graphics
  271.                                 ; local variables for LINE plotting routine
  272. graph_mode db   0                       ; graphics video mode, default is none
  273. cursor  dw      0                       ; saved text cursor
  274. inited  db      0                       ; non-zero if inited (retains page)
  275. tekflg  db      0                       ; Tek mode active flag
  276. yflags  db      0                       ; flags byte from msy
  277. flow    dw      0                       ; flow control word
  278. gpage   db      0                       ; display adapter graphics page
  279. gfcol   db      15                      ; graphics foreground colour
  280. gbcol   db      0                       ; graphics background color
  281. moremsg db      ' More >'
  282. mormsglen equ   $-moremsg               ; length of message
  283. ccode   db      0                       ; temp for holding plot color code
  284. linelen dw      0                       ; offset increment between scan lines
  285. putc    dw      mputc                   ; ptr to plot a character routine
  286. psetup  dw      psetupm                 ; ptr to plot setup routine
  287. pfin    dw      pfinm                   ; ptr to plot cleanup routine
  288. pincy   dw      pincym                  ; ptr to inc y routine
  289. plotptr dw      pltmon                  ; ptr to dot plot routine
  290. segscn  dw      0b800h                  ; actual screen segment to use
  291. ; ANSI Escape sequence to turn off Media Copy (Print Controller Off)
  292. tkoff   db      escape,'[?38l'          ; Exit Tek mode escape sequence
  293. tkofflen equ    $-tkoff                 ; length of sequence
  294. tkoffs  db      6 dup (0)               ; received chars in rcv'd sequence
  295. tkcnt   dw      0                       ; counter of matched char in tkoffs
  296. repbuf  db      6 dup (0)               ; crosshairs report buf
  297. repcnt  db      0                       ; number of untouched chars in repbuf
  298. temp    dw      0
  299.  
  300. ; 8*8 font for Hercules, CGA, and EGA TEK mode
  301. ; - allows 43 lines, and 80 (90 for Hercules) chars per line.
  302. ; all printing (?) characters from <space> to <del> - two characters per line
  303. ; 8 bits per scan line, given top line first, 8 scan lines.
  304. font    db      0,0,0,0,0,0,0,0,               18h,18h,18h,18h,18h,0,18h,0
  305.         db      6ch,6ch,6ch,0,0,0,0,0,         36h,36h,7fh,36h,7fh,36h,36h,0
  306.         db      0ch,3fh,68h,3eh,0bh,7eh,18h,0, 60h,66h,0ch,18h,30h,66h,06h,0
  307.         db      38h,6ch,6ch,38h,6dh,66h,3bh,0, 0ch,18h,30h,0,0,0,0,0
  308.         db      0ch,18h,30h,30h,30h,18h,0ch,0, 30h,18h,0ch,0ch,0ch,18h,30h,0
  309.         db      0,18h,7eh,3ch,7eh,18h,0,0,     0,18h,18h,7eh,18h,18h,0,0
  310.         db      0,0,0,0,0,18h,18h,30h,         0,0,0,7eh,0,0,0,0
  311.         db      0,0,0,0,0,18h,18h,0,           0,06h,0ch,18h,30h,60h,0,0
  312.         db      3ch,66h,6eh,7eh,76h,66h,3ch,0, 18h,38h,18h,18h,18h,18h,7eh,0
  313.         db      3ch,66h,06h,0ch,18h,30h,7eh,0, 3ch,66h,06h,1ch,06h,66h,3ch,0
  314.         db      0ch,1ch,3ch,6ch,7eh,0ch,0ch,0, 7eh,60h,7ch,06h,06h,66h,3ch,0
  315.         db      1ch,30h,60h,7ch,66h,66h,3ch,0, 7eh,06h,0ch,18h,30h,30h,30h,0
  316.         db      3ch,66h,66h,3ch,66h,66h,3ch,0, 3ch,66h,66h,3eh,06h,0ch,38h,0
  317.         db      0,0,18h,18h,0,18h,18h,0,       0,0,18h,18h,0,18h,18h,30h
  318.         db      0ch,18h,30h,60h,30h,18h,0ch,   0,0,0,7eh,0,7eh,0,0,0
  319.         db      30h,18h,0ch,06h,0ch,18h,30h,   0,3ch,66h,0ch,18h,18h,0,18h,0
  320.         db      3ch,66h,6eh,6ah,6eh,60h,3ch,   0,3ch,66h,66h,7eh,66h,66h,66h,0
  321.         db      7ch,66h,66h,7ch,66h,66h,7ch,   0,3ch,66h,60h,60h,60h,66h,3ch,0
  322.         db      78h,6ch,66h,66h,66h,6ch,78h,   0,7eh,60h,60h,7ch,60h,60h,7eh,0
  323.         db      7eh,60h,60h,7ch,60h,60h,60h,   0,3ch,66h,60h,6eh,66h,66h,3ch,0
  324.         db      66h,66h,66h,7eh,66h,66h,66h,   0,7eh,18h,18h,18h,18h,18h,7eh,0
  325.         db      3eh,0ch,0ch,0ch,0ch,6ch,38h,   0,66h,6ch,78h,70h,78h,6ch,66h,0
  326.         db      60h,60h,60h,60h,60h,60h,7eh,   0,63h,77h,7fh,6bh,6bh,63h,63h,0
  327.         db      66h,66h,76h,7eh,6eh,66h,66h,   0,3ch,66h,66h,66h,66h,66h,3ch,0
  328.         db      7ch,66h,66h,7ch,60h,60h,60h,   0,3ch,66h,66h,66h,6ah,6ch,36h,0
  329.         db      7ch,66h,66h,7ch,6ch,66h,66h,   0,3ch,66h,60h,3ch,06h,66h,3ch,0
  330.         db      7eh,18h,18h,18h,18h,18h,18h,   0,66h,66h,66h,66h,66h,66h,3ch,0
  331.         db      66h,66h,66h,66h,66h,3ch,18h,   0,63h,63h,6bh,6bh,7fh,77h,63h,0
  332.         db      66h,66h,3ch,18h,3ch,66h,66h,   0,66h,66h,66h,3ch,18h,18h,18h,0
  333.         db      7eh,06h,0ch,18h,30h,60h,7eh,   0,7ch,60h,60h,60h,60h,60h,7ch,0
  334.         db      0,60h,30h,18h,0ch,06h,0,0,     3eh,06h,06h,06h,06h,06h,3eh,0
  335.         db      18h,3ch,66h,42h,0,0,0,0,       0,0,0,0,0,0,0,0ffh
  336.         db      30h,18h,0ch,0,0,0,0,0,         0,0,3ch,06h,3eh,66h,3eh,0
  337.         db      60h,60h,7ch,66h,66h,66h,7ch,0, 0,0,3ch,66h,60h,66h,3ch,0
  338.         db      06h,06h,3eh,66h,66h,66h,3eh,0, 0,0,3ch,66h,7eh,60h,3ch,0
  339.         db      0eh,18h,18h,3ch,18h,18h,18h,0, 0,0,3eh,66h,66h,3eh,06h,3ch
  340.         db      60h,60h,7ch,66h,66h,66h,66h,0, 18h,0,38h,18h,18h,18h,3ch,0
  341.         db      18h,0,38h,18h,18h,18h,18h,70h, 60h,60h,66h,6ch,78h,6ch,66h,0
  342.         db      38h,18h,18h,18h,18h,18h,3ch,0, 0,0,76h,7fh,6bh,6bh,63h,0
  343.         db      0,0,7ch,66h,66h,66h,66h,0,     0,0,3ch,66h,66h,66h,3ch,0
  344.         db      0,0,7ch,66h,66h,7ch,60h,60h,0, 0,3eh,66h,66h,3eh,06h,07h
  345.         db      0,0,6ch,76h,60h,60h,60h,0,     0,0,3eh,60h,3ch,06h,7ch,0
  346.         db      30h,30h,7ch,30h,30h,30h,1ch,0, 0,0,66h,66h,66h,66h,3eh,0
  347.         db      0,0,66h,66h,66h,3ch,18h,0,     0,0,63h,6bh,6bh,7fh,36h,0
  348.         db      0,0,66h,3ch,18h,3ch,66h,0,     0,0,66h,66h,66h,3eh,06h,3ch
  349.         db      0,0,7eh,0ch,18h,30h,7eh,0,     0ch,18h,18h,70h,18h,18h,0ch,0
  350.         db      18h,18h,18h,0,18h,18h,18h,0,   30h,18h,18h,0eh,18h,18h,30h,0
  351.         db      31h,6bh,46h,0,0,0,0,0,         8 dup (0ffh)
  352. datas   ends
  353.  
  354. code    segment public 'code'
  355.         extrn   outchr:near, beep:near, scrseg:near, cmblnk:near
  356.         extrn   clrmod:near, savescr:near, cptchr:near, pcwait:near
  357.         extrn   restscr:near, getflgs:near, clrbuf:near, vtans52:near
  358.  
  359.         assume  cs:code, ds:datas, es:nothing
  360.  
  361. ; Initialise TEK mode by setting high resolution screen, etc
  362.  
  363. ;The IBM PC CGA card has (639,199) as the coordinate of the lower-right corner.
  364. ;Calculate endpoint X=(5/8)*(HIX*32+LOX), Y=199-(10/39)*(HIY*32+LOY)
  365.  
  366. ;The Olivetti has (639,399) as the coordinate of the lower-right corner.
  367. ;Calculate endpoint X=(5/8)*(HIX*32+LOX), Y=399-(20/39)*(HIY*32+LOY)
  368.  
  369. ;The Hercules card has (719,347) as the coordinate of the lower-right corner.
  370. ;Calculate endpoint X=(45/64)*(HIX*32+LOX), Y=347-(29/65)*(HIY*32+LOY)
  371.  
  372. ; The EGA card has (639,349) as the coordinates of the lower-right corner
  373. ;Calculate endpoint X=(45/64)*(HIX*32+LOX), Y=349-(35/78)*(HIY*32+LOY)
  374.  
  375. tekini  PROC NEAR
  376.         push    ax                      ; do presence tests. [jrd]
  377.         push    bx
  378.         push    cx
  379.         push    dx
  380.         push    si
  381.         push    di
  382.         push    es
  383.         mov     bx,portval              ; get port flow control chars:
  384.         mov     bx,[bx].flowc           ; bh=xon, bl=xoff or both are nulls
  385.         mov     flow,bx                 ; save here
  386.         mov     ax,bx                   ; get flow control word
  387.         cmp     al,0                    ; able to do xoff?
  388.         je      tekin0                  ; e = no
  389.         call    outmodem                ; tell host xoff while we change modes
  390. tekin0: mov     bx,vtemu.att_ptr        ; emulator screen color ptr
  391.         mov     al,[bx]
  392.         mov     gfcol,al                ; save foreground color
  393.         and     gfcol,0fh               ; save just foreground bits
  394.         and     al,70h                  ; select background color, no bold
  395.         mov     cl,4
  396.         shr     al,cl                   ; get background colors
  397.         mov     gbcol,al                ; set graphics background color
  398.  
  399.         mov     ah,15                   ; get current screen mode
  400.         int     screen
  401.         cmp     al,3                    ; in a mono/color text mode (2/3)?
  402.         jbe     tekin1                  ; be = yes
  403.         cmp     al,mono                 ; mono text mode (7)?
  404.         je      tekin1                  ; e = yes
  405.         cmp     tekflg,0                ; are we active as Tek device now?
  406.         je      tekin1                  ; e = no
  407.         jmp     tekin13                 ; yes, don't redo graphics setup
  408. tekin1: mov     curmode,al              ; save mode here
  409.         mov     ah,3                    ; get cursor position
  410.         xor     bh,bh                   ; page 0
  411.         int     screen
  412.         mov     cursor,dx               ; save position
  413.         call    savescr                 ; save text screen
  414.                                         ; Presence tests.
  415. tekin2: mov     graph_mode,cga          ; Color. Assume CGA
  416.         mov     segscn,segcga           ; assume cga screen segment
  417.         mov     gpage,0                 ; graphics page 0 but no page 1
  418.         mov     putc,offset gputc       ; CGA character display routine
  419.         mov     psetup,offset psetupc   ; CGA plot setup routine
  420.         mov     plotptr,offset pltcga   ; CGA dot plot routine
  421.         mov     pfin,offset pfinc       ; CGA cleanup routine
  422.         mov     pincy,offset pincyc     ; CGA inc y routine
  423.         mov     xmult,5                 ; CGA. Scale TEK to PC by 640/1024
  424.         mov     xdiv,8                  ;  so that 0-1023 converts to 0-639
  425.         mov     xmax,640-8              ; x-coord of rightmost character
  426.         mov     ymult,10                ; vertical scale for IBM is 200/780
  427.         mov     ydiv,39                 ;
  428.         mov     ybot,199                ; Bottom of screen is Y=199
  429.                                         ; test for EGA
  430.         mov     ax,1200H                ; EGA: Bios alternate select
  431.         mov     bl,10H                  ; Ask for EGA info
  432.         mov     bh,0ffH                 ; Bad info, for testing
  433.         mov     cl,0fH                  ; Reserved switch settings
  434.         int     screen                  ; EGA, are you there?
  435.         and     cl,0fh                  ; four lower switches
  436.         cmp     cl,0cH                  ; Test reserved switch settings
  437.         jb      tekin3                  ; b = ega present
  438.         jmp     tekin7                  ; else no EGA, check other adapters
  439.  
  440. tekin3: mov     ax,40h                  ; check Bios 40:87h for ega being
  441.         mov     es,ax                   ;  the active display adapter
  442.         test    byte ptr es:[87h],8     ; is ega active?
  443.         jz      tekin3a                 ; z = yes
  444.         jmp     tekin7                  ; ega is inactive, check others
  445. tekin3a:cmp     bl,1                    ; is there 128KB on ega board?
  446.         jb      tekin4                  ; b = less, so no screen saves
  447.         mov     gpage,1                 ; >=128 KB, use two graphics pages
  448. tekin4: mov     graph_mode,ega          ; assume high resolution color
  449.         cmp     cl,3                    ; high resolution color?
  450.         je      tekin5                  ; e = yes
  451.         cmp     cl,9                    ; high resolution color?
  452.         je      tekin5                  ; e = yes
  453.         mov     graph_mode,monoega      ; assume mono monitor on ega board
  454.         test    bh,1                    ; ega mono mode in effect?
  455.         jnz     tekin5                  ; nz = yes
  456.         mov     graph_mode,colorega     ; say ordinary cga on ega board, 64KB
  457.         mov     gpage,1                 ; is enough memory with 200 scan lines
  458.         jmp     short tekin5a           ; use current cga parameters
  459. tekin5: mov     ybot,349                ; text screen bottom is 349 on EGA
  460.         mov     ymult,35                ;
  461.         mov     ydiv,78                 ; scale y by 350/780
  462. tekin5a:mov     segscn,segega           ; use ega screen segment
  463.         mov     psetup,offset psetupe   ; plot setup routine
  464.         mov     plotptr,offset pltega   ; ega dot plot routine
  465.         mov     pfin,offset pfine       ; cleanup routine
  466.         mov     pincy,offset pincye     ; inc y routine
  467.         mov     putc,offset gputc       ; character display routine
  468.         mov     ah,gfcol
  469.         mov     al,gbcol
  470.         cmp     graph_mode,monoega      ; monochrome display?
  471.         jne     tekin5d                 ; ne = no
  472.         test    al,7                    ; bright backgound?
  473.         jnz     tekin5b                 ; nz = yes
  474.         mov     ah,1                    ; normal foreground
  475.         test    gfcol,8                 ; intensity on?
  476.         jz      tekin5b                 ; z = no
  477.         mov     ah,5                    ; say bright foreground
  478. tekin5b:test    al,7                    ; black backgound?
  479.         jz      tekin5c                 ; z = yes
  480.         mov     al,1                    ; regular video
  481. tekin5c:cmp     ah,al                   ; same color in both?
  482.         jne     tekin5d                 ; ne = no
  483.         mov     ah,1                    ; make foreground regular
  484.         mov     al,0                    ;  and background black
  485. tekin5d:mov     gfcol,ah
  486.         mov     gbcol,al
  487.         cmp     gpage,0                 ; minimal memory (64KB mono and ega)?
  488.         ja      tekin5e                 ; a = no, enough, else strange mapping
  489.         mov     al,gfcol                ; fix coloring to map planes C0 to C1
  490.         and     al,5                    ; and C2 to C3 (as 0, 3, 0Ch, or 0Fh)
  491.         mov     ah,al                   ; make a copy
  492.         shl     ah,1                    ; duplicate planes C0, C2 in C1, C3
  493.         or      al,ah                   ; merge the bits
  494.         mov     gfcol,al                ; store proper foreground color
  495.         mov     al,gbcol                ; repeat for background color
  496.         and     al,5
  497.         mov     ah,al
  498.         shl     ah,1
  499.         or      al,ah
  500.         mov     gbcol,al
  501. tekin5e:jmp     tekin13                 ; end of ega tests.
  502.  
  503. tekin7: mov     ax,0fc00h               ; Olivetti/AT&T 6300, check rom id
  504.         mov     es,ax                   ; look in 0fc00:050h for logo
  505.         mov     di,50h                  ; 'OLIVETTI' logo should be here
  506.         mov     si,offset ATTLOGO       ; master string
  507.         mov     cx,attlen               ; length of it
  508.         cld
  509.         repe    cmpsb                   ; do a match
  510.         jne     tekin7a                 ; ne = mismatch, check other adapters
  511.         mov     graph_mode,olivetti     ; Olivetti
  512.         mov     gpage,0                 ; only page 0 with 640 by 400 mode
  513.         mov     segscn,segcga           ; use cga screen segment (0b800h)
  514.         mov     psetup,offset psetupo   ; plot setup routine for Olivetti
  515.         mov     plotptr,offset pltcga   ; cga dot plot routine
  516.         mov     pfin,offset pfinc       ; cleanup routine
  517.         mov     pincy,offset pincyh     ; inc y routine (Herc style addresses)
  518.         mov     putc,offset gputc       ; character display routine
  519.         mov     ybot,399                ; bottom of screen is y = 399
  520.         mov     ymult,20                ; Olivetti vertical scale = 400/780
  521.         mov     ydiv,39                 ; same as cga setup
  522.         jmp     tekin13
  523.  
  524. tekin7a:cmp     curmode,mono            ; mono text mode?
  525.         je      tekin8                  ; e = yes
  526.         jmp     tekin11                 ; ne = no, try cga
  527.                                         ; test for Hercules
  528. tekin8: call    scrseg                  ; get screen segment, test Environment
  529.         cmp     tv_mode,0               ; Environment active?
  530.         je      tekin8a                 ; e = no, ok to test for Hercules
  531.         jmp     tekin10                 ; don't do Herc mode, do Mono
  532. tekin8a:mov     dx,hstatus              ; Herc status port
  533.         in      al,dx                   ; read it
  534.         mov     bl,al                   ; save here
  535.         and     bl,80h                  ; remember retrace bit
  536.         mov     cx,0ffffh               ; do many times (for fast machines)
  537. tekin8b:mov     dx,hstatus              ; check status port
  538.         in      al,dx
  539.         and     al,80h                  ; select bit
  540.         jmp     $+2                     ; use a little time
  541.         cmp     bl,al                   ; did it change?
  542.         loope   tekin8b                 ; test again if not
  543.         je      tekin10                 ; e = no change in bit, not Herc
  544.         mov     graph_mode,hercules     ; say have Herc board
  545.         mov     segscn,seghga           ; assume hga screen segment
  546.         mov     putc,offset gputc       ; character display routine
  547.         mov     psetup,offset psetuph   ; plot setup routine to use
  548.         mov     plotptr,offset plthga   ; use hga dot plot routine
  549.         mov     pfin,offset pfinh       ; cleanup routine
  550.         mov     pincy,offset pincyh     ; inc y routine
  551.         mov     xmult,45                ; Scale TEK to Hercules by 720/1024
  552.         mov     xdiv,64                 ;  so that 0-1023 converts to 0-719
  553.         mov     xmax,720-8              ; x-coord of rightmost character
  554.         mov     ymult,87                ; vertical scale for Hercules is
  555.         mov     ydiv,195                ;  348/780
  556.         mov     ybot,347                ; bottom of screen is y = 347
  557.         mov     ax,seghga               ; segment of Herc video display
  558.         mov     es,ax
  559.         mov     al,es:[8000h]           ; read original contents, page 1
  560.         not     byte ptr es:[8000h]     ; write new pattern
  561.         mov     ah,es:[8000h]           ; read back
  562.         not     byte ptr es:[8000h]     ; restore original contents
  563.         not     ah                      ; invert this too
  564.         cmp     ah,al                   ; same (memory present?)
  565.         jne     tekin9                  ; ne = not same, no memory there
  566.         mov     gpage,1                 ; say two pages of display memory
  567. tekin9: jmp     tekin13
  568.                                         ; test for MONO
  569. tekin10:mov     graph_mode,mono         ; force monochrome adapter text
  570.         mov     segscn,segmono          ; assume mono screen segment
  571.         call    scrseg                  ; Environments: get virtual screen
  572.         mov     segscn,ax               ;  seg returned in ax and es:di
  573.         mov     gpage,0
  574.         mov     putc,offset mputc       ; character display routine
  575.         mov     psetup,offset psetupm   ; plot setup routine to use
  576.         mov     plotptr,offset pltmon   ; use hga dot plot routine
  577.         mov     pfin,offset pfinm       ; cleanup routine
  578.         mov     pincy,offset pincym     ; inc y routine
  579.         mov     xmult,5                 ; Scale TEK to mono by 640/1024
  580.         mov     xdiv,8                  ;  so that 0-1023 converts to 0-639
  581.         mov     xmax,640-8              ; x-coord of rightmost character
  582.         mov     ymult,10                ; vertical scale for mono is 200/780
  583.         mov     ydiv,39
  584.         mov     ybot,200                ; bottom of screen is y = 200 for Bios
  585.         jmp     tekin13                 ; Uses TEXT mode, for safety
  586.  
  587.                                         ; test for CGA
  588. tekin11:mov     graph_mode,cga          ; set CGA high resolution graphics
  589.         mov     segscn,segcga           ; CGA screen segment
  590.         jmp     tekin13
  591.  
  592.                                         ; Set Graphics mode
  593. tekin13:cmp     graph_mode,hercules     ; Hercules?
  594.         jne     tekin14                 ; ne = no
  595.         call    hgraf                   ; set Herc graphics mode, clear regen
  596.         jmp     short tekin16           ; restore screen
  597. tekin14:mov     ah,0                    ; set screen mode
  598.         mov     al,graph_mode           ;  to this screen mode
  599.         cmp     gpage,0                 ; only page 0 available?
  600.         je      tekin15                 ; e = yes, and watch for Bios errors
  601.         cmp     inited,0                ; first time through?
  602.         je      tekin15                 ; e = yes, clear the page of old junk
  603.         or      al,80h                  ; save regen buffer (save area too)
  604. tekin15:int     screen                  ; Bios Set Mode.
  605.  
  606. tekin16:mov     tekflg,1                ; starting Tek sub mode
  607.         cmp     inited,0                ; inited yet?
  608.         jne     tekin19                 ; ne = yes, restore screen
  609.         mov     ttstate,offset tektxt   ; do displayable text
  610.         mov     prestate,offset tektxt  ; set a previous state of text
  611.         mov     inited,1                ; say we have initialized
  612.         call    tekcls                  ; clear screen, for ega coloring
  613.         jmp     short tekin20
  614. tekin19:call    tekrest                 ; restore old graphics screen
  615. tekin20:mov     ax,flow                 ; get flow control word
  616.         xchg    ah,al                   ; get xon into al
  617.         cmp     al,0                    ; able to send xon?
  618.         je      tekin21                 ; e = no
  619.         call    outmodem                ; tell host xon
  620. tekin21:clc                             ; clear carry for success
  621.         jmp     short tekin23
  622. tekin22:stc                             ; set carry for failure
  623. tekin23:pop     es
  624.         pop     di
  625.         pop     si
  626.         pop     dx
  627.         pop     cx
  628.         pop     bx
  629.         pop     ax
  630.         ret
  631. tekini  ENDP
  632.  
  633. ;Terminal emulation. Enter with received character in AL.
  634.  
  635. TEKEMU PROC     NEAR                    ; main emulator
  636.         cmp     tekflg,0                ; Tek mode active yet? (msz call)
  637.         jne     tektt1                  ; ne = yes
  638.         call    tekini                  ; init now
  639.         mov     ttstate,offset tektxt   ; initial state
  640.         mov     prestate,offset tektxt  ; set a previous state of text
  641.         jnc     tektt1                  ; nc = succeeded
  642.         ret                             ; else failed to init, just return
  643. tektt1: and     al,7fh                  ; force Tek chars to be 7 bits.
  644.         cmp     al,0                    ; NUL char?
  645.         je      tekign                  ; e = yes, ignore it before logging
  646.         push    ax
  647.         call    getflgs                 ; get msy yflags into al
  648.         mov     yflags,al
  649.         test    al,capt                 ; capturing output?
  650.         pop     ax
  651.         jz      tektt4                  ; z = no, forget this part
  652.         push    ax                      ; save char
  653.         call    cptchr                  ; give it captured character
  654.         pop     ax                      ; restore character and keep going
  655. tektt4: test    yflags,trnctl           ; debug? if so use tty mode
  656.         jz      tektt5                  ; z = no
  657.         cmp     al,DEL                  ; DEL char?
  658.         jne     tektt4a                 ; ne = no
  659.         mov     al,5eh                  ; make DEL a caret query mark
  660.         call    outscrn
  661.         mov     al,3fh                  ; the query mark
  662.         call    outscrn
  663.         jmp     short tekign
  664. tektt4a:cmp     al,' '                  ; control char?
  665.         jae     tektt4b                 ; ne = no
  666.         push    ax
  667.         mov     al,5eh                  ; caret
  668.         call    outscrn
  669.         pop     ax
  670.         add     al,'A'-1                ; make char printable
  671. tektt4b:call    outscrn
  672.  
  673. tekign: ret                             ; Ignore this character
  674.  
  675. tektt5: call    tkscan                  ; scan for "ESC [ ? 3 8 l" exit code
  676.         cmp     al,0                    ; null char response?
  677.         je      tekign                  ; e = yes, ignore the character
  678.                                         ; check for echo of crosshair report
  679.         cmp     repcnt,0                ; any chars need matching in report?
  680.         je      tektt5a                 ; e = no
  681.         push    bx                      ; yes
  682.         mov     bx,6                    ; number of bytes in crosshairs rpt
  683.         sub     bl,repcnt               ; number of chars needing matching
  684.         cmp     al,repbuf[bx]           ; received same as current rpt char?
  685.         pop     bx
  686.         jne     tektt5a                 ; ne = mismatch, stop echo test
  687.         dec     repcnt                  ; say one more matched
  688.         clc                             ; absorb without comment
  689.         ret                             ; stay in this state
  690. tektt5a:mov     repcnt,0                ; clear report count
  691.         cmp     al,' '                  ; control code?
  692.         jb      tektt6                  ; b = yes, decode
  693.         jmp     ttstate                 ; no, do current state
  694.                                         ; Control characters:
  695. tektt6: cmp     al,GS                   ; Line plot command?
  696.         jne     tektt7                  ; ne = no
  697.         mov     visible,0               ; Next move is invisible
  698.         and     status,not txtmode      ; set status report byte
  699.         mov     ttstate,offset tekline  ; expect coordinates next
  700.         jmp     tektt12
  701. tektt7: cmp     al,RS                   ; Incremental dot command?
  702.         jne     tektt8                  ; ne = no
  703.         and     status,not txtmode      ; set status report
  704.         mov     ttstate,offset tekrlin  ; expect pen command next
  705.         jmp     tektt12
  706. tektt8: cmp     al,FS                   ; Point plot command?
  707.         jne     tektt9                  ; ne = no
  708.         mov     visible,0               ; next move is invisible
  709.         and     status,not txtmode      ; set status report byte
  710.         mov     ttstate,offset tekpnt
  711.         jmp     tektt12
  712. tektt9: cmp     al,US                   ; assert text mode? [bjh]
  713.         jne     tektt10                 ; ne = no
  714.         or      status,txtmode          ; set status report byte
  715.         mov     ttstate,offset tektxt   ; Go to TEKTXT next time
  716.         jmp     tektt12
  717. tektt10:cmp     al,ESCAPE               ; Escape?
  718.         jne     tektt11                 ; ne = no
  719.         or      status,txtmode          ; set status report byte
  720.         cmp     ttstate,offset tekesc   ; already in escape state?
  721.         je      tektt14                 ; e = yes, nest no further
  722.         push    ttstate                 ; current state
  723.         pop     prestate                ; save here as previous state
  724.         mov     ttstate,offset tekesc   ; next state parses escapes
  725.         ret
  726. tektt11:cmp     al,CAN                  ; Control X? (exits Tek sub mode)
  727.         jne     tektt13                 ; ne = no, stay in current state
  728.         mov     ttstate,offset tektxt   ; back to text mode
  729.         test    flags.vtflg,tttek       ; main Tek emulator?
  730.         jnz     tektt12                 ; nz = yes, ignore the ^X
  731.         call    tekend                  ; else exit sub mode
  732.         mov     tekflg,0                ; clear Tek sub mode flag
  733. tektt12:mov     prestate,offset tektxt  ; make previous state text
  734. tektt14:ret
  735. tektt13:jmp     ttstate                 ; let someone else worry about this
  736. TEKEMU  ENDP
  737.  
  738. ; End TEK emulation, recover previous screen
  739.  
  740. TEKEND  PROC    NEAR
  741.         cmp     tekflg,0                ; Tek sub mode active?
  742.         jne     teknd0                  ; ne = yes
  743.         ret                             ; else return as is.
  744. teknd0: call    teksave                 ; save graphics screen to page 1
  745.         cmp     graph_mode,hercules     ; Hercules?
  746.         jne     teknd1                  ; ne = no
  747.         call    htext                   ; yes then set up Hercules text mode
  748. teknd1: mov     ah,0                    ; set video mode
  749.         mov     al,curmode              ; restore previous screen mode
  750.         int     screen                  ; revert to text screen
  751.         call    restscr                 ; restore text screen
  752.         mov     dx,cursor               ; saved cursor position
  753.         mov     bh,0                    ; page 0
  754.         mov     ah,2                    ; set cursor
  755.         int     screen
  756.         ret
  757. TEKEND  ENDP
  758.  
  759. ; State machine active while Tek is active. Senses ESC [ ? 3 8 l to exit
  760. ; Tek mode and return to either non-sub mode terminal or to a VT102.
  761. ; Plays back unmatched escape sequences. Enter with character in al.
  762.  
  763. tkscan  proc    near
  764.         and     al,7fh                  ; strip high bit
  765.         cmp     al,byte ptr tkoff       ; start of Tek Off sequence?
  766.         jne     tkscn1                  ; ne = no
  767.         call    tkscn4                  ; playback previously matched chars
  768.         mov     tkcnt,1                 ; count matched chars (one now)
  769.         mov     tkoffs,al               ; save full character, with high bit
  770.         mov     al,0                    ; our temporary response
  771.         jmp     short tkscnx            ;  and exit
  772.  
  773. tkscn1: push    bx                      ; check for char in Tek Off sequence
  774.         mov     bx,tkcnt                ; number of chars matched in Tek Off
  775.         mov     tkoffs[bx],al           ; save this char
  776.         cmp     al,byte ptr tkoff[bx]   ; match expected char in sequence?
  777.         pop     bx
  778.         jne     tkscn3                  ; ne = no, play back partial match
  779.         inc     tkcnt                   ; count new match
  780.         mov     al,0                    ; our temporary response
  781.         cmp     tkcnt,tkofflen          ; matched all char in sequence?
  782.         jne     tkscnx                  ; ne = not yet, wait for more
  783.         mov     tkcnt,0                 ; clear counter
  784.         cmp     flags.vtflg,tttek       ; are we a full Tek terminal now?
  785.         jne     tkscn2                  ; ne = no, a submode
  786.         call    vtans52                 ; toggle terminal type, in msyibm
  787. tkscn2: mov     al,CAN                  ; simulate arrival of Control-X
  788.         jmp     short tkscnx            ;  all done
  789.  
  790. tkscn3: call    tkscn4                  ; playback previously matched chars
  791.         mov     tkcnt,0                 ; reset to no match and exit
  792. tkscnx: ret                             ; common exit
  793.  
  794.                                         ; local worker procedure
  795. tkscn4: push    ax                      ; save break char (in al)
  796.         push    cx                      ; playback partial sequence to printer
  797.         mov     cx,tkcnt                ; number of chars matched before break
  798.         jcxz    tkscn4b                 ; z = none
  799.         push    si
  800.         mov     si,offset tkoffs        ; string to be played back
  801. tkscn4a:cld
  802.         lodsb                           ; get a char into al
  803.         push    cx
  804.         push    si                      ; save these around tektt5a work
  805.         call    tektt5a                 ; use it
  806.         pop     si
  807.         pop     cx
  808.         loop    tkscn4a                 ; do all that came in previously
  809.         pop     si
  810. tkscn4b:pop     cx
  811.         pop     ax                      ; recover break char
  812.         ret
  813. tkscan  endp
  814.  
  815.  
  816. TEKTXT  proc    near                    ; Dispatch on text characters
  817.         cmp     al,DEL                  ; RUBOUT?
  818.         jne     tektx1                  ; ne = no
  819.         mov     al,bs                   ; make <BS>
  820. tektx1: cmp     al,CR                   ; ^M Carriage return?
  821.         je      tektx7                  ; e = yes
  822. tektx2: cmp     al,LF                   ; ^J LineFeed?
  823.         je      tektx7                  ; e = yes
  824. tektx3: cmp     al,FF                   ; ^L Formfeed?
  825.         jne     tektx4                  ; ne = no
  826.         call    tekcls                  ; clear the screen
  827.         jmp     short tektx8
  828. tektx4: cmp     al,VT                   ; ^K vertical tab?
  829.         je      tektx7
  830.         cmp     al,bell                 ; ^G bell on line?
  831.         jne     tektx5                  ; ne = no
  832.         call    beep
  833.         jmp     short tektx8
  834. tektx5: cmp     al,Tab                  ; Tab?
  835.         jne     tektx6                  ; ne = no
  836.         mov     al,' '                  ; make it a space
  837. tektx6: cmp     al,BS                   ; ^H backspace?
  838.         je      tektx7                  ; e = yes
  839.         cmp     al,' '                  ; control char?
  840.         jb      tektx8                  ; b = yes, ignore it
  841. tektx7: call    OUTSCRN                 ; output character to the screen
  842. tektx8: ret
  843. TEKTXT  endp
  844.  
  845. ; Process escape sequences. Callable from msz terminal emulator.
  846. ; Enter with received character in AL. Escape sequences are generally
  847. ; treated as interruptions to the current plotting/text command. Screen
  848. ; clearing is the exception by causing a general emulator reset.
  849. TEKESC  PROC    NEAR
  850.         mov     ttstate,offset tekesc   ; in case get here from msz file
  851.         cmp     tekflg,0                ; Tek mode active yet? (msz call)
  852.         jne     tekesc1                 ; ne = yes
  853.         call    tekini                  ; init now
  854.         mov     prestate,offset tektxt  ; set a previous state of text
  855.         jnc     tekesc1                 ; nc = succeeded
  856.         ret                             ; else failed to init, just return
  857.  
  858. tekesc1:cmp     al,'Z'                  ; ESC-Z Identify?
  859.         jne     tekesc2                 ; ne = no
  860.         call    SENDID                  ; Send terminal identification
  861.         jmp     tekescx
  862.  
  863. tekesc2:cmp     al,FF                   ; ESC-FF Clear screen?
  864.         jne     tekesc3                 ; ne = no
  865.         call    tekcls                  ; Clear screen
  866.         mov     prestate,offset tektxt  ; make previous state text mode
  867.         jmp     tekescx                 ; Return to text mode after ESC-FF
  868.  
  869. tekesc3:cmp     al,ESCZ                 ; ESC-^Z Enter GIN mode?
  870.         jne     tekesc4                 ; ne = no
  871.         cmp     graph_mode,mono         ; Monochrome text mode?
  872.         je      tekesc3a                ; e = yes, no crosshairs in text mode
  873.         call    CROSHAIR                ; Activate the cross-hairs
  874.         jmp     tekescx
  875. tekesc3a:call   beep                    ; tell the user we are unhappy
  876.         jmp     tekescx                 ; and ignore the command
  877.  
  878. tekesc4:cmp     al,ENQ                  ; ESC-^E Enquiry for cursor position?
  879.         jne     tekesc5                 ; ne = no
  880.         call    SENDSTAT                ; send status
  881.         jmp     tekescx
  882.  
  883. tekesc5:cmp     al,accent               ; accent grave, line pattern series?
  884.         jb      tekescx                 ; b = no
  885.         cmp     al,65h                  ; lowercase e?
  886.         ja      tekescx                 ; a = beyond line pattern series
  887.         push    bx
  888.         mov     bl,al
  889.         sub     bl,accent               ; remove bias
  890.         mov     bh,0
  891.         shl     bx,1                    ; make this a word index
  892.         mov     bx,linetab[bx]          ; get line pattern word
  893.         mov     linepat,bx              ; save in active word
  894.         pop     bx                      ; return to previous mode
  895.  
  896. tekescx:push    ax
  897.         mov     ax,prestate             ; get previous state
  898.         mov     ttstate,ax              ; restore it
  899.         or      ax,ax                   ; test for none
  900.         pop     ax
  901.         jz      go2text                 ; z = none, use text mode
  902.         clc
  903.         ret                             ; resume previous state
  904.  
  905. go2text:mov     ttstate,offset tektxt   ; Go to TEKTXT next time
  906.         mov     lastc,0                 ; clear last drawing coordinate flag
  907.         or      status,txtmode          ; set text mode in status byte
  908.         clc
  909.         ret
  910.  
  911. TEKESC  ENDP
  912.  
  913. TEKLINE proc    near                    ; GS line drawing
  914.         call    tekxyc                  ; parse coordinates from input bytes
  915.         jnc     teklin1                 ; nc = not done yet
  916.         mov     cl,visible              ; get moveto or drawto variable
  917.         call    tekdraw                 ; move that point
  918.         mov     visible,1               ; say next time we draw
  919. teklin1:ret
  920. TEKLINE endp
  921.  
  922. TEKPNT  proc    near                    ; FS plot single point
  923.         call    tekxyc                  ; parse coordinates
  924.         jnc     tekpnt1                 ; nc = not done yet
  925.         mov     cl,0                    ; do not draw
  926.         call    tekdraw                 ; move to the point
  927.         mov     ax,si                   ; copy starting point to end point
  928.         mov     bx,di                   ; ax,bx,si,di are in PC coordinates
  929.         mov     cl,1                    ; make plot visible
  930.         call    line                    ; draw the dot
  931.         mov     visible,0               ; return to invisibility
  932. tekpnt1:ret
  933. TEKPNT  endp
  934.  
  935. ; Decode graphics x,y components. Returns carry set to say have all
  936. ; components for a line, else carry clear. Understands 4014 lsb extensions.
  937. ; Permits embedded escape sequences.
  938. TEKXYC  proc    near
  939.         cmp     al,CR                   ; Exit drawing on CR,LF,RS,US,FS,CAN
  940.         je      go2text                 ; e = yes, a cr
  941.         cmp     al,LF                   ; these terminate line drawing cmds
  942.         je      go2text
  943.         cmp     al,FS                   ; <FS>
  944.         je      go2text
  945.         cmp     al,RS                   ; <RS>
  946.         je      go2text
  947.         cmp     al,US                   ; <US>
  948.         je      go2text
  949.         cmp     al,CAN                  ; and <CAN>
  950.         je      go2text                 ; BUT ignore other control chars
  951.         cmp     al,20h                  ; Control char?
  952.         jb      tekgh0                  ; b = yes, ignore it
  953.         cmp     al,40h
  954.         jb      tekgh2                  ; 20-3F are HIX or HIY
  955.         cmp     al,60h                  ; 40-5F are LOX (causes beam movement)
  956.         jb      tekgh4                  ; 60-7F are LOY
  957.  
  958.                                         ; Extract low-order 5 bits of Y coord
  959.         mov     ah,tek_loy              ; Copy previous LOY to MSB (4014)
  960.         mov     tek_lsb,ah
  961.         and     al,1Fh                  ; LOY is 5 bits
  962.         mov     tek_loy,al
  963.         cmp     lastc,loy               ; 2nd LOY in a row?
  964.         je      tekgh1                  ; Yes, then LSB is valid
  965.         mov     tek_lsb,0               ; 1st one, clear LSB
  966. tekgh1: mov     lastc,loy               ; LOY seen, expect HIX (instead of HIY)
  967. tekgh0: clc                             ; c clear = not completed yet
  968.         ret
  969.                       ; Extract high-order 5 bits (X or Y, depending on lastc)
  970. tekgh2: and     ax,1Fh                  ; Just 5 bits
  971.         mov     cl,5
  972.         shl     ax,cl                   ; Shift over 5 bits
  973.         cmp     lastc,loy               ; was last coordinate a low-y?
  974.         je      tekgh3                  ; e = yes, parse hix
  975.         mov     tek_hiy,ax              ; this byte has HIY
  976.         mov     lastc,hiy
  977.         clc
  978.         ret
  979. tekgh3: mov     tek_hix,ax              ; This byte has HIX
  980.         mov     lastc,hix
  981.         clc
  982.         ret
  983. tekgh4: and     al,1Fh                  ; Just 5 bits
  984.         mov     tek_lox,al
  985.         mov     lastc,lox
  986.         mov     ax,tek_hix              ; Combine HIX*32
  987.         or      al,tek_lox              ;  with LOX
  988.         mov     bx,tek_hiy              ; Same for Y
  989.         or      bl,tek_loy
  990.         stc                             ; set c to say completed operation
  991.         ret
  992. TEKXYC  endp
  993.  
  994. TEKRLIN proc    near                    ; RS relative line drawing
  995.         cmp     al,' '                  ; Pen up command?
  996.         jne     tekrli1                 ; ne = no, try pen down
  997.         mov     visible,0               ; do invisible movements
  998.         jmp     short tekrli2           ; do the command
  999. tekrli1:cmp     al,'P'                  ; pen down command?
  1000.         jne     tekrli3                 ; ne = no, return to text mode
  1001.         mov     visible,1               ; set visible moves
  1002.  
  1003. tekrli2:mov     ax,x_coord              ; PC x coordinate of pen
  1004.         mov     bx,y_coord              ;    y coordinate
  1005.         call    pctotek                 ; get current pen position in Tek coor
  1006.         mov     cl,0                    ; invisible, moveto
  1007.         call    tekdraw                 ; move that point, set oldx and oldy
  1008.         mov     ttstate,offset tekinc   ; next get incremental movement cmds
  1009.         ret
  1010.  
  1011. tekrli3:mov     visible,0               ; bad char, reset visibility
  1012.         push    prestate
  1013.         pop     ttstate                 ; restore previous state
  1014.         jmp     tektt5                  ; deal with the break char
  1015. TEKRLIN endp
  1016.                                         ; interpret RS inc plot command byte
  1017. TEKINC  proc    near                    ; get movement character and do cmd
  1018.         cmp     al,'A'                  ; move right?
  1019.         jne     tekinc1                 ; ne = no
  1020.         inc     oldx                    ; adjust beam position
  1021.         jmp     short tekinc9
  1022. tekinc1:cmp     al,'E'                  ; move right and up?
  1023.         jne     tekinc2                 ; ne = no
  1024.         inc     oldx
  1025.         inc     oldy
  1026.         jmp     short tekinc9
  1027. tekinc2:cmp     al,'D'                  ; move up?
  1028.         jne     tekinc3                 ; ne = no
  1029.         inc     oldy
  1030.         jmp     short tekinc9
  1031. tekinc3:cmp     al,'F'                  ; move left and up?
  1032.         jne     tekinc4                 ; ne = no
  1033.         dec     oldx
  1034.         inc     oldy
  1035.         jmp     short tekinc9
  1036. tekinc4:cmp     al,'B'                  ; move left?
  1037.         jne     tekinc5                 ; ne = no
  1038.         dec     oldx
  1039.         jmp     short tekinc9
  1040. tekinc5:cmp     al,'J'                  ; move left and down?
  1041.         jne     tekinc6                 ; ne = no
  1042.         dec     oldx
  1043.         dec     oldy
  1044.         jmp     short tekinc9
  1045. tekinc6:cmp     al,'H'                  ; move down?
  1046.         jne     tekinc7                 ; ne = no
  1047.         dec     oldy
  1048.         jmp     short tekinc9
  1049. tekinc7:cmp     al,'I'                  ; move right and down?
  1050.         jne     tekincb                 ; ne = no, bad command
  1051.         inc     oldx
  1052.         dec     oldy
  1053. tekinc9:cmp     oldx,0                  ; too far left?
  1054.         jge     tekinc10                ; ge = no
  1055.         mov     oldx,0                  ; else stop at the left margin
  1056. tekinc10:cmp    oldx,maxtekx-1          ; too far left?
  1057.         jle     tekinc11                ; le = no
  1058.         mov     oldx,maxtekx-1          ; else stop that the left margin
  1059. tekinc11:cmp    oldy,maxteky-1          ; above the top?
  1060.         jle     tekinc12                ; le = no
  1061.         mov     oldy,maxteky-1          ; else stop at the top
  1062. tekinc12:cmp    oldy,0                  ; below the bottom?
  1063.         jge     tekinc13                ; ge = no
  1064.         mov     oldy,0                  ; else stop at the bottom
  1065. tekinc13:mov    ax,oldx                 ; ax is vector x end point
  1066.         mov     bx,oldy                 ; bx is vector y end point
  1067.         mov     cl,visible
  1068.         call    tekdraw                 ; move/draw to that point
  1069.         ret
  1070. tekincb:push    prestate                ; bad character, exit inc plot mode
  1071.         pop     ttstate                 ; new state is previous state
  1072.         mov     visible,0
  1073.         jmp     tektt5                  ; reparse the bad char
  1074. TEKINC  endp
  1075.  
  1076.  
  1077. ; Routine to trigger the crosshairs, wait for a key to be struck, and send
  1078. ; the typed char (if printable ascii) plus four Tek encoded x,y position
  1079. ; coordinates and then a carriage return.
  1080. ; ax, by, xcross, ycross operate in PC coordinates.
  1081.  
  1082. CROSHAIR PROC NEAR
  1083.         push    linepat                 ; save line drawing pattern
  1084.         mov     linepat,0ffffh          ; reset line type to solid
  1085.  
  1086. crosha0:mov     ax,xmax                 ; right margin minus 7 dots
  1087.         add     ax,7
  1088.         mov     temp,ax                 ; right margin dot
  1089.         shr     ax,1                    ; central position
  1090.         mov     xcross,ax               ; save PC coord for crosshair
  1091.         mov     ax,ybot                 ; last scan line
  1092.         shr     ax,1
  1093.         mov     ycross,ax               ; this is the center of the screen
  1094. crosha1:call    crosdraw                ; draw the cross-hairs
  1095.         mov     ah,coninq               ; DOS, quiet read char
  1096.         int     dos
  1097.         push    ax                      ; save char for later
  1098.         call    crosdraw                ; erase cross hairs
  1099.         pop     ax
  1100.         or      al,al                   ; ascii or scan code returned
  1101.         jnz     arrow5                  ; nz = ascii char returned
  1102.  
  1103.         mov     ah,coninq               ; read scan code
  1104.         int     dos
  1105.         cmp     al,0                    ; Control-Break?
  1106.         jne     crosha3                 ; ne = no, something else
  1107. crosha2:pop     linepat                 ; restore line pattern
  1108.         ret                             ; exit crosshairs mode
  1109.  
  1110. crosha3:cmp     al,homscn               ; is it 'home'?
  1111.         je      crosha0                 ; e = yes
  1112.         jmp     short arrow1            ; else try the arrow keys
  1113.  
  1114. arrow1: cmp     al,lftarr               ; left arrow?
  1115.         jne     arrow2                  ; ne = no
  1116.         mov     cx,-1                   ; left shift
  1117.         jmp     short xkeys
  1118. arrow2: cmp     al,rgtarr               ; right arrow?
  1119.         jne     arrow3                  ; ne = no
  1120.         mov     cx,1                    ; right shift
  1121.         jmp     short xkeys
  1122. arrow3: cmp     al,uparr                ; up arrow?
  1123.         jne     arrow4                  ; ne = no
  1124.         mov     cx,-1                   ; up shift
  1125.         jmp     short vertkey
  1126. arrow4: cmp     al,dnarr                ; down arrow?
  1127.         jne     badkey                  ; ne = no, ignore it
  1128.         mov     cx,1                    ; down shift
  1129.         jmp     short vertkey
  1130.  
  1131. badkey: call    beep                    ; tell user we don't understand
  1132.         jmp     crosha1                 ; keep going
  1133.  
  1134.                                         ; Shifted keys yield ascii keycodes
  1135. arrow5: cmp     al,'C' and 1fh          ; Control-C?
  1136.         je      crosha2                 ; e = yes, exit crosshairs mode now
  1137.         cmp     al,shlftarr             ; shifted left arrow?
  1138.         jne     arrow6                  ; ne = no
  1139.         mov     cx,-64                  ; big left shift
  1140.         jmp     short xkeys
  1141. arrow6: cmp     al,shrgtarr             ; shifted right arrow?
  1142.         jne     arrow7                  ; ne = no
  1143.         mov     cx,64                   ; big right shift
  1144.         jmp     short xkeys
  1145. arrow7: cmp     al,shuparr              ; shifted up arrow?
  1146.         jne     arrow8                  ; ne = no
  1147.         mov     cx,-32                  ; big up shift
  1148.         jmp     short vertkey
  1149. arrow8: cmp     al,shdnarr              ; shifted down arrow?
  1150.         jne     charkey                 ; ne = no, send this key as is
  1151.         mov     cx,32                   ; big down shift
  1152.         jmp     short vertkey
  1153.  
  1154. xkeys:  add     cx,xcross               ; add increment
  1155.         jns     noxc                    ; gone too far negative?
  1156.         mov     cx,0                    ; yes - then make it 0
  1157. noxc:   cmp     cx,temp                 ; too far right?
  1158.         jb      xdraw9                  ; b = no
  1159.         mov     cx,temp                 ; yes - then make it the right
  1160. xdraw9: mov     xcross,cx               ; new x value for cross hairs
  1161.         jmp     crosha1                 ; and redraw
  1162.  
  1163. vertkey:add     cx,ycross               ; adjust cx
  1164.         jns     noyc                    ; gone negative?
  1165.         mov     cx,0                    ; yes then make 0
  1166. noyc:   cmp     cx,ybot                 ; too high?
  1167.         jb      yok
  1168.         mov     cx,ybot                 ; make it maximum
  1169. yok:    mov     ycross,cx               ; save new y crosshair
  1170.         jmp     crosha1                 ; and redraw
  1171.  
  1172. charkey:call    clrbuf                  ; purge received data to date
  1173.         mov     repcnt,6                ; set length of report string
  1174.         mov     repbuf,al               ; store first report character
  1175.         call    outmodem                ; send the break character
  1176.         mov     ax,xcross               ; set beam to xcross,ycross
  1177.         mov     bx,ycross               ; must convert to Tek coordinates
  1178.         call    pctotek                 ; scale from PC screen coord to Tek
  1179.         push    ax                      ; save around drawing
  1180.         push    bx
  1181.         mov     cx,0                    ; just a move
  1182.         call    tekdraw                 ; moveto ax,bx in Tek coord
  1183.         pop     bx                      ; recover Tek y
  1184.         pop     ax                      ; recover Tek x
  1185.         call    sendpos                 ; send position report to host
  1186.         pop     linepat                 ; recover current line drawing pattern
  1187.         ret
  1188. CROSHAIR ENDP
  1189.  
  1190. ; CROSDRAW draws cross-hairs by XORing cross with picture.
  1191. ; xcross and ycross are in PC coordinates.
  1192. CROSDRAW PROC   NEAR
  1193.         mov     si,xcross               ; move to (xcross, ycross-12)
  1194.         mov     di,ycross
  1195.         sub     di,12                   ; half the size of the cross
  1196.         jns     crosd1                  ; no sign bit means ok
  1197.         mov     di,0                    ; else limit to start of screen
  1198. crosd1: mov     ax,si                   ; next, draw to (xcross, ycross+12)
  1199.         mov     bx,ycross               ; make bottom stroke
  1200.         add     bx,12
  1201.         cmp     bx,ybot                 ; too large?
  1202.         jbe     crosd2                  ; be = no
  1203.         mov     bx,ybot                 ; vertical line to (xcross,ybot)
  1204. crosd2: mov     cx,0ffh                 ; invert pixels
  1205.         call    line                    ; and draw vertical
  1206.         sub     si,12                   ; move to (xcross-12, ycross)
  1207.         jns     crosd3                  ; no sign means ok
  1208.         mov     si,0                    ; else limit to start of line
  1209. crosd3: mov     di,ycross
  1210.         mov     bx,di
  1211.         mov     ax,xcross               ; draw to (xcross+12, ycross)
  1212.         add     ax,12
  1213.         cmp     ax,temp                 ; temp is right margin, too large?
  1214.         jbe     crosd4                  ; be = no, ok
  1215.         mov     ax,temp                 ; max x value
  1216. crosd4: mov     cx,0ffh                 ; set XOR code
  1217.         call    line                    ; draw to (xcross+12, ycross)
  1218.         ret
  1219. CROSDRAW ENDP
  1220.  
  1221. ; SENDPOS sends position of cross-hairs to the host.
  1222. ; ax has Tek X and bx has Tek Y coord of center of crosshair
  1223. SENDPOS PROC NEAR
  1224.         push    bx                      ; preserve register
  1225.         call    sendxy                  ; send x coord
  1226.         mov     word ptr repbuf+1,ax    ; first word
  1227.         pop     ax
  1228.         call    sendxy                  ; send y coord
  1229.         mov     word ptr repbuf+3,ax    ; second word
  1230.         mov     al,cr                   ; follow up with cr
  1231.         mov     repbuf+5,al             ; last report character
  1232.         call    outmodem
  1233.         ret
  1234. SENDPOS ENDP
  1235.  
  1236. ; SENDXY sends value of ax as Tek encoded bytes
  1237. ; ax is in Tek coordinates
  1238. SENDXY  PROC    NEAR
  1239.         shl     ax,1
  1240.         shl     ax,1                    ; move all but lower 5 bits to ah
  1241.         shl     ax,1
  1242.         shr     al,1
  1243.         shr     al,1                    ; move low five bits to low 5 bits
  1244.         shr     al,1
  1245.         or      ah,20h                  ; make it a printing char as per TEK
  1246.         xchg    al,ah                   ; send high 5 bits first
  1247.         call    outmodem
  1248.         xchg    al,ah                   ; then low five bits
  1249.         or      al,20h
  1250.         call    outmodem
  1251.         xchg    ah,al                   ; al is first sent byte
  1252.         ret
  1253. SENDXY  ENDP
  1254.  
  1255.  
  1256. SENDID  PROC NEAR                       ; Pretend VT100 with graphics option
  1257.         mov     bx,IDSEQ                ; Get addr of string
  1258. sndid1: mov     al,[bx]                 ; Get char from sequence
  1259.         cmp     al,0                    ; End of sequence?
  1260.         jz      sndid0                  ; Yes, return
  1261.         call    OUTMODEM                ; Send it out the port
  1262.         inc     bx
  1263.         jmp     sndid1
  1264. sndid0: ret
  1265. SENDID  ENDP
  1266.  
  1267. ; SENDSTAT - send status and cursor position to host
  1268.  
  1269. SENDSTAT PROC NEAR
  1270.         mov     al,STATUS               ; get tek status
  1271.         or      al,20h                  ; make it printable
  1272.         call    OUTMODEM                ; and send it
  1273.         mov     ax,oldx                 ; now send x coordinate (oldx is Tek)
  1274.         call    SENDXY
  1275.         mov     ax,oldy                 ; and y coordinate (oldy is Tek coord)
  1276.         call    SENDXY
  1277.         mov     al,cr                   ; end with a cr
  1278.         call    OUTMODEM
  1279.         ret
  1280. SENDSTAT ENDP
  1281.  
  1282. ; routine to send al to the modem port
  1283.  
  1284. OUTMODEM PROC   NEAR
  1285.         push    ax
  1286.         mov     ah,al
  1287.         call    outchr                  ; outchr reads from ah
  1288.          nop                            ; ignore errors
  1289.          nop
  1290.          nop
  1291.         pop     ax
  1292.         ret
  1293. OUTMODEM ENDP
  1294.  
  1295. ; Convert X and Y from PC coordinates to Tek coordinates. AX = X, BX = Y
  1296. ; for both input and output.
  1297. pctotek proc    near
  1298.         mul     xdiv                    ; scale from PC screen coord to Tek
  1299.         div     xmult
  1300.         xchg    bx,ax                   ; save Tek x coord in bx
  1301.         neg     ax                      ; y axis. Turn upside down for Tek
  1302.         add     ax,ybot
  1303.         mul     ydiv                    ; scale y from PC screen coord to Tek
  1304.         div     ymult
  1305.         xchg    ax,bx                   ; ax has X, bx has Y in Tek coords
  1306.         ret
  1307. pctotek endp
  1308.  
  1309. ; Routine to output character in AL to the screen.
  1310.  
  1311. OUTSCRN PROC NEAR                       ; Output one character to the screen
  1312.                                         ; Set Translation Input filter
  1313.         cmp     rxtable+256,0           ; translation turned off?
  1314.         je      outsct                  ; e = yes, no translation
  1315.         push    bx
  1316.         mov     bx,offset rxtable       ; address of translate table
  1317.         xlatb                           ; new char is in al
  1318.         and     al,7fh                  ; retain only lower seven bits
  1319.         pop     bx
  1320. outsct: mov     si,ybot                 ; get last scan line
  1321.         inc     si                      ; number of scan lines
  1322.         sub     si,y_coord              ; minus where char bottom needs to go
  1323.         jnc     outscc                  ; nc = enough space for char
  1324.                                         ; else give "More >" message
  1325.         push    ax                      ; save current char
  1326.         mov     ax,mormsglen            ; characters in More message
  1327.         shl     ax,1
  1328.         shl     ax,1
  1329.         shl     ax,1                    ; times 8 bits/character
  1330.         neg     ax                      ; (note: leave last char cell empty)
  1331.         add     ax,xmax                 ; right justify
  1332.         mov     x_coord,ax              ; set starting x dot
  1333.         mov     ax,ybot
  1334.         mov     y_coord,ax              ; set starting y line
  1335.         mov     ah,gfcol                ; get screen coloring
  1336.         mov     al,gbcol
  1337.         push    ax                      ; save it
  1338.         xchg    ah,al                   ; interchange colors for message
  1339.         mov     gfcol,ah
  1340.         mov     gbcol,al
  1341.         mov     si,offset moremsg       ; give More message
  1342.         push    cx
  1343.         mov     cx,mormsglen
  1344. outsclf:cld
  1345.         lodsb                           ; read a byte from string
  1346.         call    putc                    ; display the string
  1347.         loop    outsclf                 ; repeat for all string chars
  1348.         pop     cx
  1349.         pop     ax                      ; restore normal video
  1350.         mov     gfcol,ah
  1351.         mov     gbcol,al
  1352.         mov     ah,coninq               ; read keyboad via DOS
  1353.         int     dos                     ; wait for keystroke
  1354.         or      al,al                   ; scan code being returned?
  1355.         jne     outscl3                 ; ne = no
  1356.         mov     ah,coninq               ; clear away scan code too
  1357.         int     dos
  1358. outscl3:call    tekcls                  ; clear the screen
  1359.         pop     ax                      ; recover current character
  1360.         cmp     al,lf                   ; just a line feed?
  1361.         jne     outscc                  ; ne = no, display it
  1362.         ret                             ;  else ignore the line feed
  1363.  
  1364. outscc: push    ax
  1365.         mov     ax,xmax
  1366.         cmp     x_coord,ax              ; beyond right margin?
  1367.         jbe     outsc3                  ; be = no
  1368.         mov     al,cr                   ; else simulate cr/lf
  1369.         call    putc                    ; before displaying current char
  1370.         mov     al,lf
  1371.         call    putc
  1372. outsc3: pop     ax
  1373.         call    putc                    ; routine to draw characters
  1374.         ret
  1375. OUTSCRN ENDP
  1376.  
  1377.  
  1378. ; TEKCLS routine to clear the screen.
  1379. ; Entry point tekcls1 clears screen without resetting current point.
  1380. TEKCLS  PROC    NEAR
  1381.         cmp     tekflg,0                ; Tek sub mode active yet?
  1382.         jne     tekcls0                 ; ne = yes
  1383.         ret                             ; else ignore this call
  1384. tekcls0:mov     x_coord,0               ; starting text coordinates
  1385.         mov     y_coord,8
  1386.         mov     oldx,0                  ; assumed cursor starting location
  1387.         mov     oldy,maxteky            ;  top right corner (Tek coord)
  1388.         mov     scalex,0                ; clear last plotted point (PC coord)
  1389.         mov     scaley,0
  1390.         mov     lastc,0                 ; last parsed x,y coordinate
  1391.         mov     visible,0               ; make lines invisible
  1392.         mov     linepat,0ffffh          ; reset line pattern to solid
  1393.         mov     ccode,1                 ; reset to ordinary writing
  1394.         mov     ttstate,offset tektxt   ; do displayable text
  1395.  
  1396. tekcls1:push    ax                      ; save registers
  1397.         push    cx
  1398.         cmp     graph_mode,hercules     ; Hercules?
  1399.         jne     tekcls2                 ; ne = no
  1400.         call    hgraf                   ; set Hercules board to Graphics mode
  1401.         jmp     tekcls7
  1402.  
  1403. tekcls2:mov     di,0                    ; point to start of screen, di=row
  1404.         call    psetup                  ; setup graphics routine and es:di
  1405.         mov     cx,4000h                ; CGA, 200 lines times 80 bytes worth
  1406.         cmp     graph_mode,cga          ; cga?
  1407.         je      tekcls3                 ; e = yes
  1408.         mov     cx,8000h                ; Olivetti, 400 lines times 80 bytes
  1409.         cmp     graph_mode,olivetti     ; AT&T-Olivetti?
  1410.         jne     tekcls4                 ; ne = no
  1411. tekcls3:cld                             ; clear screen directly of text stuff
  1412.         mov     al,0                    ; color is black
  1413.         rep     stosb                   ; clear the bytes
  1414.         jmp     short tekcls7
  1415.  
  1416. tekcls4:cmp     graph_mode,ega          ; EGA?
  1417.         je      tekcls5                 ; e = yes
  1418.         cmp     graph_mode,monoega      ; EGA with mono display?
  1419.         je      tekcls5                 ; e = yes
  1420.         cmp     graph_mode,colorega     ; EGA with medium resolution monitor?
  1421.         je      tekcls5                 ; e = yes
  1422.         jmp     short tekcls6           ; else use Bios
  1423.  
  1424. tekcls5:                                ; EGA clear screen quickly
  1425.         mov     ax,0ff08h               ; set all 8 bits to be changed
  1426.         call    ega_gc                  ; set bit mask register accordingly
  1427.         mov     cx,ybot                 ; last scan line
  1428.         inc     cx                      ; number of scan lines
  1429.         mov     ax,80                   ; bytes per scan line
  1430.         mul     cx
  1431.         mov     cx,ax                   ; cx = number of bytes to clear
  1432.         mov     al,gbcol                ; select background colour
  1433.         cld
  1434.         rep     stosb                   ; write backgound color
  1435.         jmp     short tekcls7
  1436.  
  1437. tekcls6:push    es                      ; clear screen by scrolling up
  1438.         call    cmblnk                  ; clear screen, for Environments
  1439.         pop     es
  1440.  
  1441. tekcls7:mov     si,0                    ; starting x  (in case screen is
  1442.         mov     di,0                    ; starting y    cleared by user)
  1443.         pop     cx
  1444.         pop     ax
  1445.         ret
  1446. TEKCLS  ENDP
  1447.  
  1448. ; Routine to draw a line on the screen, using TEKTRONIX coordinates.
  1449. ; X coordinate in AX, 0=left edge of screen, 1023=right edge of screen.
  1450. ; Y coordinate in BX, 0=bottom of screen, 779=top of screen.
  1451. ; CL=0 - invisible move, CL=1 - draw a line, CL=0FFh - invert pixels on line
  1452.  
  1453. TEKDRAW PROC NEAR
  1454.         mov     si,scalex               ; get old x already scaled
  1455.         mov     di,scaley               ; get old y already scaled
  1456.         call    scale                   ; scale new end point to PC coords
  1457.         cmp     cl,0                    ; invisible drawing?
  1458.         je      moveto                  ; z = just move, skip draw part
  1459.         call    LINE                    ; draw the line
  1460. moveto: mov     x_coord,ax              ; update text coordinates to match
  1461.         mov     y_coord,bx              ;  last drawn point
  1462.         ret
  1463. TEKDRAW ENDP
  1464.  
  1465. ; scale TEKTRONIX coordinates to the currently defined screen coordinates
  1466. ; AX holds X axis, BX holds Y axis. Both are changed from Tektronix coord
  1467. ; to PC coordinates by this procedure.
  1468. SCALE   PROC    NEAR
  1469.         push    dx
  1470.         push    si
  1471.         mov     oldx,ax                 ; save current Tek x for next draw
  1472.         mov     oldy,bx                 ; save current Tek y for next draw
  1473.         mul     xmult                   ; scale x-coord
  1474.         mov     si,xdiv                 ; get the divisor
  1475.         shr     si,1                    ; halve it
  1476.         add     ax,si                   ; add in - to round to nearest integer
  1477.         adc     dx,0
  1478.         div     xdiv
  1479.         push    ax
  1480.         mov     ax,bx
  1481.         mul     ymult                   ; scale y-coord
  1482.         mov     si,ydiv                 ; get divisor
  1483.         shr     si,1                    ; halve it
  1484.         add     ax,si                   ; add in - to round to nearest integer
  1485.         adc     dx,0
  1486.         div     ydiv
  1487.         mov     bx,ybot
  1488.         sub     bx,ax                   ; Put new Y in right reg
  1489.         jns     scale3                  ; ns = not too far
  1490.         mov     bx,0
  1491. scale3: pop     ax                      ; Put new X in right reg
  1492.         mov     scalex,ax               ; save scaled values
  1493.         mov     scaley,bx
  1494.         pop     si
  1495.         pop     dx
  1496.         ret
  1497. SCALE   ENDP
  1498.  
  1499. ; LINE  Subroutine to plot a line with endpoints in AX,BX and SI,DI.
  1500. ;       fast line drawing routine for the IBM PC
  1501. ;
  1502. ; Registers at CALL
  1503. ; -----------------
  1504. ; SI=Start X coord, all in PC coordinates
  1505. ; DI=Start Y coord
  1506. ; AX=End X coord
  1507. ; BX=End Y coord
  1508. ; CL=Color code: 1=draw foreground, 0=draw background, 0ffh=invert
  1509. ; BP= line drawing pattern (is changed here by rotation)
  1510. ; registers are all unchanged
  1511.  
  1512. LINE    PROC    NEAR
  1513.         push    ax
  1514.         push    bx
  1515.         push    cx
  1516.         push    dx
  1517.         push    si
  1518.         push    di
  1519.         push    es
  1520.         mov     bp,linepat              ; store active line pattern word in BP
  1521.         mov     ccode,cl        ; save color code in ccode for use by plot()
  1522.                         ; first get coord to achieve increasing x; deltax >= 0
  1523.         sub     ax,si                   ; deltax = x2 - x1
  1524.         jge     line1                   ; ge = going to the right, as desired
  1525.         neg     ax                      ; make deltax non-negative
  1526.         sub     si,ax                   ; swap the x coordinates
  1527.         xchg    bx,di                   ; swap the y coordinates too
  1528.                                 ; second, compute deltay. ax = deltax, si = x1
  1529. line1:  sub     bx,di                   ; deltay = y2 - y1
  1530.         call    psetup                  ; setup display adapter for plotting
  1531.                                         ;  and setup es:di to screen memory
  1532.   ; Choose algorithm based on |deltay| < |deltax| (use shallow) else steep.
  1533.   ; We arrange matters such that both deltas are non-negative.
  1534.         cmp     bx,0                    ; deltay
  1535.         jge     line2                   ; ge = non-negative
  1536.         neg     linelen
  1537.         neg     bx                      ; make non-negative
  1538. line2:  cmp     bx,ax                   ; |deltay| versus |deltax|
  1539.         jbe     shallow                 ; be = do shallow algorithm
  1540.         jmp     steep                   ; else do steep algorithm
  1541.  
  1542.         ; shallow algorithm, move along x, di=y1, bx=deltay, si=x1, ax=deltax
  1543. shallow:add     bx,bx                   ; bx = 2*deltay
  1544.         mov     cx,ax                   ; cx = number of steps (deltax here)
  1545.         inc     cx                      ; loop dec's cx before testing
  1546.         mov     dx,bx                   ; dx holds error
  1547.         sub     dx,ax                   ; error = 2*deltay - deltax
  1548.         add     ax,ax                   ; ax = 2*|deltax|
  1549. shal1:  call    plotptr                 ; Plot(x,y)
  1550.         cmp     dx,0
  1551.         jle     shal2                   ; le =   error <= 0
  1552.         call    pincy                   ; increment y by one scan line
  1553.         sub     dx,ax                   ; error = error - 2*deltax
  1554. shal2:  add     dx,bx                   ; error = error + 2*deltay
  1555.         inc     si                      ; x = next dot right
  1556.         loop    shal1
  1557. shal3:  jmp     plotex
  1558.  
  1559.         ; steep algorithm, move along y, di=y1, bx=deltay, si=x1, ax=deltax
  1560. steep:  add     ax,ax                   ; ax = 2*deltax
  1561.         mov     dx,ax                   ; dx holds error
  1562.         sub     dx,bx                   ; error = 2*deltax(bx) - deltay (bx)
  1563.         mov     cx,bx                   ; cx = number of steps (deltay here)
  1564.         inc     cx                      ; loop dec's cx before testing
  1565.         add     bx,bx                   ; bx = 2*|deltay|
  1566. stee1:  call    plotptr                 ; Plot(x,y) x = ax, y = di
  1567.         cmp     dx,0
  1568.         jle     stee2                   ; le  error <= 0
  1569.         inc     si                      ; x = next dot right
  1570.         sub     dx,bx                   ; error = error - 2*deltay
  1571. stee2:  add     dx,ax                   ; error = error + 2*deltax
  1572.         call    pincy                   ; increment y
  1573.         loop    stee1
  1574. stee3:  jmp     plotex
  1575.  
  1576. plotex: call    pfin                    ; cleanup boards after plotting
  1577.         mov     ccode,1                 ; reset to do foreground coloring
  1578.         pop     es
  1579.         pop     di
  1580.         pop     si
  1581.         pop     dx                      ; restore the world
  1582.         pop     cx
  1583.         pop     bx
  1584.         pop     ax
  1585.         ret
  1586. LINE    ENDP
  1587.  
  1588. ;;;;;;;;;;;;;;;;;;;;;;;;;;; EGA plot support routines
  1589. psetupe proc    near                    ; EGA setup for plotting
  1590.         push    ax
  1591.         mov     linelen,80              ; for y going down screen by pincy
  1592.         mov     ax,segscn               ; set es to screen memory segment
  1593.         mov     es,ax
  1594.         mov     ax,0205h                ; mode: write mode 2
  1595.         call    ega_gc
  1596.         mov     ax,0003h                ; assume writing bits directly
  1597.         cmp     ccode,0ffh              ; inverting bits?
  1598.         jne     psete2                  ; ne = no
  1599.         mov     ax,1803h                ; then say XOR the bits
  1600. psete2: call    ega_gc                  ; set controller
  1601.         mov     ax,80                   ; compute starting point in regen buff
  1602.         mul     di
  1603.         mov     di,ax                   ; di = di * 80
  1604.         pop     ax
  1605.         ret
  1606. psetupe endp
  1607.  
  1608. pfine   proc    near                    ; EGA end of plot board cleanup
  1609.         mov     ax,0003h                ; restore write bits directly mode
  1610.         call    ega_gc                  ; set controller
  1611.         ret
  1612. pfine   endp
  1613.  
  1614. pincye  proc    near                    ; EGA inc y
  1615.         add     di,linelen              ; includes sign of deltay
  1616.         ret
  1617. pincye  endp
  1618.  
  1619. pltega  proc    near            ; EGA plot(x,y). x is in si, y is in di
  1620.         rol     bp,1                    ; rotate line pattern
  1621.         jnc     pltega1                 ; nc = no bit to be plotted
  1622.         push    bx
  1623.         push    si
  1624.         push    di
  1625.         mov     bx,si                   ; want si/8 for bytes along line
  1626.         shr     si,1
  1627.         shr     si,1
  1628.         shr     si,1
  1629.         add     di,si                   ; starting point in regen buffer
  1630.         and     bx,0007h                ; leave lower 3 bits for bit in byte
  1631.         mov     bh,masktab[bx]          ; 0-7 into bit mask in byte, x pos
  1632.         mov     bl,ccode                ; get line type code
  1633.         call    ega_plt
  1634.         pop     di
  1635.         pop     si
  1636.         pop     bx
  1637. pltega1:ret
  1638. pltega  endp
  1639.  
  1640. ;;;;;;;;;;;;;;;;;;;;;;;;;; CGA plot support routines
  1641. ; The CGA graphics memory mapping in mode 6 (640 by 200) is 8 dots per byte,
  1642. ; left most dot in the high bit, 80 bytes per scan line, scan line segments
  1643. ; alternating between 0b800h (even lines 0, 2, ...) and 0ba00h (odd lines).
  1644. psetupc proc    near                    ; CGA setup for plotting
  1645.         push    ax
  1646.         push    cx
  1647.         mov     linelen,80              ; 80 bytes per scan line
  1648.         mov     cx,segscn
  1649.         mov     es,cx
  1650.         mov     cx,di                   ; save copy of di, start y line
  1651.                                         ; compute starting point in regen buff
  1652.         shr     di,1                    ; half the lines in each bank
  1653.         mov     ax,80                   ; 80 bytes per line
  1654.         mul     di
  1655.         mov     di,ax                   ; di = di * 80 / 2
  1656.         test    cx,1                    ; even or odd line
  1657.         jz      psetc1                  ; z = even
  1658.         add     di,2000h                ; offset to odd bank (seg 0ba00h)
  1659. psetc1: and     di,3fffh
  1660.         pop     cx
  1661.         pop     ax
  1662.         ret
  1663. psetupc endp
  1664.  
  1665. pincyc  proc    near                    ; CGA inc y
  1666.         cmp     linelen,0               ; increasing or decreasing y?
  1667.         jl      pinyc2                  ; l = decreasing
  1668.         cmp     di,2000h                ; in upper bank now?
  1669.         jb      pinyc1                  ; b = no, in lower bank
  1670.         add     di,linelen              ; add a line
  1671. pinyc1: add     di,2000h                ; switch banks
  1672.         and     di,3fffh                ; roll over address
  1673.         ret
  1674. pinyc2: cmp     di,2000h                ; in upper bank now?
  1675.         jae     pinyc4                  ; ae = yes
  1676.         add     di,linelen              ; subtract a line
  1677. pinyc4: add     di,2000h                ; switch banks
  1678.         and     di,3fffh                ; roll over address
  1679.         ret
  1680. pincyc  endp
  1681.  
  1682. pfinc   proc    near                    ; CGA end of plot board cleanup
  1683.         ret
  1684. pfinc   endp
  1685.  
  1686. pltcga  proc    near            ; CGA plot(x,y). x is in si, y is in di
  1687.         push    bx              ; used for HGA plot also.
  1688.         push    si
  1689.         push    di
  1690.         rol     bp,1                    ; rotate line pattern
  1691.         jnc     pltcg3                  ; nc = no bit to be plotted
  1692.         mov     bx,si                   ; want si/8 for bytes along line
  1693.         shr     si,1
  1694.         shr     si,1
  1695.         shr     si,1
  1696.         add     di,si                   ; starting point in regen buffer
  1697.         and     bx,0007h                ; leave lower 3 bits for bit in byte
  1698.                                         ; di = offset in regen buffer
  1699.         mov     bh,masktab[bx]          ; 0-7 into bit mask in byte. x position
  1700.         mov     bl,ccode                ; get line type code
  1701.         cmp     bl,1                    ; draw the bit?
  1702.         jne     pltcg1                  ; ne = no
  1703.         or      es:[di],bh              ; drawn
  1704.         jmp     short pltcg3
  1705. pltcg1: cmp     bl,0                    ; draw in background (erase)?
  1706.         jne     pltcg2                  ; ne = no
  1707.         not     bh
  1708.         and     es:[di],bh              ; erase the dots
  1709.         jmp     short pltcg3
  1710. pltcg2: xor     es:[di],bh              ; xor in this color
  1711. pltcg3: pop     di
  1712.         pop     si
  1713.         pop     bx
  1714.         ret
  1715. pltcga  endp
  1716. ;;;;;;;;;;;;;;;;;;;;;;;;;; HGA plot support routines
  1717. ; The HGA graphics memory mapping in mode 255 (720 by 348) is 8 dots per byte,
  1718. ; left most dot in the high bit, 90 bytes per scan line, scan line segments
  1719. ; sequence as 0b000h, 0b200h, 0b400h, 0b800h for lines 0-3 and repeat 90 bytes
  1720. ; higher for the rest.
  1721. psetuph proc    near                    ; HGA setup for plotting
  1722.         push    ax
  1723.         push    cx
  1724.         mov     linelen,90              ; for y going down screen by incy
  1725.         mov     ax,segscn               ; base segment of display memory
  1726.         mov     es,ax
  1727.         mov     cx,di                   ; save copy of di, start y line
  1728.                                         ; compute starting point in regen buff
  1729.         shr     di,1                    ; quarter the lines in each bank
  1730.         shr     di,1
  1731.         mov     ax,90
  1732.         mul     di
  1733.         mov     di,ax                   ; di = di * 90 / 4
  1734.         and     cx,3                    ; compute bank from 2 lsb of line num
  1735.         jcxz    pseth2                  ; z means it is in bank 0 (0b000h)
  1736. pseth1: add     di,2000h                ; add offset for each bank
  1737.         loop    pseth1                  ; do cx times
  1738. pseth2: pop     cx
  1739.         pop     ax
  1740.         ret
  1741. psetuph endp
  1742.  
  1743. plthga  proc    near                    ; HGA plot(x,y). x is in si, y is in di.
  1744.         jmp     pltcga                  ; use CGA routine for plotting
  1745. plthga  endp
  1746.  
  1747. pincyh  proc    near                    ; HGA inc y, step offset of line
  1748.         cmp     linelen,0               ; increasing y?
  1749.         jg      pinyh2                  ; g = yes
  1750.         cmp     di,2000h                ; in lowest for four banks?
  1751.         ja      pinyh1                  ; a = no
  1752.         add     di,linelen              ; yes, add a line
  1753. pinyh1: add     di,6000h                ; move back by adding a lot
  1754.         and     di,7fffh                ; roll over address
  1755.         ret
  1756. pinyh2: cmp     di,6000h                ; in top most bank?
  1757.         jb      pinyh4                  ; b = no
  1758.         add     di,linelen              ; yes, first add a line
  1759. pinyh4: add     di,2000h                ; switch to next bank
  1760.         and     di,7fffh                ; roll over address
  1761.         ret
  1762. pincyh  endp
  1763.  
  1764. pfinh   proc    near                    ; HGA end of plot board cleanup
  1765.         ret
  1766. pfinh   endp
  1767.  
  1768. ;;;;;;;;;;;;;;; AT&T-Olivetti Graphics Adapter plot support routines
  1769. ; The OGA graphics memory mapping in mode 48h (640 by 400) is 8 dots per byte,
  1770. ; left most dot in the high bit, 80 bytes per scan line, scan line segments
  1771. ; sequence as 0b800h, 0ba00h, 0bc00h, 0be00h for lines 0-3 and repeat 80 bytes
  1772. ; higher for the rest. Use Hercules line incrementing (inc y) and CGA dot
  1773. ; writing. This is a monographic display.
  1774. psetupo proc    near                    ; OGA setup for plotting
  1775.         push    ax
  1776.         push    cx
  1777.         mov     linelen,80              ; for y going down screen by incy
  1778.         mov     ax,segscn               ; base segment of display memory
  1779.         mov     es,ax
  1780.         mov     cx,di                   ; save copy of di, start y line
  1781.                                         ; compute starting point in regen buff
  1782.         shr     di,1                    ; quarter the lines in each bank
  1783.         shr     di,1
  1784.         mov     ax,80
  1785.         mul     di
  1786.         mov     di,ax                   ; di = di * 80 / 4
  1787.         and     cx,3                    ; compute bank from 2 lsb of line num
  1788.         jcxz    pseto2                  ; z means it is in bank 0 (0b800h)
  1789. pseto1: add     di,2000h                ; add offset for each bank
  1790.         loop    pseto1                  ; do cx times
  1791. pseto2: pop     cx
  1792.         pop     ax
  1793.         ret
  1794. psetupo endp
  1795.  
  1796. ;;;;;;;;;;;;;;;;;;; Monochrome, simulate dots with text char
  1797. psetupm proc    near
  1798.         mov     linelen,1               ; 80 characters but one line
  1799.         ret
  1800. psetupm endp
  1801.  
  1802. pltmon  proc    near                    ; Monochrome dot plot
  1803.         mov     x_coord,si              ; put dot at row=di, col=si, PC Coord
  1804.         mov     y_coord,di
  1805.         push    ax
  1806.         mov     al,'+'
  1807.         call    mputc                   ; display text char
  1808.         pop     ax
  1809.         ret
  1810. pltmon  endp
  1811.  
  1812. pincym  proc    near                    ; Monochrome inc y
  1813.         add     di,linelen              ; includes sign
  1814.         ret
  1815. pincym  endp
  1816.  
  1817. pfinm   proc    near                    ; Monochrome end of plot cleanup
  1818.         ret
  1819. pfinm   endp
  1820.  
  1821. ; GPUTC - a routine to send text characters from font to true graphics boards
  1822. ; such as EGA, Hercules or CGA. Char is in al.
  1823.  
  1824. gputc   proc    near
  1825.         cmp     al,' '                  ; control character?
  1826.         jae     gputc1                  ; ae = no, display the char
  1827.         jmp     putctrl                 ; else handle controls at putctrl
  1828. gputc1: push    bx                      ; first save some registers
  1829.         push    cx
  1830.         push    es
  1831.         push    di
  1832.         mov     bl,al                   ; now BL has char to be displayed
  1833.         and     bl,7fh                  ; no high bits allowed here
  1834.                                         ; set board mode
  1835.         mov     di,y_coord              ; get current y coord (char bottom)
  1836.         sub     di,8                    ; start 8 lines higher
  1837.         jnc     gputc2                  ; nc = ok
  1838.         mov     di,0                    ; move up to first line
  1839.         mov     y_coord,8               ; and reset scan line indicator
  1840. gputc2: call    psetup          ; enter with di=line number, sets es:di to
  1841.                                 ; start of line in display buf and
  1842.                                 ; sets byte-wide plot mode
  1843.         mov     ax,x_coord              ; compute regen buffer byte
  1844.         shr     ax,1                    ; want x_coord/8 for bytes along line
  1845.         shr     ax,1
  1846.         shr     ax,1
  1847.         add     di,ax                   ; byte in regen buffer
  1848.         xor     bh,bh
  1849.         sub     bx,32                   ; characters in font start at 32
  1850.         shl     bx,1
  1851.         shl     bx,1                    ; 8 bytes per char - hence * 8
  1852.         shl     bx,1
  1853.         mov     cx,8                    ; 8 bytes (scan lines) to transfer
  1854.         cmp     graph_mode,cga          ; CGA. medium color display and board?
  1855.         je      gputc4                  ; e = yes
  1856.         cmp     graph_mode,hercules     ; Hercules?
  1857.         je      gputc4                  ; e = yes
  1858.         cmp     graph_mode,olivetti     ; AT&T-Olivetti?
  1859.         je      gputc4                  ; e = yes
  1860.  
  1861. gputc3: mov     al,font[bx]             ; EGA byte plot: get bits from font
  1862.         push    bx
  1863.         mov     bh,0ffh                 ; write these bits to clear field
  1864.         mov     bl,0                    ; in background coloring
  1865.         call    ega_plt                 ; plot a byte
  1866.         mov     bh,al                   ; set bit pattern of character
  1867.         mov     bl,1                    ; plot in foreground colors this time
  1868.         call    ega_plt                 ; byte plot routine for EGA systems
  1869.         pop     bx
  1870.         inc     bx                      ; next byte of char pattern
  1871.         call    pincy                   ; next scan line
  1872.         loop    gputc3
  1873.         jmp     short gputx
  1874.  
  1875. gputc4: mov     al,font[bx]             ; Non-EGA systems: get bits from font
  1876.         mov     es:[di],al              ; write desired pattern (no overwrite)
  1877.         inc     bx                      ; point to next byte of char pattern
  1878.         call    pincy                   ; inc to next line (linelen is preset)
  1879.         loop    gputc4                  ; and repeat 'til complete
  1880. gputx:  call    incx                    ; move to next char position
  1881.         pop     di
  1882.         pop     es
  1883.         pop     cx
  1884.         pop     bx
  1885.         ret
  1886. gputc   endp
  1887.  
  1888. putctrl proc    near                    ; CONTROL CHARS = cursor movement
  1889.         cmp     al,FF                   ; formfeed?
  1890.         jne     putct0                  ; ne = no
  1891.         call    TEKCLS                  ; FF clears the screen
  1892.         ret
  1893. putct0: cmp     al,BS                   ; BS? sends (logical) cursor back one
  1894.         jne     putct2                  ; ne = no, try next
  1895.         mov     ax,x_coord
  1896.         sub     ax,8                    ; so delete 8 dots (move left)
  1897.         jns     putct1                  ; ns = non-negative
  1898.         mov     ax,0                    ; but not less than 0
  1899. putct1: mov     x_coord,ax              ; and replace x coordinate
  1900.         mov     al,' '                  ; send a space
  1901.         call    putc
  1902.         sub     x_coord,8               ; restore cursor
  1903.         ret
  1904. putct2: cmp     al,tab                  ; tabs move forward one char position
  1905.         jne     putct4                  ; ne = not a tab
  1906.         mov     ax,x_coord
  1907.         add     ax,8                    ; so add 8
  1908.         cmp     ax,xmax                 ; zero if off edge of screen
  1909.         jbe     putct3
  1910.         mov     x_coord,0
  1911.         mov     al,lf
  1912.         jmp     short putct5            ; process our new line feed
  1913. putct3: mov     x_coord,ax
  1914.         ret
  1915. putct4: cmp     al,cr                   ; <CR> means go to beginning of line
  1916.         jne     putct5
  1917.         mov     x_coord,0               ; zero the x coordinate
  1918.         ret
  1919. putct5: cmp     al,lf                   ; <LF> means go down 8 pixels (1 line)
  1920.         jne     putct7                  ; ne = not LF
  1921.         add     y_coord,8               ; border managed by outscrn and incx
  1922.         ret
  1923. putct7: cmp     al,vt                   ; <VT> move up screen 1 line (8 pixels)
  1924.         jne     putctx
  1925.         sub     y_coord,8               ; - so subtract 8
  1926.         jnc     putctx                  ; nc = space left
  1927.         mov     y_coord,8               ; else set to top of screen
  1928. putctx: ret
  1929. putctrl endp
  1930.  
  1931. mputc   proc    near                    ; MONO put char in AL via Bios
  1932.         push    ax                      ; updates x_coord,y_coord with
  1933.         push    bx                      ; new cursor position
  1934.         push    cx
  1935.         push    dx
  1936.         mov     ah,0                    ; marker for cursor setting not needed
  1937.         cmp     al,' '                  ; control code?
  1938.         jae     mputc1                  ; ae = no, printable
  1939.         call    putctrl                 ; do cursor arithmetic
  1940.         mov     ah,1                    ; marker to set cursor but no display
  1941.  
  1942. mputc1: push    ax                      ; save char and marker
  1943.         mov     cl,3                    ; char cell is 8 x 8 dots
  1944.         mov     ax,x_coord              ; get resulting cursor PC positions
  1945.         shr     ax,cl
  1946.         mov     dl,al                   ; column
  1947.         mov     ax,y_coord
  1948.         sub     ax,8                    ; minus 8 dots, like other modes
  1949.         jnc     mputc2                  ; nc = non-negative
  1950.         mov     ax,0                    ; else start at the top
  1951.         mov     y_coord,8               ; here too
  1952. mputc2: shr     ax,cl
  1953.         mov     dh,al                   ; row
  1954.         mov     ah,2                    ; set cursor to x_coord,y_coord
  1955.         mov     bh,0                    ; page 0
  1956.         int     screen
  1957.         pop     ax
  1958.         cmp     ah,0                    ; write a char in al?
  1959.         jne     mputcx                  ; ne = no
  1960.         mov     ah,09h                  ; write char at cursor postion
  1961.         mov     cx,1                    ; just one char
  1962.         mov     bh,0                    ; page 0
  1963.         mov     bl,gfcol                ; foreground coloring
  1964.         int     screen
  1965.         inc     dl                      ; next column
  1966.         mov     ah,2                    ; set real cursor ahead of last char
  1967.         int     screen
  1968.         call    incx                    ; move logical cursor
  1969. mputcx: pop     dx
  1970.         pop     cx
  1971.         pop     bx
  1972.         pop     ax
  1973.         ret
  1974. mputc   endp
  1975.  
  1976. incx    proc    near                    ; move the logical cursor right
  1977.         mov     ax,x_coord              ; shift the (logical) cursor right
  1978.         add     ax,8                    ;  one character cell
  1979.         mov     x_coord,ax
  1980.         cmp     ax,xmax                 ; at end of the line?
  1981.         jbe     incx1                   ; b = no
  1982.         mov     x_coord,0               ; wrap to next line
  1983.         add     y_coord,8               ; next row
  1984.         mov     ax,ybot                 ; last scan line
  1985.         cmp     ax,y_coord              ; below bottom line?
  1986.         jge     incx1                   ; ge = no
  1987.         mov     y_coord,ax              ; set to bottom row
  1988.         mov     al,lf                   ; simulate a line feed operation
  1989.         call    outscrn                 ; invoke More message
  1990. incx1:  ret
  1991. incx    endp
  1992.  
  1993. ; routines to manipulate ega graphics controller and mode register
  1994. ; command code in al, value in ah - destroys al and dx
  1995.  
  1996. ega_gc  proc    near                    ; ega graphics controller
  1997.         mov     dx,3ceh
  1998.         out     dx,al                   ; output command code
  1999.         inc     dx                      ; dx is now data port
  2000.         mov     al,ah                   ; get value to al
  2001.         out     dx,al                   ; output value
  2002.         ret
  2003. ega_gc  endp
  2004. ega_md  proc    near                    ; ega mode controller
  2005.         mov     dx,3c4h
  2006.         out     dx,al                   ; output command code
  2007.         inc     dx                      ; dx is now data port
  2008.         mov     al,ah                   ; get value to al
  2009.         out     dx,al                   ; output value
  2010.         ret
  2011. ega_md endp
  2012.  
  2013. ; Plot eight pixels using an EGA board
  2014. ; Enter with ES:[DI] pointing to screen address of byte,
  2015. ; bh has pattern of bits to be set, bl has attributes:
  2016. ;  0 = draw in background color, 1 = draw in foreground color,
  2017. ;  0ffh = XOR with current dot colors.
  2018. ; registers preserved
  2019.  
  2020. ega_plt proc    near
  2021.         push    ax
  2022.         push    dx
  2023.         mov     al,8                    ; command to set bit mask register
  2024.         mov     ah,bh                   ; get bits to be modified (1)
  2025.         call    ega_gc                  ; unprotect those bit positions
  2026.         mov     ah,gfcol                ; get foreground colour
  2027.         cmp     bl,1                    ; draw in foreground?
  2028.         je      ega2                    ; ne = no
  2029.         mov     ah,gbcol                ; get grahics background colour
  2030.         cmp     bl,0ffh                 ; do an XOR?
  2031.         jne     ega2                    ; ne = no
  2032.         mov     ah,0ffh                 ; XOR, touch all color bits
  2033. ega2:   mov     al,es:[di]              ; latch byte
  2034.         mov     es:[di],ah              ; set the byte
  2035.         pop     dx
  2036.         pop     ax
  2037.         ret
  2038. ega_plt endp
  2039.  
  2040. ; routine to set Hercules card to graphics mode - only page 0 is
  2041. ; enabled and used
  2042.  
  2043. HGRAF   PROC    NEAR
  2044.         push    ax
  2045.         push    bx                      ; save used registers
  2046.         push    cx
  2047.         push    si
  2048.         mov     al,grph                 ; graph mode
  2049.         lea     si,gtable               ;  requires graphics table
  2050.         mov     bx,0
  2051.         mov     cx,4000h                ; clear 4000h words
  2052.         call    setmd                   ; and set the mode
  2053.         pop     si
  2054.         pop     cx
  2055.         pop     bx
  2056.         pop     ax
  2057.         ret
  2058. HGRAF   ENDP
  2059.  
  2060. ; set Hercules card to text mode
  2061.  
  2062. HTEXT   PROC    NEAR
  2063.         push    ax
  2064.         push    bx
  2065.         push    cx
  2066.         push    si
  2067.         mov     al,text                 ; text mode
  2068.         lea     si,ttable               ; requires text table
  2069.         mov     bx,0720h                ; blank value (space, white on black)
  2070.         mov     cx,2000                 ; whole screen to clear (80*25)
  2071.         call    setmd                   ; set the mode
  2072.         pop     si
  2073.         pop     cx
  2074.         pop     bx
  2075.         pop     ax
  2076.         ret
  2077. HTEXT   ENDP
  2078.  
  2079. ; Hercules mode set - called from HTEXT and HGRAF
  2080.  
  2081. SETMD   PROC    NEAR
  2082.         push    dx
  2083.         push    ax
  2084.         mov     dx,config               ; configuration port
  2085.         mov     al,genable              ; allow graphics mode to be set
  2086.         out     dx,al
  2087.         pop     ax
  2088.         push    ax
  2089.         push    cx                      ; save count
  2090.         mov     dx,cntrl                ; control port
  2091.         out     dx,al                   ; set to text or graphics
  2092.         mov     dx,index                ; send 12 bytes from table to 6845
  2093.         mov     cx,12                   ; number of registers to load
  2094.         xor     ah,ah                   ; start with register 0 of 6845
  2095.         cld
  2096. setmd1: jmp     $+2                     ; small pause for hardware
  2097.         mov     al,ah                   ; ah is counter
  2098.         out     dx,al                   ; set register
  2099.         inc     dx                      ; point to data port
  2100.         lodsb                           ; get next byte in table
  2101.         jmp     $+2                     ; small pause for hardware
  2102.         out     dx,al                   ; and send to 6845
  2103.         inc     ah                      ; next register
  2104.         dec     dx                      ; point to register port
  2105.         loop    setmd1                  ; and continue 'til cx=0
  2106.         pop     cx                      ; recover count
  2107.         cld
  2108.         push    di
  2109.         push    es
  2110.         mov     ax,segscn               ; start of screen
  2111.         mov     es,ax
  2112.         xor     di,di
  2113.         mov     ax,bx                   ; get blanking character
  2114.         rep     stosw                   ; store blanking char in whole screen
  2115.         pop     es
  2116.         pop     di
  2117.         mov     dx,cntrl                ; now to re-enable screen
  2118.         pop     ax                      ; get mode
  2119.         or      al,scrn_on              ; enable screen
  2120.         out     dx,al
  2121.         pop     dx
  2122.         ret
  2123. SETMD   ENDP
  2124.  
  2125. teksave proc    near            ; saves graphics screen from page 0 to page 1
  2126.         push    si
  2127.         push    di
  2128.         cmp     gpage,0         ; only graphics page 0 on display board?
  2129.         je      teksavx         ; e = yes, no saving possible here
  2130.         mov     si,segscn       ; segment (!) of current screen
  2131.         cmp     graph_mode,ega
  2132.         je      teksav1
  2133.         cmp     graph_mode,monoega
  2134.         je      teksav1
  2135.         cmp     graph_mode,colorega
  2136.         je      teksav1
  2137.         cmp     graph_mode,hercules
  2138.         je      teksav2
  2139.         jmp     short teksavx   ; else nothing
  2140. teksav1:mov     di,segega+800h  ; EGA page 1 screen segment
  2141.         call    egasr           ; call common save/restore code
  2142.         jmp     short teksavx
  2143. teksav2:mov     di,seghga+800h  ; Hercules page 1 screen segment
  2144.         call    hgasr           ; call common save/restore code
  2145. teksavx:pop     di
  2146.         pop     si
  2147.         ret
  2148. teksave endp
  2149.  
  2150. tekrest proc    near            ; saves graphics screen of page 0 in page 1
  2151.         push    si
  2152.         push    di
  2153.         cmp     gpage,0         ; only graphics page 0 on display board?
  2154.         jne     tekres0         ; ne = no, more so work to do here
  2155.         call    tekcls1         ;  else clear the screen to color it
  2156.         jmp     short tekresx   ;  and exit
  2157. tekres0:mov     di,segscn       ; segment (!) of new graphics screen
  2158.         cmp     graph_mode,ega
  2159.         je      tekres1
  2160.         cmp     graph_mode,monoega
  2161.         je      tekres1
  2162.         cmp     graph_mode,colorega
  2163.         je      tekres1
  2164.         cmp     graph_mode,hercules
  2165.         je      tekres2
  2166.         jmp     short tekresx   ; else nothing
  2167. tekres1:mov     si,segega+800h  ; segment of EGA page 1
  2168.         call    egasr           ; call common save/restore code
  2169.         jmp     short tekresx
  2170. tekres2:mov     si,seghga+800h  ; segment of Hercules page 1
  2171.         call    hgasr           ; call common save/restore code
  2172. tekresx:pop     di
  2173.         pop     si
  2174.         ret
  2175. tekrest endp
  2176.  
  2177.  
  2178. egasr   proc    near            ; common code for Tek ega save/restore ops
  2179.         push    ax
  2180.         push    cx
  2181.         push    dx
  2182.         mov     ax,0f00h        ; enable 4 plane set/resets
  2183.         call    ega_gc          ; set controller
  2184.         mov     ax,0f01h        ; enable Set/Reset register
  2185.         call    ega_gc
  2186.         mov     ax,0f02h        ; set color compare register for 4 planes
  2187.         call    ega_gc
  2188.         mov     ax,0905h        ; set mode reg: write latches, read mode
  2189.         call    ega_gc
  2190.         mov     ax,0ff02h       ; enable all planes
  2191.         call    ega_md
  2192.         mov     cx,ybot         ; last scan line
  2193.         inc     cx              ; number of scan lines
  2194.         mov     ax,80           ; bytes per scan line
  2195.         mul     cx
  2196.         mov     cx,ax
  2197.         push    es              ; save es
  2198.         push    ds              ; save ds
  2199.         mov     es,di           ; destination, set es to video memory
  2200.         mov     ds,si           ; source, set ds to video memory
  2201.         xor     si,si           ; clear offset fields
  2202.         xor     di,di
  2203.         cld
  2204.         rep     movsb           ; copy from page [si] to page [di]
  2205.         pop     ds              ; recover ds
  2206.         pop     es              ; and other registers
  2207.         mov     ax,0000h        ; disable 4 plane set/resets
  2208.         call    ega_gc          ; set controller
  2209.         mov     ax,0001h        ; disable Set/Reset register
  2210.         call    ega_gc          ; set controller
  2211.         mov     ax,0002h        ; disable color compare register
  2212.         call    ega_gc
  2213.         mov     ax,1005h        ; set mode reg: write latches, odd/even
  2214.         call    ega_gc
  2215.         pop     dx
  2216.         pop     cx
  2217.         pop     ax
  2218.         ret
  2219. egasr   endp
  2220.  
  2221. hgasr   proc    near            ; Hercules save restore screen
  2222.         push    cx
  2223.         mov     cx,4000h        ; number of words to move
  2224.         push    es              ; save es
  2225.         push    ds              ; save ds
  2226.         mov     es,di           ; destination, set es to video memory
  2227.         mov     ds,si           ; source, set ds to video memory
  2228.         xor     si,si           ; clear offset fields
  2229.         xor     di,di
  2230.         cld
  2231.         rep     movsw           ; copy from page [si] to page [di]
  2232.         pop     ds              ; recover ds
  2233.         pop     es              ; and other registers
  2234.         pop     cx
  2235.         ret
  2236. hgasr   endp
  2237. code    ends
  2238.         end
  2239.  
  2240.