home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / msr313src.zip / msgibm.asm < prev    next >
Assembly Source File  |  1993-07-12  |  237KB  |  7,302 lines

  1.      Name msgibm
  2. ; File MSGIBM.ASM
  3.     include mssdef.h
  4. ;       Copyright (C) 1982,1993, Trustees of Columbia University in the
  5. ;       City of New York.  Permission is granted to any individual or
  6. ;       institution to use, copy, or redistribute this software as long as
  7. ;       it is not sold for profit and this copyright notice is retained.
  8. ; Tektronix emulator for use with MS Kermit/IBM.
  9. ; Edit history:
  10. ; 2 June 1993 version 3.13
  11. ; 6 Sept 1991 version 3.11
  12. ; 2 March 1991 version 3.10
  13. ; Last edit 2 June 1993
  14. ; June 1993 store EGA images in expanded memory if available and if used
  15. ;  for screen rollback.
  16. ; March 1993 Read GRight font from Code Page DOS file EGA.CPI, add CP850
  17. ;  compressed font.
  18. ; Feb 1992 Add DG 470 color graphics, cursor, etc.
  19. ; Dec 1992 Add DG compressed fonts, line, bar, etc graphics support.
  20. ; August 1992 Add beginnings of Data General D463 support.
  21. ; 12 Nov 1990 Add text cursor symbol, and on 17 Nov add cursor on/off.
  22. ; 2 Nov 1990 Add Microsoft mouse direct support.
  23. ; 8 June 1989 Added Wyse-700 support from Mikko Laanti.
  24. ; 21 Nov 1988 Version 2.32
  25. ; 1 Nov 1987 Heavy rewrite to integrate code into regular MS Kermit/IBM
  26. ;  material. [jrd]
  27. ;==============================================================================
  28. ; Original version for TI Pro computers by
  29. ; 12-Dec-84  Joe Smith, CSM Computing Center, Golden CO 80401
  30. ; adapted to IBM PC June 1987 by    Brian Holley,
  31. ;                    Faculty of Economics and Politics
  32. ;                    University of Cambridge, England
  33. ;                    Email: BJH6@UK.AC.CAM.PHX
  34. ; Upgraded and integrated into MS Kermit 2.30 by Joe Doupnik, Utah State Univ.
  35. ;
  36. ;           Description of Tektronix commands
  37. ;
  38. ; ESC CONTROL-E (ENQ) requests a status report
  39. ; ESC FORMFEED erases the screen.
  40. ; ESC CONTROL-X turns on bypass mode (ignore incoming characters).
  41. ; ESC CONTROL-Z turns on the crosshairs (not on 4006 or 4025)
  42. ; ESC 2  exit Tek submode for text mode (ignore if doing full Tek)
  43. ; ESC ? is replaced by DEL code, to assist line plots with 7 bit systems.
  44. ; ESC [ Pn ; Pn m  set screen colors. Pn = 30 + sum of colors for foregnd,
  45. ;  40 + sum of colors for background, Pn = 0 sets b/w, Pn = 1 for high
  46. ;  intensity. Colors are red = 1, green = 2, blue = 4.
  47. ; ESC [ ? 3 8 l  exits Tek mode and returns to host text terminal type
  48. ;  (VT102 if none defined yet). This is an extension from DEC VT340's.
  49. ; ESC [ ? 256 n  invokes a screen size report, for Word Perfect. Report is
  50. ;   ESC [ ? 256; height; width; num colors n   where num colors is 0, 1 or
  51. ;   16; report ESC [ ? 24; 80; 0 n  for pure text mono systems.
  52. ; ESC @  through  ESC M  sets default fill pattern as below (1=@...).
  53. ; ESC Z  report terminal type (as VT320)
  54. ; ESC [ 2; 2 $ u  host request color palette report.
  55. ; ESC / xhome;yhome;xwidth;yheight x           draw an empty rectangle
  56. ; ESC / xhome;yhome;xwidth;yheight;pattern y   fill rectangle with pattern
  57. ; ESC / xhome;yhome;xwidth;yheight;pattern z   fill rect with pattern+border
  58. ;  where x/yhome is the lower left Tek corner, xwidth and yheight are the
  59. ;  Tek width and height. All values are decimal numbers.
  60. ;  Patterns 0:use default, 1:solid, 2:grey, 3:left to right slant, 4:right to
  61. ;  left slant, 5:horizontal lines, 6:vertical lines, 7:slanted cross-hatch,
  62. ;  8:vertical cross-hatch, 9:checkerboard; 10:dotted, 11:horiz herringbone,
  63. ;  12:vertical herringbone,13 and above:border without fill. All are tiling
  64. ;  8x8 pixel patterns.
  65. ; ESC / param a, ... ESC / param c  set user definable line drawing pattern
  66. ;  to 16 bit value of param; plot as lsb first.
  67. ; ESC / 2 h or l,  ESC / 9 h or l. h is set, l is reset, 2 is destructive
  68. ;  space and 9 is destructive backspace. Defaults are reset.
  69. ; ESC x  ESC y  ESC z   selects one of these user definable patterns above.
  70. ; ESC P  P1; P2; P3 q string ESC \        a Sixel Graphics command
  71. ;   P1 and P3 ignored, P2 = 0 or 2 means draw 0 bits in background, 1 means
  72. ;    skip them.
  73. ;   string is
  74. ;     sixel chars (3fh..7eh, lower 6 bits+3fh, displayed lsb at the top)
  75. ;     ! Pn sixel char        where Pn is a repeat count
  76. ;     " Pan; Pad; Ph; Pv    raster attributes (all ignored for now)
  77. ;     # Pc; Pu; Px; Py; Pz  coloring as follows
  78. ;    Pc is color palette, 0-255  (note, only 0..15 are predefined)
  79. ;    Pu is color units, 1=HLS, 2=RGB
  80. ;    For Hue Lightness Saturation:
  81. ;        Px = Hue angle, 0-360 degrees. The colors are mapped around
  82. ;        the color wheel in 60 degree segments as Hues:
  83. ;        0-29 deg = blue, 30-89 = magenta (blue + red), 90-149 = red,
  84. ;        150-209 = yellow (red + green), 210-269 = green,
  85. ;        270-329 = cyan (green + blue), 330-359 = blue.
  86. ;        Py = Lightness, 0-100%, Pz = Saturation, 0-100%
  87. ;          Lightness    Sat = 51-100    Sat = 11-50     Sat = 0-10
  88. ;          86-100    bold white    bold white     bold white
  89. ;          71-85        bold hue    bold white     bold white
  90. ;          57-70        bold hue    grey (dim white) grey
  91. ;          43-56        bold hue    dim hue         black
  92. ;          29-42        dim hue        grey         grey
  93. ;          14-28        dim hue        black         black
  94. ;           0-13     black        black         black
  95. ;        Note that Py = Pz = 50 gives the widest spectrum.
  96. ;    For RGB: Px = red, 0-100%, Py = green, 0-100%, Pz = blue, 0-100%
  97. ;        If any color exceeds 50% then the bold bit is turned on for
  98. ;        the ensemble (IBM ega display adapter constraint for RGBi).
  99. ;
  100. ;    Palette registers can be selected by the substring
  101. ;        # Pc    followed by a non-numeric char other than ";"
  102. ;            and Pc is the palette register, 0-255.
  103. ;
  104. ;     $  (dollar sign )     meaning go to left margin
  105. ;     -  (minus)         meaning go to left margin 6 dots down.
  106. ;   This command yields one or more sets of 6 vertically arranged dots. They
  107. ;   are placed starting at the top and left side of the current text cell.
  108. ;   Escape sequences are permitted within string and occur without disruption.
  109. ; CONTROL-] (GS) turns on plot mode, the first move will be with beam off.
  110. ; CONTROL-^ (RS) turns on incremental plot mode. RS space means move pen up
  111. ;  RS P means move pen down, following letters: A, E, D, F, B, J, H, I mean
  112. ;  move right, right and up, up, left and up, left, left and down, down, and
  113. ;  right and down, respectively. Ex: RS <space> J J J  means move three Tek
  114. ;  positions left and down with the pen up (invisibly).
  115. ; CONTROL-UNDERLINE (US) turns off plot mode, as does CR (for all but 4025).
  116. ; CONTROL-X switches from TEKTRONIX sub mode to NORMAL alpha mode but is
  117. ;  ignored if we are emulating a full Tek terminal rather than a sub mode
  118. ;  of DEC or Heath.
  119. ; FF erases screen.
  120. ; ESC letter, where letter is accent grave (`) a..e, sets the line drawing
  121. ;   pattern until reset to solid lines (same as escape accent) by command or
  122. ;   a terminal reset.
  123. ;    ENQ = Control E
  124. ;    ESC = Control [ (left square bracket)
  125. ;    FF = Control L
  126. ;    FS = Control \ (backslash)
  127. ;    GS = Control ] (right square bracket)
  128. ;    RS = Control ^ (caret)
  129. ;    US = Control _ (underscore)
  130. ;
  131. ; The plot commands are characters which specify the absolute position to move
  132. ; the beam.  All moves except the one immediately after the GS character
  133. ; (Control-]) are with a visible trace.
  134. ;
  135. ; For 4010-like devices - The positions are from 0 to 1023 for both X and Y,
  136. ; although only 0 to 780 are visible for Y due to screen geometry.  The screen
  137. ; is 10.23 by 7.80 inches, and coordinates are sent as 1 to 4 characters.
  138. ;
  139. ; For 4014-like devices - The positions are from 0 to 4096, but each movement
  140. ; is a multiple of 4 positions unless the high-resolution LSBXY are sent.  This
  141. ; makes it compatible with the 4010 in that a full sized plot fills the screen.
  142. ;
  143. ; HIX,HIY = High-order 5 bits of position
  144. ; LOX,LOY = Middle-order 5 bits of position
  145. ; LSBXY      = Low-order 2 bits of X + low-order 2 bits of Y (4014 mode)
  146. ;
  147. ; Hi Y      Lo Y      Hi X      LSBXY      Characters sent (Lo-X always sent)
  148. ; ----      ----      ----      -----      ----------------------------------
  149. ; Same      Same      Same      Same                 Lo-X
  150. ; Same      Same      Same      Diff        LSB, Lo-Y,     Lo-X    4014
  151. ; Same      Same      Diff      Same             Lo-Y, Hi-X, Lo-X
  152. ; Same      Same      Diff      Diff        LSB, Lo-Y, Hi-X, Lo-X    4014
  153. ; Same      Diff      Same      Same             Lo-Y,     Lo-X
  154. ; Same      Diff      Same      Diff        LSB, Lo-Y,     Lo-X    4014
  155. ; Same      Diff      Diff      Same             Lo-Y, Hi-X, Lo-X
  156. ; Same      Diff      Diff      Diff        LSB, Lo-Y, Hi-X, Lo-X    4014
  157. ; Diff      Same      Same      Same      Hi-Y,             Lo-X
  158. ; Diff      Same      Same      Diff      Hi-Y, LSB, Lo-Y,     Lo-X    4014
  159. ; Diff      Same      Diff      Same      Hi-Y,         Lo-Y, Hi-X, Lo-X
  160. ; Diff      Same      Diff      Diff      Hi-Y, LSB, Lo-Y, Hi-X, Lo-X    4014
  161. ; Diff      Diff      Same      Same      Hi-Y,         Lo-Y,     Lo-X
  162. ; Diff      Diff      Same      Diff      Hi-Y, LSB, Lo-Y,     Lo-X    4014
  163. ; Diff      Diff      Diff      Same      Hi-y,         Lo-Y, Hi-X, Lo-X
  164. ; Diff      Diff      Diff      Diff      Hi-y, LSB, Lo-Y, Hi-X, Lo-X    4014
  165. ; Offset for byte:          20h    60h  60h   20h     40h
  166. ;
  167. ; Note that LO-Y must be sent if HI-X has changed so that the TEKTRONIX knows
  168. ; the HI-X byte (in the range of 20h-3fh) is HI-X and not HI-Y.     LO-Y must
  169. ; also be sent if LSBXY has changed, so that the 4010 will ignore LSBXY and
  170. ; accept LO-Y.    The LSBXY byte is 60h + MARGIN*10h + LSBY*4 + LSBX. (MARGIN=0)
  171. ;
  172. ;
  173. ;
  174. ; External variable tekflg and calls to tekini, tekemu, tekesc, tekcls:
  175. ; Byte TEKFLG is non-zero when the Tek emulator is active; it is set by the
  176. ; startup code in tekini and is maintained in mszibm. Internal variable
  177. ; inited remembers if we have a graphics screen saved, etc.
  178. ; TEKINI must be called when entering the emulator to establish the graphics
  179. ; screen mode and to calculate the screen dimensions.
  180. ; TEKRINT reinitialize complete emulator.
  181. ; TEKESC is called from say mszibm.asm to invoke Tek emulation when the
  182. ; external procedures have detected an Escape Control-L sequence. An implicit
  183. ; initialization is done if necessary.
  184. ; TEKEMU is the normal entry point to pass a received character to the emulator.
  185. ; It too will do an implicit initialization, if required.
  186. ; TEKCLS clears the graphics screen, but only if the emulator is active.
  187. ; The emulator remains active during Connect mode Help, Status, and other
  188. ; interrupts which do not change the terminal type.
  189.  
  190.      
  191.     public    tekemu,tekini,tekrint,tekend,tekgraf ; Terminal emulation
  192.         public    tekdmp, tekinq, tekpal, tekrpal    ; used by mszibm file
  193.     public    chcontrol, tekcursor, tekgcptr        ; used by msyibm file
  194.     public    ttxtchr,ttxtline, dgline, dgbar, teksetcursor, tekremcursor
  195.     public    cursorst, croshair, dgcrosson, dgcrossoff, dgcrossrpt
  196.     public    dgsetcrloc, dgarc, dgpoly, savegoff, saveglen, cspb2
  197.  
  198. ENQ    equ    05h            ; ^E ENQ for TEK enquiries
  199. CAN    equ    18h            ; ^X to return to ANSI mode
  200. ESCZ    equ    1Ah            ; SUB, ESC-^Z triggers crosshairs
  201. VT    equ    0Bh            ; ^K go up one line
  202. CR    equ    0Dh
  203. FS    equ    1Ch            ; ^\ for point plot mode
  204. GS    equ    1Dh            ; ^] draw line (1st move is invisible)
  205. RS    equ    1Eh                   ; ^^ for incremental line plot mode
  206. US    equ    1Fh            ; ^_ (underscore) returns to text mode
  207. accent    equ    60h            ; accent grave
  208.  
  209. txtmode    equ    4            ; text mode for TEKTRONIX status
  210. maxtekx equ    1024            ; horizontal and
  211. maxteky equ    780            ; vertical resolution of TEK 4010
  212.      
  213. screen    equ    10h            ; IBM Bios screen call
  214.      
  215. uparr    equ    72            ; DOS scan codes for arrow keys
  216. dnarr    equ    80
  217. lftarr    equ    75
  218. rgtarr    equ    77
  219. homscn    equ    71            ; DOS home screen scan code
  220. shuparr    equ    '8'            ; ascii codes for shifted arrows
  221. shdnarr    equ    '2'
  222. shlftarr equ    '4'
  223. shrgtarr equ    '6'
  224. mouse    equ    33h            ; Microsoft mouse interrupt
  225. msread    equ    3            ; mouse, read status and position
  226. mswrite    equ    4            ; mouse, set position
  227. mshoriz    equ    7            ; mouse, set min/max horizontal motion
  228. msvert    equ    8            ; mouse, set min/max vertical motion
  229. msgetbf    equ    21            ; mouse, get state buffer size
  230. msgetst    equ    22            ; mouse, get mouse state to buffer
  231. mssetst    equ    23            ; mouse, set mouse state from buffer
  232. msreset    equ    33            ; mouse, software reset
  233.  
  234.                     ; Graph_mode for different systems:
  235. cga    equ    6            ; highest resolution mode for CGA
  236. mono    equ    7            ; real monochrome display adapter
  237. colorega equ    14            ; Low-res mode, color EGA
  238. monoega equ    15            ; mono ega needs mode 15
  239. ega    equ    16            ; Hi-res mode - EGA
  240. olivetti equ    72            ; Olivetti's Hi-res - 50 lines text
  241. toshiba    equ    74h            ; Toshiba T3100, like Olivetti
  242. vaxmate    equ    0D0h            ; DEC VAXmate II, like Olivetti
  243. wyse700 equ    0D3h            ; Wyse-700 1280 * 400
  244. hercules equ    255            ; pseudo mode for Hercules graphics
  245. ; Note: IBM VGA modes 17 & 18, 640 by 480, can be used by setting "ega" above
  246. ; to 17 or 18 and modifying ybot to be 479 and ymult to be 48 at label tekin5.
  247. ; The code will scale everything appropriately for the new screen size, but
  248. ; there will be insufficient memory to retain the entire graphics image.
  249. ; Manual override SET TERMINAL GRAPHICS VGA accomplishes these two steps.
  250. ;
  251. ; Note: WYSE-700 mode 1024 * 780 and 1280 * 800 can be set only by
  252. ; manual override SET TERMINAL GRAPHICS WYSET or WYSEA, respectively.
  253. ; No automatic sensing for Wyse.
  254.  
  255. ;; tekflg bits in byte
  256. ;tek_active equ    1            ; actively in graphics mode
  257. ;tek_tek equ    2            ; Tek terminal
  258. ;tek_dec equ    4            ; Tek submode of DEC terminals
  259. ;tek_sg    equ    8            ; special graphics mode
  260.  
  261. segega    equ    0a000h            ; segments of display memory, EGA,VGA
  262. segcga    equ    0b800h            ; CGA, AT&T/Olivetti and relatives
  263. seghga    equ    0b000h            ; HGA
  264. segmono    equ    0b000h            ; Monochrome
  265. segwyse equ    0a000h            ; wyse-700, both banks start from here
  266.                     ; Wyse equates:
  267. wystoff equ    03ddh            ; set bank start offset
  268. wystseg equ    03deh            ; set bank start base
  269. wymode    equ    03dfh            ; register to select mode & bank
  270. wybeven equ    0c8h            ; mask for R/W even bank
  271. wybodd    equ    0cbh            ; mask for R/W odd bank
  272.  
  273.                     ; Hercules equates:
  274. index    equ    03b4h            ; 6845 index register
  275. cntrl    equ    03b8h            ; Display mode control port
  276. hstatus    equ    03bah            ; status port
  277. scrn_on equ    8            ; bit to turn screen on
  278. grph    equ    2            ; graphics mode
  279. text    equ    20h            ; text mode
  280. config    equ    03bfh            ; configuration port
  281. genable equ    1+2            ; enable graphics (1) on two pages (2) 
  282. rgbbold    equ    80            ; nor/bold threshold for RGB intensity
  283. hiy    equ    1            ; codes for Tek graphics components
  284. loy    equ    2
  285. hix    equ    4
  286. lox    equ    3
  287. ; maxparam and maxinter must agree with the prime equ's in file mszibm.asm
  288. maxparam equ    10            ; number of ESC and DCS Parameters
  289. maxinter equ    10            ; number of ESC and DCS Intermediates
  290.  
  291.                     ; Pixel basic operation codes
  292. pixor    equ    1            ; write as foreground OR current dot
  293. pixbak    equ    2            ; write as absolute background color
  294. pixxor    equ    4            ; write as foreground XOR current dot 
  295. pixfor    equ    8            ; write absolute foreground color
  296.  
  297. emsint    equ    67h            ; EMS interrupt
  298. xmspresent equ    4300h            ; EMS presence check for XMS mgr
  299. emsmgrstat equ    40h            ; EMS get manager status
  300. emsgetseg equ    41h            ; EMS get segment of page frame
  301. emsgetnpgs equ    42h            ; EMS get number free pages
  302. emsalloc equ    43h            ; EMS get handle and allocate memory
  303. emsmapmem equ    44h            ; EMS map memory
  304. emsrelease equ    45h            ; EMS release mapped memory
  305. emsgetver equ    46h            ; EMS get version number
  306. emssetname equ    5301h            ; EMS LIM 4, set name
  307.  
  308. data    segment
  309.     extrn    flags:byte, rxtable:byte, vtemu:byte, vtcpage:word
  310.     extrn    tv_mode:byte, yflags:byte, low_rgt:byte, tekflg:byte
  311.     extrn    param:word, nparam:word, inter:byte, ninter:word, lparam:byte
  312.     extrn    parstate:word, pardone:word, parfail:word
  313.     extrn    dnparam:word, dparam:word, dlparam:byte, dninter:word
  314.     extrn    dinter:byte, dcsstrf:byte, emubufc:word, emubuf:byte
  315.     extrn    emubufl:word, ttyact:byte, vtclear:byte, cursor:word
  316.     extrn    dgwindcomp:byte, atctype:byte, dgcross:byte, scbattr:byte
  317.     extrn    rdbuf:byte, decbuf:byte, curattr:byte, dosnum:word
  318.     extrn    parmsk:byte, flowon:byte, flowoff:byte, flowcnt:byte
  319.     extrn    emsrbhandle:word, emsgshandle:word
  320.  
  321. ; required for Hercules screen handling
  322.      
  323. gtable    db    35h,2dh,2eh,7        ; bytes for 6845 controller
  324.     db    5bh,2,57h,57h        ; - graphics mode
  325.     db    2,3,0,0
  326.      
  327. ttable    db    61h,50h,52h,0fh        ; bytes for 6845 controller
  328.     db    19h,6,19h,19h        ; - text mode
  329.     db    2,0dh,0bh,0ch
  330.  
  331. attlogo    db    'OLIVETTI'        ; Olivetti M24/28, AT&T 6300 rom id
  332. attllen    equ    $-attlogo        ; length
  333. toshlogo db    '  TT33110000  TTOOSSHHIIBBAA' ; Toshiba T3100 logo
  334. toshlen    equ    $-toshlogo        ; length
  335. declogo    db    'Copyright Digital Equipment Corp' ; DEC VAXmate
  336. declen    equ    $-declogo
  337. dumpname db    'TEKPLT.TIF',0        ; dump name
  338. dumplen    equ    $-dumpname
  339. dhandle    dw    -1            ; dump file handle
  340. emsgsname db    'KERMIT  ',0        ; 8 byte EMS region name, + safety
  341. emsseg    dw    0            ; segment of ems memory
  342. emsbytes dw    0            ; pixel bytes in ems storage
  343. ;;;;;;;;;;;;;;; start session save area
  344.     even
  345. savegoff label    word
  346.  
  347. ttstate    dw    tektxt            ; state machine control pointer
  348. prestate dw    0            ; previous state, across interruptions
  349. visible db    0            ; 0 to move, 1 to draw a line
  350. tek_hiy dw    0            ; Y coordinate in Tektronix mode
  351. tek_loy db    0
  352. tek_hix dw    0            ; X coordinate in Tektronix mode
  353. tek_lox db    0
  354. tek_lsb db    0            ; Low-order 2 bits of X + low Y
  355.                     ;    (4014 mode)
  356. status    db    0
  357. lastc    db    0            ; last x/y coord fragment seen       
  358. bnkchan db    0            ; a flag so we can select which bank
  359.                     ; to write in Wyse 1280*800 mode
  360. colpal    db    0,9,0ch,0ah        ; VT340 color palette table, IRGB
  361.     db    0dh,0bh,0eh,7, 8,1,4,2, 5,3,6,0fh ; 16 bytes, active table
  362.     db    256-($-colpal) dup (0)    ; to make 256 entries overall
  363. coldef    db    0,9,0ch,0ah, 0dh,0bh,0eh,7, 8,1,4,2, 5,3,6,0fh ; color def
  364. mondef    db    0,7 dup (0fh), 8 dup (7) ; monochrome default "colors"
  365. havepal    db    0            ; 1 if have selected palette
  366. masktab db    80h,40h,20h,10h,8,4,2,1 ; quicker than calculations!
  367.                     ; dashed line patterns
  368. linetab    dw    0ffffh            ; ESC accent    11111111 11111111
  369.     dw    0aaaah            ; ESC a        10101010 10101010
  370.     dw    0f0f0h            ; ESC b        11110000 11110000
  371.     dw    0fafah            ; ESC c        11111010 11111010
  372.     dw    0ffcch            ; ESC d        11111111 11001100
  373.     dw    0fc92h            ; ESC e        11111100 10010010
  374.     dw    0ffffh            ; ESC x    user defined
  375.     dw    0ffffh            ; ESC y user defined
  376.     dw    0ffffh            ; ESC z user defined
  377. linepat    dw    0ffffh            ; active line pattern, from above
  378. ginlpsave dw    0            ; saved linepat while in GIN mode
  379.  
  380. tekid    db    escape,'[?63;1;2;4;8;9;15c',0; VT320, level 3, etc
  381. ;End of init data
  382.  
  383.     even
  384. xmult    dw    1            ; scaling factor for x is
  385. xdiv    dw    1            ;     xmult/xdiv
  386. ymult    dw    1            ; scaling factor for y is
  387. ydiv    dw    1            ;     ymult/ydiv
  388. xmax    dw    640-8            ;
  389. ybot    dw    350-1            ;
  390. x_coord dw    0            ; Tek text char X coordinate
  391. y_coord dw    0            ; Tek text char Y coordinate
  392. xcursor    dw    0            ; PC x_coord of text cursor symbol
  393. ycursor    dw    0            ; PC y_coord of text cursor symbol
  394. save_xcor dw    0            ; save with save-screen
  395. save_ycor dw    0            ; ditto
  396. xcross    dw    0            ; crosshair coordinates
  397. ycross    dw    0
  398. xcenter    dw    0            ; center of screen
  399. ycenter    dw    0            ; center of screen
  400. crossactive db    0            ; non-zero if crosshair is active
  401. tekcursor db    1            ; show text cursor (non-zero)
  402. cursorst db    0            ; cursor state (non-zero is displayed)
  403. oldx    dw    0            ; Tek coordinates of last point
  404. oldy    dw    767            ;  initially top left
  405. scalex    dw    0            ; PC coord for scaled x value
  406. scaley    dw    0            ;  for scaled y value
  407. rectx1    dw    0            ; Rectangle PC x lower left corner
  408. recty1    dw    0            ; Rectangle PC y lower left corner
  409. rectx2    dw    0            ; Rectangle PC x width
  410. recty2    dw    0            ; Rectangle PC y height
  411. angle    dw    0,0            ; arc worker area
  412. dgxmax    dw    640-1            ; DG 470
  413. dgymax    dw    480-1
  414. ;dgxmax    dw    800-1            ; DG 463
  415. ;dgymax    dw    576-1
  416.  
  417. numlines dw    0            ; number of lines to fill
  418. charhgt    dw    8            ; scan lines per character
  419. charwidth dw    8            ; dots across character cell
  420. fontlptr dd    font            ; pointer to high bit clear char fonts
  421. fontrptr dd    font            ; pointer to high bit set char fonts
  422. dotbuf    db    16 dup (0)        ; buffer to hold char dot pattern
  423. fontfile db    'EGA.CPI',0        ; DOS Code Page file, ASCIIZ
  424. havefont dw    0            ; holds Code Page if have GRight font
  425. curcharw dw    8            ; char width of cursor font
  426. curgcol dw    0            ; last used colors of cursor
  427.                     ; area fill material
  428. fill    db    0            ; current fill byte pattern
  429. fillptr    dw    filpat1            ; pointer to current fill pattern
  430. fillist    dw    filpat1,filpat2,filpat3,filpat4,filpat5,filpat6,filpat7
  431.     dw    filpat8,filpat9,filpat10,filpat11,filpat12,filpat13
  432.     dw    filpat14
  433. numfil    equ    ($-fillist)/2        ; number of fill patterns
  434.     ; fill patterns, 8 bits wide, first byte is at top of PC screen
  435.     ; 8 bytes per pattern for 8 scan line repetition
  436. filpat1    db    8 dup (0ffh)        ; solid fill
  437. filpat2    db    4 dup (0aah, 55h)    ; grey (alternating dots)
  438. filpat3    db    80h,01h,02h,04h, 08h,10h,20h,40h ; right to left slant up
  439. filpat4    db    80h,40h,20h,10h, 08h,04h,02h,01h ; left to right slant up
  440. filpat5 db    2 dup (0,0,0aah,0)    ; horizontal lines
  441. filpat6    db    8 dup (44h)        ; vertical lines
  442. filpat7    db    80h,41h,22h,14h, 08h,14h,22h,41h   ; slanted crosshatch
  443. filpat8    db    2 dup (0aah,80h,80h,80h)  ; vertical crosshatch
  444. filpat9    db    4 dup (0f0h), 4 dup (0fh) ; checkerboard
  445. filpat10 db    4 dup (44h, 11h)    ; dots
  446. filpat11 db    2 dup (10h,28h,44h,82h)    ; horizontal herringbone
  447. filpat12 db    80h,40h,20h,10h,08h,10h,20h,40h ; vertical herringbone
  448. filpat13 db    8 dup (0ffh)        ; first user definable fill
  449. filpat14 db    8 dup (0ffh)        ; second user definable fill
  450.                     ; end of area fill material
  451. defcurpat db    0ffh,6 dup (81h),0ffh    ; 8x8 def Tek cursor
  452. dgcurupat db    11 dup (0),0ffh,0ffh,0,0; D463/470 cursor underline pattern
  453. dgcurbpat db    0,12 dup (0ffh),0    ; D463/470 cursor block pattern
  454. dgctype    db    0            ; D463/470 last written cursor type
  455. curmode    db    0            ; screen mode before graphics
  456. tekgraf    db    0        ; Tek graphics board selection (def=auto)
  457.                 ; local variables for LINE plotting routine
  458. graph_mode db    0            ; graphics video mode, default is none
  459. inited    db    0            ; non-zero if inited (retains page)
  460. tekident db    0            ; Tek ident request flag
  461. gpage    db    0            ; display adapter graphics page
  462. gfcol    db    15            ; graphics foreground color
  463. gbcol    db    0            ; graphics background color
  464. tfcol    db    0            ; temp foreground color
  465. tbcol    db    0            ; temp background color
  466. colortb    db    0,4,2,6,1,5,3,7        ; color reversed-bit setting bytes
  467. ccode    db    pixfor            ; temp for holding plot color code
  468. bypass    db    0            ; GIN mode bypass condition (0=off)
  469. esctype    db    0            ; first char after ESCAPE char
  470. bscontrol db    0            ; non-zero for destructive BS
  471. spcontrol db    0            ; non-zero for destructive SPACE
  472. chcontrol db    0            ; char-writing, 1=opaque,0=transparent
  473.     even
  474. putc    dw    mputc            ; ptr to plot a character routine
  475. psetup    dw    psetupm            ; ptr to plot setup routine
  476. pincy    dw    pincym            ; ptr to inc y routine
  477. plotptr    dw    pltmon            ; ptr to dot plot routine
  478. gfplot    dw    bpltmon            ; ptr to area-fill plot routine
  479. segscn    dw    0b800h            ; actual screen segment to use
  480. linelen    dw    0            ; offset increment between scan lines
  481. temp    dw    0
  482.  
  483. saveglen dw    ($-savegoff)        ; length of z save area
  484. ;;;;;;;;;;;;;;;;; end of session save area
  485.  
  486. ten    dw    10            ; word 10 for multiplying
  487. mousebuf dw    0            ; segment of mouse save buffer
  488.  
  489. ; TIFF version 5.0 data fields
  490. ; Reference: Aldus/Microsoft Technical Memorandum dated 8/8/88
  491.                     ; TIFF data item size indicators
  492. uchar    equ    1            ; unsigned byte
  493. ascii    equ    2            ; asciiz string byte
  494. integer    equ    3            ; 16 bit unsigned integer
  495. long    equ    4            ; 32 bit unsigned integer
  496. rational equ    5            ; 32 bit numerator, 32 bit denominator
  497.  
  498. entry    struc                ; 12 byte image file directory entries
  499.     dw    ?            ; tag
  500.     dw    integer            ; type, of data item
  501. entcnt    dd    1            ; length, count of data items
  502. entval    dw    0            ; long value or long offset to value
  503.     dw    0
  504. entry    ends
  505.     
  506.     even                ; TIFF 5.0,  8 byte header
  507. header    dw    4949h            ; 'll', low byte stored first
  508.     dw    42            ; TIFF identification, 42 decimal
  509.     dw    nentry-header,0        ; long offset to image file directory
  510.                     ; Image File Directory
  511. nentry    dw    entrycnt        ; number of entries to follow
  512.                     ; 12-byte directory entries
  513. newsub    entry    <0feh,long>        ; new subfield type
  514. iwidth    entry    <100h,integer>        ; image width,  integer for WP 5
  515. ilength entry    <101h,integer>        ; image length, integer for WP 5
  516. bps    entry    <102h,,,4>         ; bits per sample, 4=iRGB, 1=B/W
  517. comp    entry    <103h,,,1>        ; compression, none
  518. photo     entry    <106h,,,3>        ; photometric interpret, palette 
  519. strip     entry    <111h,long,25,stripoff-header> ; offset to long strip offsets
  520. spp    entry    <115h,,,1>        ; samples/pixel, 1
  521. rps    entry    <116h,long,1,25>    ; long rows per strip
  522. sbc    entry    <117h,integer,25,stripbc-header> ; offset to strip byte counts
  523. xres    entry    <11ah,rational,1,xresval-header> ; x axis resolution
  524. yres    entry    <11bh,rational,1,yresval-header> ; y axis resolution
  525. resunit entry    <128h,integer,1,1>    ; resolution unit, no absolute units
  526. soft    entry    <131h,ascii,proglen,prog-header> ; software ident
  527. stamp    entry    <132h,ascii,dtlen,dandt-header>  ; date and time stamp
  528. cmap    entry    <140h,integer,3*16,colmap-header> ; palette color map
  529. entrycnt equ    ($-nentry-2+11)/12    ; compute number of entries for nentry
  530.     dd    0            ; long offset of next directory (none)
  531.                     ; supporting data pointed at above
  532. prog    db    'MS Kermit 300',0    ; originating program, asciiz
  533. proglen equ    $-prog
  534. dandt    db    '1989:12:25 00:00:01',0    ; date and time format
  535. dtlen    equ    $-dandt
  536. xresval dw    0,0,1,0            ; two double words (top / bottom)
  537. yresval dw    0,0,1,0            ; two double words (top / bottom)
  538. stripoff dd    25 dup (0)        ; long file offset for each strip
  539. stripbc dw    25 dup (0)        ; integer byte count for each strip
  540.     ; color map for red, green, blue; index by IRGB bits from ega sample
  541. colmap    dw    4 dup (0), 4 dup (007ffh), 4 dup (0), 4 dup (0ffffh) ; red
  542.     dw    2 dup (0,0,007ffh,007ffh), 2 dup (0,0,0ffffh,0ffffh) ; green
  543.     dw    2 dup (0,007ffh,0,007ffh), 2 dup (0,0ffffh,0,0ffffh) ; blue
  544. tifflen equ    $-header         ; length of header + directory + info
  545. pixdata equ    $              ; pixel data start here on disk
  546.                     ; end of TIFF information
  547.  
  548. esctab    db    33            ; table of ESC <char> dispatches
  549.     dw    escjmp            ; address of table for action routines
  550.     db    ENQ,FF,CAN,CTLZ,'/'            ; ^E,^L,^X,^Z,/
  551.     db    '@ABCD','EFGHI','JKLM'
  552.     db    3fh,'PZ[\'                ; '?PZ[\'
  553.     db    60h,'abcde','fghij','klmno','xyz'    ; accent, a..o,x,y,z
  554.  
  555. ; Dispatch for esctab table
  556.     even
  557. escjmp    dw    tekenq, tekcls,tekcan, tekgin,tekeseq    ; ^E,^L,^X,^Z,/
  558.     dw    14 dup (tekfill)            ; '@ABCDEFGHIJKLM'
  559.     dw    tekqury,tekeseq,sendid,tekeseq,tekgotst ; '?PZ[\'
  560.     dw    19 dup (teklpat)            ; accent, a..o,x,y,z
  561.  
  562. ; Final char table for ANSI escape sequences
  563. anstab    db    21            ; number of entries
  564.     dw    ansjmp            ; address of action routines
  565.     db    '@ABCD','EFGHJ','KXade','fhlmn','u'
  566.  
  567. ; Dispatch for anstab table
  568.     even
  569. ansjmp    dw    ansich, atcuu,   atcud,   atcuf,  atcub        ; '@ABCD'
  570.     dw    atcnl,  atcpl,   atcha,   atcup,  ated        ; 'EFGHJ'
  571.     dw    atel,   atech,   atcuf,   atcva,  atcud        ; 'KXade'
  572.     dw    atcup,  escexit, escexit, tekcol, tekrid    ; 'fhlmn'
  573.     dw    tekprpt                        ; 'u'
  574. data    ends
  575.  
  576. data1    segment
  577.  
  578. ; 8*8 font for Hercules and such, CGA, and EGA
  579. ; - allows 43 lines, and 80 (90 for Hercules) chars per line.
  580. ; all printing (?) characters from <space> to <del> - two characters per line
  581. ; 8 bits per scan line, top line given first, 8 scan lines.    
  582. font    db    0,0,0,0,0,0,0,0,           18h,18h,18h,18h,18h,0,18h,0
  583.     db    6ch,6ch,6ch,0,0,0,0,0,           36h,36h,7fh,36h,7fh,36h,36h,0
  584.     db    0ch,3fh,68h,3eh,0bh,7eh,18h,0, 60h,66h,0ch,18h,30h,66h,06h,0
  585.     db    38h,6ch,6ch,38h,6dh,66h,3bh,0, 0ch,18h,30h,0,0,0,0,0
  586.     db    0ch,18h,30h,30h,30h,18h,0ch,0, 30h,18h,0ch,0ch,0ch,18h,30h,0
  587.     db    0,18h,7eh,3ch,7eh,18h,0,0,     0,18h,18h,7eh,18h,18h,0,0
  588.     db    0,0,0,0,0,18h,18h,30h,           0,0,0,7eh,0,0,0,0
  589.     db    0,0,0,0,0,18h,18h,0,           0,06h,0ch,18h,30h,60h,0,0
  590.     db    3ch,66h,6eh,7eh,76h,66h,3ch,0, 18h,38h,18h,18h,18h,18h,7eh,0
  591.     db    3ch,66h,06h,0ch,18h,30h,7eh,0, 3ch,66h,06h,1ch,06h,66h,3ch,0
  592.     db    0ch,1ch,3ch,6ch,7eh,0ch,0ch,0, 7eh,60h,7ch,06h,06h,66h,3ch,0
  593.     db    1ch,30h,60h,7ch,66h,66h,3ch,0, 7eh,06h,0ch,18h,30h,30h,30h,0
  594.     db    3ch,66h,66h,3ch,66h,66h,3ch,0, 3ch,66h,66h,3eh,06h,0ch,38h,0
  595.     db    0,0,18h,18h,0,18h,18h,0,       0,0,18h,18h,0,18h,18h,30h
  596.     db    0ch,18h,30h,60h,30h,18h,0ch,   0,0,0,7eh,0,7eh,0,0,0
  597.     db    30h,18h,0ch,06h,0ch,18h,30h,   0,3ch,66h,0ch,18h,18h,0,18h,0
  598.     db    3ch,66h,6eh,6ah,6eh,60h,3ch,   0,3ch,66h,66h,7eh,66h,66h,66h,0
  599.     db    7ch,66h,66h,7ch,66h,66h,7ch,   0,3ch,66h,60h,60h,60h,66h,3ch,0
  600.     db    78h,6ch,66h,66h,66h,6ch,78h,   0,7eh,60h,60h,7ch,60h,60h,7eh,0
  601.     db    7eh,60h,60h,7ch,60h,60h,60h,   0,3ch,66h,60h,6eh,66h,66h,3ch,0
  602.     db    66h,66h,66h,7eh,66h,66h,66h,   0,7eh,18h,18h,18h,18h,18h,7eh,0
  603.     db    3eh,0ch,0ch,0ch,0ch,6ch,38h,   0,66h,6ch,78h,70h,78h,6ch,66h,0
  604.     db    60h,60h,60h,60h,60h,60h,7eh,   0,63h,77h,7fh,6bh,6bh,63h,63h,0
  605.     db    66h,66h,76h,7eh,6eh,66h,66h,   0,3ch,66h,66h,66h,66h,66h,3ch,0
  606.     db    7ch,66h,66h,7ch,60h,60h,60h,   0,3ch,66h,66h,66h,6ah,6ch,36h,0
  607.     db    7ch,66h,66h,7ch,6ch,66h,66h,   0,3ch,66h,60h,3ch,06h,66h,3ch,0
  608.     db    7eh,18h,18h,18h,18h,18h,18h,   0,66h,66h,66h,66h,66h,66h,3ch,0
  609.     db    66h,66h,66h,66h,66h,3ch,18h,   0,63h,63h,6bh,6bh,7fh,77h,63h,0
  610.     db    66h,66h,3ch,18h,3ch,66h,66h,   0,66h,66h,66h,3ch,18h,18h,18h,0
  611.     db    7eh,06h,0ch,18h,30h,60h,7eh,   0,7ch,60h,60h,60h,60h,60h,7ch,0
  612.     db    0,60h,30h,18h,0ch,06h,0,0,     3eh,06h,06h,06h,06h,06h,3eh,0
  613.     db    18h,3ch,66h,42h,0,0,0,0,       0,0,0,0,0,0,0,0ffh
  614.     db    30h,18h,0ch,0,0,0,0,0,           0,0,3ch,06h,3eh,66h,3eh,0
  615.     db    60h,60h,7ch,66h,66h,66h,7ch,0, 0,0,3ch,66h,60h,66h,3ch,0
  616.     db    06h,06h,3eh,66h,66h,66h,3eh,0, 0,0,3ch,66h,7eh,60h,3ch,0
  617.     db    0eh,18h,18h,3ch,18h,18h,18h,0, 0,0,3eh,66h,66h,3eh,06h,3ch
  618.     db    60h,60h,7ch,66h,66h,66h,66h,0, 18h,0,38h,18h,18h,18h,3ch,0
  619.     db    18h,0,38h,18h,18h,18h,18h,70h, 60h,60h,66h,6ch,78h,6ch,66h,0
  620.     db    38h,18h,18h,18h,18h,18h,3ch,0, 0,0,76h,7fh,6bh,6bh,63h,0
  621.     db    0,0,7ch,66h,66h,66h,66h,0,     0,0,3ch,66h,66h,66h,3ch,0
  622.     db    0,0,7ch,66h,66h,7ch,60h,60h,0, 0,3eh,66h,66h,3eh,06h,07h
  623.     db    0,0,6ch,76h,60h,60h,60h,0,     0,0,3eh,60h,3ch,06h,7ch,0
  624.     db    30h,30h,7ch,30h,30h,30h,1ch,0, 0,0,66h,66h,66h,66h,3eh,0
  625.     db    0,0,66h,66h,66h,3ch,18h,0,     0,0,63h,6bh,6bh,7fh,36h,0
  626.     db    0,0,66h,3ch,18h,3ch,66h,0,     0,0,66h,66h,66h,3eh,06h,3ch
  627.     db    0,0,7eh,0ch,18h,30h,7eh,0,     0ch,18h,18h,70h,18h,18h,0ch,0
  628.     db    18h,18h,18h,0,18h,18h,18h,0,   30h,18h,18h,0eh,18h,18h,30h,0
  629.     db    31h,6bh,46h,0,0,0,0,0,           0ffh,6 dup (81h),0ffh
  630.     ; note, the last 8 bytes comprise the text cursor symbol pattern
  631.  
  632.     ; 5x14 font cell, space is on the left, 4 dot descender region
  633. fivedot    db    14 dup (0)                    ; 0 null
  634.     db    0,0,0,70h,88h,0d8h,88h,0d8h,0a8h,70h,0,0,0,0    ; 1 happy face
  635.     db    0,0,0,70h,0f8h,0a8h,0f8h,0a8h,0d8h,70h,0,0,0,0    ; 2 happy face
  636.     db    0,0,0,0d8h,4 dup (0f8h),70h,20h,0,0,0,0        ; 3 heart
  637.     db    0,0,0,20h,70h,0f8h,0f8h,70h,70h,20h,0,0,0,0    ; 4 diamond
  638.     db    0,0,0,70h,20h,0a8h,0f8h,0a8h,20h,20h,0,0,0,0    ; 5 club
  639.     db    0,0,0,20h,70h,0f8h,0f8h,0a8h,20h,20h,0,0,0,0    ; 6 spade
  640.     db    4 dup (0),20h,70h,70h,70h,20h,5 dup (0)        ; 7 dot
  641.     db    5 dup (0f8h),0d8h,98h,98h,0d8h,5 dup (0f8h)    ; 8 floppy
  642.     db    4 dup (0),20h,50h,98h,98h,50h,20h,0,0,0,0    ; 9 circle
  643.     db    4 dup (0f8h),0d8h,0a8h,70h,70h,0a8h,0d8h,4 dup (0f8h) ; 10
  644.     db    0,0,0,18h,8,20h,50h,98h,50h,20h,0,0,0,0        ; 11 male
  645.     db    5 dup (0),20h,50h,98h,50h,20h,20h,70h,20h,0    ; 12 female
  646.     db    0,0,0,30h,28h,20h,20h,20h,0e0h,0c0h,0,0,0,0    ; 13 note
  647.     db    0,0,0,40h,70h,50h,70h,50h,0d0h,0d0h,30h,30h,0,0    ; 14 notes
  648.     db    0,0,20h,98h,20h,70h,70h,20h,98h,20h,0,0,0,0    ; 15 sun
  649.     db    0,0,0,40h,60h,70h,78h,70h,60h,40h,0,0,0,0    ; 16 rt arrow
  650.     db    0,0,0,8,18h,38h,78h,38h,18h,8,0,0,0,0        ; 17 lft arrow
  651.     db    0,20h,50h,98h,20h,20h,20h,98h,50h,20h,0,0,0,0    ; 18 t/b arrow
  652.     db    0,0,6 dup (50h),0,50h,0,0,0,0            ; 19 dbl bang
  653.     db    0,0,0,78h,0a8h,0a8h,68h,28h,28h,28h,0,0,0,0    ; 20 paragraph
  654.     db    0,20h,50h,40h,20h,50h,20h,10h,50h,20h,0,0,0,0     ; 21 section
  655.     db    5 dup (0),70h,70h,7 dup (0)            ; 22 bar
  656.     db    0,20h,50h,98h,20h,20h,20h,98h,50,20h,0,0f8h,0,0    ; 23 arrow,bar
  657.     db    0,20h,50h,98h,6 dup (20h),0,0,0,0        ; 24 up arrow
  658.     db    0,0,5 dup (20h),98h,50h,20h,0,0,0,0        ; 25 dn arrow
  659.     db    0,0,0,20h,10h,0e8h,10h,20h,6 dup (0)        ; 26 rt arrow
  660.     db    0,0,0,20h,40h,0b8h,40h,20h,6 dup (0)        ; 27 lf arrow
  661.     db    5 dup (0),40h,40h,78h,6 dup (0)            ; 28
  662.     db    4 dup (0),50h,98h,50h,7 dup (0)            ; 29
  663.     db    4 dup (0),20h,70h,0f8h,7 dup (0)        ; 30 up triang
  664.     db    4 dup (0),0f8h,70h,20h,7 dup (0)        ; 31 dn traing
  665.     db    14 dup (0)                    ; space
  666.     db    0,0,20h,20h,20h,20h,20h,0,20h,0,0,0,0,0        ; !
  667.     db    0,0,50h,50h,50h,9 dup (0)            ; "
  668.     db    0,0,50h,50h,0f8h,50h,50h,0f8h,50h,50h,0,0,0,0     ; #
  669.     db    0,20h,30h,60h,40h,60h,30h,30h,60h,20h,0,0,0,0     ; $
  670.     db    0,0,0c0h,0c8h,10h,20h,40h,98h,18h,0,0,0,0,0    ; %
  671.     db    0,20h,50h,70h,20h,68h,90h,90h,90h,68h,0,0,0,0    ; &
  672.     db    0,0,20h,20h,20h,9 dup (0)            ; '
  673.     db    0,0,10h,20h,40h,40h,40h,40h,20h,10h,0,0,0,0    ; (
  674.     db    0,0,40h,20h,10h,10h,10h,10h,20h,40h,0,0,0,0    ; )
  675.     db    0,0,0,20h,0a8h,70h,70h,70h,0a8h,20h,0,0,0,0    ; *
  676.     db    0,0,20h,20h,20h,0f8h,20h,20h,20h,0,0,0,0,0    ; +
  677.     db    8 dup (0),10h,10h,10h,20h,0,0            ; ,
  678.     db    5 dup (0),70h,8 dup (0)                ; -
  679.     db    8 dup (0),20h,20h,0,0,0,0            ; .
  680.     db    0,0,0,0,08h,10h,20h,40h,80h,5 dup (0)        ; /
  681.     db    0,0,78h,48h,48h,58h,68h,48h,48h,78h,0,0,0,0    ; 0
  682.     db    0,0,20h,60h,5 dup (20h),70h,0,0,0,0        ; 1
  683.     db    0,0,70h,50h,10h,30h,60h,40h,40h,70h,0,0,0,0    ; 2
  684.     db    0,0,70h,50h,10h,30h,10h,10h,50h,70h,0,0,0,0    ; 3
  685.     db    0,0,10h,30h,30h,50h,50h,78h,10h,10h,0,0,0,0    ; 4
  686.     db    0,0,70h,40h,40h,70h,10h,10h,50h,70h,0,0,0,0    ; 5
  687.     db    0,0,70h,50h,40h,40h,70h,50h,50h,70h,0,0,0,0    ; 6
  688.     db    0,0,70h,10h,10h,10h,20h,20h,40h,40h,0,0,0,0    ; 7
  689.     db    0,0,70h,50h,50h,70h,50h,50h,50h,70h,0,0,0,0    ; 8
  690.     db    0,0,70h,50h,50h,70h,10h,10h,50h,70h,0,0,0,0    ; 9
  691.     db    0,0,0,20h,20h,0,0,20h,20h,5 dup (0)        ; :
  692.     db    5 dup (0),20h,20h,0,0,20h,20h,40h,0,0        ; ;
  693.     db    0,0,08h,10h,20h,40h,20h,10h,08h,5 dup(0)    ; <
  694.     db    0,0,0,0,70h,0,70h,7 dup (0)            ; =
  695.     db    0,0,40h,20h,10h,08h,10h,20h,40h,5 dup (0)    ; >
  696.     db    0,0,70h,50h,10h,30h,20h,20h,0,20h,0,0,0,0    ; ?
  697.     db    0,0,0,78h,88h,0b8h,0a8h,0b8h,80h,70h,0,0,0,0    ; @
  698.     db    0,0,30h,48h,48h,48h,78h,48h,48h,48h,0,0,0,0    ; A
  699.     db    0,0,70h,50h,48h,70h,50h,48h,48h,70h,0,0,0,0    ; B
  700.     db    0,0,30h,48h,4 dup (40h),48h,30h,0,0,0,0        ; C
  701.     db    0,0,70h,50h,4 dup (48h),50h,70h,0,0,0,0        ; D
  702.     db    0,0,78h,40h,40h,70h,40h,40h,40h,78h,0,0,0,0    ; E
  703.     db    0,0,78h,40h,40h,70h,40h,40h,40h,40h,0,0,0,0    ; F
  704.     db    0,0,30h,48h,40h,40h,58h,48h,48h,38h,0,0,0,0    ; G
  705.     db    0,0,48h,48h,48h,78h,48h,48h,48h,48h,0,0,0,0    ; H
  706.     db    0,0,70h,6 dup (20h),70h,0,0,0,0            ; I
  707.     db    0,0,38h,08h,08h,08h,08h,48h,48h,78h,0,0,0,0    ; J
  708.     db    0,0,48h,48h,50h,60h,60h,50h,50h,48h,0,0,0,0    ; K
  709.     db    0,0,7 dup (40h),70h,0,0,0,0            ; L
  710.     db    0,0,48h,78h,78h,5 dup (48h),0,0,0,0         ; M
  711.     db    0,0,48h,48h,48h,68h,58h,48h,48h,48h,0,0,0,0    ; N
  712.     db    0,0,30h,6 dup (48h),30h,0,0,0,0            ; O
  713.     db    0,0,70h,48h,48h,48h,70h,40h,40h,40h,0,0,0,0    ; P
  714.     db    0,0,30h,48h,48h,48h,48h,58h,58h,30h,10h,0,0,0    ; Q
  715.     db    0,0,70h,48h,48h,70h,50h,50h,48h,48h,0,0,0,0    ; R
  716.     db    0,0,30h,50h,40h,60h,30h,10h,50h,60h,0,0,0,0    ; S
  717.     db    0,0,0f8h,7 dup (20h),0,0,0,0            ; T
  718.     db    0,0,7 dup (48h),78h,0,0,0,0            ; U
  719.     db    0,0,6 dup (48h),30h,30h,0,0,0,0            ; V
  720.     db    0,0,5 dup (48h),78h,78h,48h,0,0,0,0         ; W
  721.     db    0,0,50h,50h,50h,20h,20h,50h,50h,50h,0,0,0,0    ; X
  722.     db    0,0,88h,88h,50h,50h,20h,20h,20h,20h,0,0,0,0    ; Y
  723.     db    0,0,78h,08h,10h,10h,20h,20h,40h,78h,0,0,0,0    ; Z
  724.     db    0,0,70h,6 dup (40h),70h,0,0,0,0            ; [
  725.     db    0,0,0,0,80h,40h,20h,10h,08h,5 dup (0)        ; \
  726.     db    0,0,70h,6 dup (10h),70h,0,0,0,0            ; ]
  727.     db    0,0,20h,50h,88h,9 dup (0)            ; ^
  728.     db    10 dup (0),0f8h,0,0,0                ; _
  729.     db    0,0,40h,60h,10h,9 dup (0)            ; `
  730.     db    5 dup (0),70h,10h,70h,50h,78h,0,0,0,0        ; a
  731.     db    0,0,40h,40h,40h,70h,50h,50h,50h,70h,0,0,0,0    ; b
  732.     db    5 dup (0),70h,50h,40h,50h,70h,0,0,0,0        ; c
  733.     db    0,0,10h,10h,10h,70h,50h,50h,50h,70h,0,0,0,0    ; d
  734.     db    5 dup (0),70h,50h,70h,40h,70h,0,0,0,0        ; e
  735.     db    0,0,30h,20h,20h,70h,20h,20h,20h,20h,0,0,0,0    ; f
  736.     db    5 dup (0),70h,50h,50h,70h,10h,50h,70h,0,0    ; g
  737.     db    0,0,40h,40h,40h,70h,50h,50h,50h,50h,0,0,0,0    ; h
  738.     db    0,0,0,20h,0,60h,20h,20h,20h,70h,0,0,0,0        ; i
  739.     db    0,0,0,10h,0,30h,10h,10h,10h,50h,70h,0,0,0    ; j
  740.     db    0,0,40h,40h,40h,48h,50h,60h,50h,48h,0,0,0,0    ; k
  741.     db    0,0,60h,6 dup (20h),70h,0,0,0,0            ; l
  742.     db    5 dup (0),0d8h,0f8h,0a8h,88h,88h,0,0,0,0    ; m
  743.     db    5 dup (0),0f0h,4 dup (50h),0,0,0,0        ; n
  744.     db    5 dup (0),70h,50h,50h,50h,70h,0,0,0,0        ; o
  745.     db    5 dup (0),70h,50h,50h,50h,70h,40h,40h,0,0    ; p
  746.     db    5 dup (0),70h,50h,50h,50h,70h,10h,10h,0,0    ; q
  747.     db    5 dup (0),58h,60h,40h,40h,40h,0,0,0,0        ; r
  748.     db    5 dup (0),30h,40h,20h,10h,60h,0,0,0,0        ; s
  749.     db    0,0,20h,20h,20h,70h,20h,20h,20h,30h,0,0,0,0    ; t
  750.     db    5 dup (0),4 dup (50h),70h,0,0,0,0        ; u
  751.     db    5 dup (0),50h,50h,50h,20h,20h,0,0,0,0        ; v
  752.     db    5 dup (0),88h,0a8h,0a8h,0a8h,50h,0,0,0,0    ; w
  753.     db    5 dup (0),88h,50h,20h,50h,88h,0,0,0,0        ; x
  754.     db    5 dup (0),4 dup (50h),30h,10h,70h,0,0        ; y
  755.     db    5 dup (0), 70h,10h,20h,40h,70h,0,0,0,0        ; z
  756.     db    0,0,0,30h,20h,20h,60h,20h,20h,30h,0,0,0,0    ; {
  757.     db    0,0,8 dup (20h),0,0,0,0                ; |
  758.     db    0,0,0,60h,20h,20h,30h,20h,20h,60h,0,0,0,0    ; }
  759.     db    0,0,0,40h,0a8h,10h,8 dup (0)            ; ~
  760.     db    0,0,0,20h,50h,98h,98h,98h,0f8h,5 dup (0)    ; 127 DEL
  761.  
  762.                             ; begin CP437 GRight
  763. gr437    db    0,0,30h,48h,40h,40h,40h,40h,48h,30h,10h,70h,0,0    ; Cedillia
  764.     db    0,0,48h,0,0,4 dup (48h),78h,0,0,0,0        ; u umlate
  765.     db    0,0,10h,20h,0,70h,50h,70h,40h,70h,0,0,0,0    ; e accent
  766.     db    0,0,20h,50h,0,70h,10h,70h,50h,78h,0,0,0,0    ; a caret
  767.     db    0,0,0,50h,0,70h,10h,70h,50h,78h,0,0,0,0        ; a umlate
  768.     db    0,0,40h,20h,0,70h,10h,70h,50h,78h,0,0,0,0    ; a accent
  769.     db    0,20h,50h,20h,0,70h,10h,70h,50h,78h,0,0,0,0    ; a ring
  770.     db    5 dup (0),70h,50h,40h,50h,70h,20h,60h,0,0    ; cedillia
  771.     db    0,0,20h,50h,0,70h,50h,70h,40h,70h,0,0,0,0    ; e caret
  772.     db    0,0,0,50h,0,70h,50h,70h,40h,70h,0,0,0,0        ; e umlate
  773.     db    0,0,40h,20h,0,70h,50h,70h,40h,70h,0,0,0,0    ; e accent
  774.     db    0,0,0,50h,0,60h,20h,20h,20h,70h,0,0,0,0        ; i umlate
  775.     db    0,0,20h,50h,0,60h,20h,20h,20h,70h,0,0,0,0    ; i caret
  776.     db    0,0,40h,20h,0,60h,20h,20h,20h,70h,0,0,0,0    ; i accent
  777.     db    0,28h,0,30h,48h,48h,78h,48h,48h,48h,0,0,0,0    ; A umlate
  778.     db    10h,28h,10h,30h,48h,48h,78h,48h,48h,48h,0,0,0,0    ; A ring
  779.  
  780.     db    10h,20h,0,78h,40h,40h,70h,40h,40h,78h,0,0,0,0    ; E accent
  781.     db    5 dup (0),78h,0a8h,0b8h,0d0h,0b8h,0,0,0,0    ; ae
  782.     db    0,0,78h,0a0h,0a0h,0b0h,0a0h,0e0h,0a0h,0b8h,0,0,0,0 ; AE
  783.     db    0,0,20h,50h,0,70h,50h,50h,50h,70h,0,0,0,0    ; o caret
  784.     db    0,0,0,50h,0,70h,50h,50h,50h,70h,0,0,0,0        ; o umlate
  785.     db    0,0,40h,20h,0,70h,50h,50h,50h,70h,0,0,0,0    ; o accent
  786.     db    0,0,20h,50h,0,50h,50h,50h,50h,70h,0,0,0,0    ; u caret
  787.     db    0,0,40h,20h,0,50h,50h,50h,50h,70h,0,0,0,0    ; u accent
  788.     db    0,0,0,50h,0,4 dup (50h),30h,10h,70h,0,0        ; y umlate
  789.     db    0,28h,0,30h,5 dup (48h),30h,0,0,0,0        ; O umlate
  790.     db    0,28h,0,6 dup (48h),78h,0,0,0,0            ; U umlate
  791.     db    0,20h,20h,70h,50h,40h,50h,70h,20h,20h,0,0,0,0    ; cent sign
  792.     db    0,30h,28h,20h,20h,70h,20h,20h,40h,78h,0,0,0,0    ; Sterling
  793.     db    0,0,88h,88h,50h,20h,70h,20h,70h,20h,0,0,0,0    ; Yen
  794.     db    0,0,0e0h,90h,90h,0e0h,80h,90h,0b8h,90h,18h,0,0,0 ; Piaster
  795.     db    0,10h,28h,20h,20h,70h,20h,20h,0c0h,40h,0,0,0,0    ; Florin
  796.  
  797.     db    0,0,10h,20h,0,70h,10h,70h,50h,78h,0,0,0,0    ; a accent
  798.     db    0,0,20h,40h,0,60h,20h,20h,20h,70h,0,0,0,0    ; i accent
  799.     db    0,0,10h,20h,0,70h,50h,50h,50h,70h,0,0,0,0    ; o accent
  800.     db    0,0,10h,20h,0,50h,50h,50h,50h,70h,0,0,0,0    ; u accent
  801.     db    0,0,28h,50h,0,60h,50h,50h,50h,50h,0,0,0,0    ; n tilde
  802.     db    0,28h,50h,0,48h,48h,68h,58h,48h,48h,0,0,0,0    ; N tilde
  803.     db    0,70h,50h,78h,0,78h,8 dup (0)            ; male ord
  804.     db    0,70h,50h,70h,0,78h,8 dup (0)            ; female ord
  805.     db    0,0,10h,0,10h,10h,20h,40h,48h,30h,0,0,0,0    ; inv query
  806.     db    5 dup (0),78h,40h,40h,6 dup (0)            ; inv not
  807.     db    5 dup (0),78h,8,8,6 dup (0)            ; not
  808.     db    40h,40h,48h,50h,20h,78h,88h,18h,20h,38h,0,0,0,0    ; one half
  809.     db    40h,40h,48h,50h,28h,58h,0a8h,48h,78h,10h,0,0,0,0 ; one quarter
  810.     db    0,0,0,20h,0,5 dup (20h),0,0,0,0            ; inv bang
  811.     db    0,0,0,0,28h,50h,0a0h,50h,28h,0,0,0,0,0        ; left chevron
  812.     db    0,0,0,0,0a0h,50h,28h,50h,0a0h,0,0,0,0,0        ; rgt chevron
  813.  
  814.     db    90h,48h,20h,90h,48h,20h,90h,48h,20h,90h,48h,20h,90h,48h
  815.     db    0a8h,50h,0a8h,50h,0a8h,50h,0a8h,50h,0a8h,50h,0a8h,50h,0a8h,50h
  816.     db    48h,0a0h,20h,48h,0a0h,20h,48h,0a0h,20h,48h,0a0h,20h,48h,0a0h
  817.     db    14 dup (30h)
  818.     db    5 dup (30h),0f0h,8 dup (30h)
  819.     db    4 dup (30h),0f0h,30h,30h,0f0h,6 dup (30h)
  820.     db    6 dup (50h),0d0h,7 dup (50h)
  821.     db    6 dup (0),0f0h,7 dup (50h)
  822.     db    4 dup (0),0f0h,30h,30h,0f0h,6 dup (30h)
  823.     db    4 dup (50h),0d0h,50h,50h,0d0h,6 dup (50h)
  824.     db    14 dup (50h)                    ; 186
  825.     db    4 dup (0),0f0h,10h,10h,0d0h,6 dup (50h)
  826.     db    4 dup (50h),0d0h,10h,10h,0f0h,6 dup (0)
  827.     db    5 dup (50h),0f0h,8 dup (0)
  828.     db    4 dup (30h),0f0h,30h,30h,0f0h,6 dup (0)
  829.     db    4 dup (0),0f0h,9 dup (30h)
  830.  
  831.     db    5 dup (30h),038h,8 dup (0)            ; 192
  832.     db    5 dup (30h),0f8h,8 dup (0)
  833.     db    5 dup (0),0f8h,8 dup (30h)
  834.     db    5 dup (30h),38h,8 dup (30h)
  835.     db    5 dup (0),0f8h,8 dup (0)            ; 196
  836.     db    5 dup (30h),0f8h,8 dup (30h)
  837.     db    4 dup (30h),38h,30h,30h,38h,6 dup (30h)
  838.     db    5 dup (50h),58h,8 dup (50h)
  839.     db    4 dup (50h),58h,40h,40h,48h,6 dup (0)
  840.     db    4 dup (0),78h,40h,40h,58h,6 dup (50h)
  841.     db    4 dup (50h),58h,40h,40h,48h,6 dup (0)
  842.     db    4 dup (0),0f0h,0,0,0d8h,6 dup (50h)        ; 202
  843.     db    4 dup (50h),58h,40h,40h,58h,6 dup (50h)
  844.     db    4 dup (0),0f8h,0,0,0f8h,6 dup (0)        ; 205
  845.     db    4 dup (50h),0d8h,0,0,0d8h,6 dup (50h)
  846.     db    5 dup (30h),0f8h,0,0f8h,6 dup (0)
  847.  
  848.     db    5 dup (50h),0f8h,8 dup (0)
  849.     db    4 dup (0),0f8h,0,0,0f8h,6 dup (30h)
  850.     db    5 dup (0),0f8h,8 dup (50h)
  851.     db    5 dup (50h),0f8h,8 dup (0)
  852.     db    4 dup (30h),38h,30h,30h,38h,6 dup (0)
  853.     db    4 dup (0),38h,30h,30h,38h,6 dup (30h)        ; 213
  854.     db    5 dup (0),78h,8 dup (50h)
  855.     db    5 dup (50h),0d8h,8 dup (50h)
  856.     db    4 dup (30h),0f8h,0,0,0f8h,6 dup (30h)
  857.     db    5 dup (30h),0f0h,8 dup (0)
  858.     db    5 dup (0),38h,8 dup (30h)            ; 218
  859.     db    14 dup (0f8h)
  860.     db    7 dup (0),7 dup (0f8h)
  861.     db    14 dup (0e0h)
  862.     db    7 dup (0f8h),7 dup (0)
  863.     db    14 dup (38h)
  864.  
  865.     db    0,0,0,60h,98h,90h,90h,90h,98h,60h,0,0,0,0    ; Alpha
  866.     db    0,0,70h,58h,48h,70h,50h,48h,48h,70h,40h,40h,20h,0 ; Beta
  867.     db    0,0,78h,48h,6 dup (40h),0,0,0,0            ; Gamma
  868.     db    0,0,0,0,0f8h,5 dup (50h),0,0,0,0        ; Pi
  869.     db    0,0,78h,48h,20h,10h,10h,20h,48h,78h,0,0,0,0    ; Sigma
  870.     db    0,0,0,0,78h,90h,90h,90h,90h,60h,0,0,0,0        ; sigma
  871.     db    5 dup (0),4 dup (48h),78h,40h,40h,80h,0        ; mu
  872.     db    0,0,0,50h,0a8h,20h,20h,20h,20h,10h,0,0,0,0    ; tau
  873.     db    0,0,0f8h,20h,70h,98h,98h,70h,20h,0f8h,0,0,0,0    ; Phi
  874.     db    0,0,30h,48h,48h,78h,48h,48h,48h,30h,0,0,0,0    ; Theta
  875.     db    0,0,70h,4 dup (90h),50h,50h,0d8h,0,0,0,0    ; Omega
  876.     db    0,0,70h,48h,20h,50h,98h,98h,98h,70h,0,0,0,0    ; delta
  877.     db    4 dup (0),50h,98h,98h,98h,98h,50h,0,0,0,0    ; infinity
  878.     db    0,0,30h,48h,48h,58h,68h,48h,0c8h,30h,0,0,0,0    ; phi
  879.     db    0,0,18h,20h,40h,78h,40h,40h,20h,18h,0,0,0,0    ; epsilon
  880.     db    0,0,0,30h,6 dup (48h),0,0,0,0            ; intersect
  881.  
  882.     db    0,0,0,70h,0,70h,0,70h,6 dup (0)            ; defined
  883.     db    0,0,20h,20h,70h,20h,20h,0,70h,5 dup (0)        ; +/-
  884.     db    0,40h,20h,10h,8,10h,20h,40h,0,78h,0,0,0,0    ; geq
  885.     db    0,8,10h,20h,40h,20h,10h,8,0,78h,0,0,0,0        ; leq
  886.     db    0,0,30h,48h,48h,40h,40h,20h,20h,5 dup (10h)    ; integral top
  887.     db    4 dup (10h),5 dup (8),48h,48h,30h,0,0        ; integral bot
  888.     db    4 dup (0),10h,0,78h,0,10h,5 dup (0)        ; divide
  889.     db    4 dup (0),28h,50h,0,28h,50h,5 dup (0)        ; approx equ
  890.     db    0,0,30h,48h,48h,48h,30h,7 dup (0)        ; open circle
  891.     db    0,0,30h,78h,78h,78h,30h,7 dup (0)        ; closed circ
  892.     db    4 dup (0),30h,78h,78h,30h,6 dup (0)        ; bullet
  893.     db    0,0,18h,4 dup (10h),0d0h,30h,10h,0,0,0,0    ; sqrt
  894.     db    0,10h,68h,48h,48h,48h,8 dup (0)            ; super n
  895.     db    0,20h,50h,10h,20h,40h,70h,7 dup (0)        ; super 2
  896.     db    4 dup (0),5 dup (30h),5 dup (0)            ; square
  897.     db    14 dup (0)                    ; 255, empty
  898.  
  899.                             ; begin CP850 GRight
  900. gr850    db    0,0,30h,48h,40h,40h,40h,40h,48h,30h,10h,70h,0,0    ; Cedillia
  901.     db    0,0,48h,0,0,4 dup (48h),78h,0,0,0,0        ; u umlate
  902.     db    0,0,10h,20h,0,70h,50h,70h,40h,70h,0,0,0,0    ; e accent
  903.     db    0,0,20h,50h,0,70h,10h,70h,50h,78h,0,0,0,0    ; a caret
  904.     db    0,0,0,50h,0,70h,10h,70h,50h,78h,0,0,0,0        ; a umlate
  905.     db    0,0,40h,20h,0,70h,10h,70h,50h,78h,0,0,0,0    ; a accent
  906.     db    0,20h,50h,20h,0,70h,10h,70h,50h,78h,0,0,0,0    ; a ring
  907.     db    5 dup (0),70h,50h,40h,50h,70h,20h,60h,0,0    ; cedillia
  908.     db    0,0,20h,50h,0,70h,50h,70h,40h,70h,0,0,0,0    ; e caret
  909.     db    0,0,0,50h,0,70h,50h,70h,40h,70h,0,0,0,0        ; e umlate
  910.     db    0,0,40h,20h,0,70h,50h,70h,40h,70h,0,0,0,0    ; e accent
  911.     db    0,0,0,50h,0,60h,20h,20h,20h,70h,0,0,0,0        ; i umlate
  912.     db    0,0,20h,50h,0,60h,20h,20h,20h,70h,0,0,0,0    ; i caret
  913.     db    0,0,40h,20h,0,60h,20h,20h,20h,70h,0,0,0,0    ; i accent
  914.     db    0,28h,0,30h,48h,48h,78h,48h,48h,48h,0,0,0,0    ; A umlate
  915.     db    10h,28h,10h,30h,48h,48h,78h,48h,48h,48h,0,0,0,0    ; A ring
  916.     
  917.     db    10h,20h,0,78h,40h,40h,70h,40h,40h,78h,0,0,0,0    ; E accent
  918.     db    5 dup (0),78h,0a8h,0b8h,0d0h,0b8h,0,0,0,0    ; ae
  919.     db    0,0,78h,0a0h,0a0h,0b0h,0a0h,0e0h,0a0h,0b8h,0,0,0,0 ; AE
  920.     db    0,0,20h,50h,0,70h,50h,50h,50h,70h,0,0,0,0    ; o caret
  921.     db    0,0,0,50h,0,70h,50h,50h,50h,70h,0,0,0,0        ; o umlate
  922.     db    0,0,40h,20h,0,70h,50h,50h,50h,70h,0,0,0,0    ; o accent
  923.     db    0,0,20h,50h,0,50h,50h,50h,50h,70h,0,0,0,0    ; u caret
  924.     db    0,0,40h,20h,0,50h,50h,50h,50h,70h,0,0,0,0    ; u accent
  925.     db    0,0,0,50h,0,4 dup (50h),30h,10h,70h,0,0        ; y umlate
  926.     db    0,28h,0,30h,5 dup (48h),30h,0,0,0,0        ; O umlate
  927.     db    0,28h,0,6 dup (48h),78h,0,0,0,0            ; U umlate
  928.     db    4 dup (0),8h,78h,58h,48h,68h,78h,80h,0,0,0    ; o slash
  929.     db    0,30h,28h,20h,20h,70h,20h,20h,40h,78h,0,0,0,0    ; Sterling
  930.     db    0,0,0,38h,48h,58h,48h,68h,48h,0b0h,0,0,0,0    ; O slash
  931.     db    0,0,0,88h,50h,20h,50h,88h,0,0,0,0,0,0         ; times (x)
  932.     db    0,10h,28h,20h,20h,70h,20h,20h,0c0h,40h,0,0,0,0    ; Florin
  933.  
  934.     db    0,0,10h,20h,0,70h,10h,70h,50h,78h,0,0,0,0    ; a accent
  935.     db    0,0,20h,40h,0,60h,20h,20h,20h,70h,0,0,0,0    ; i accent
  936.     db    0,0,10h,20h,0,70h,50h,50h,50h,70h,0,0,0,0    ; o accent
  937.     db    0,0,10h,20h,0,50h,50h,50h,50h,70h,0,0,0,0    ; u accent
  938.     db    0,0,28h,50h,0,60h,50h,50h,50h,50h,0,0,0,0    ; n tilde
  939.     db    0,28h,50h,0,48h,48h,68h,58h,48h,48h,0,0,0,0    ; N tilde
  940.     db    0,70h,50h,78h,0,78h,8 dup (0)            ; male ord
  941.     db    0,70h,50h,70h,0,78h,8 dup (0)            ; female ord
  942.     db    0,0,10h,0,10h,10h,20h,40h,48h,30h,0,0,0,0    ; inv query
  943.     db    0,0,70h,88h,0f8h,0d8h,0f8h,0d0h,70h,5 dup (0)    ; registered
  944.     db    5 dup (0),78h,8,8,6 dup (0)            ; not
  945.     db    40h,40h,48h,50h,20h,78h,88h,18h,20h,38h,0,0,0,0    ; one half
  946.     db    40h,40h,48h,50h,28h,58h,0a8h,48h,78h,10h,0,0,0,0 ; one quarter
  947.     db    0,0,0,20h,0,5 dup (20h),0,0,0,0            ; inv bang
  948.     db    0,0,0,0,28h,50h,0a0h,50h,28h,0,0,0,0,0        ; left chevron
  949.     db    0,0,0,0,0a0h,50h,28h,50h,0a0h,0,0,0,0,0        ; rgt chevron
  950.  
  951.     db    90h,48h,20h,90h,48h,20h,90h,48h,20h,90h,48h,20h,90h,48h
  952.     db    0a8h,50h,0a8h,50h,0a8h,50h,0a8h,50h,0a8h,50h,0a8h,50h,0a8h,50h
  953.     db    48h,0a0h,20h,48h,0a0h,20h,48h,0a0h,20h,48h,0a0h,20h,48h,0a0h
  954.     db    14 dup (30h)
  955.     db    5 dup (30h),0f0h,8 dup (30h)
  956.     db    10h,20h,0,30h,48h,48h,78h,48h,48h,48h,4 dup (0)    ; A acute
  957.     db    10h,28h,0,30h,48h,48h,78h,48h,48h,48h,4 dup (0)    ; A caret
  958.     db    20h,10h,0,30h,48h,48h,78h,48h,48h,48h,4 dup (0)    ; A grave
  959.     db    0,70h,88h,0a8h,0d8h,0a8h,0d8h,0a8h,88h,70h,4 dup (0);copyright
  960.     db    4 dup (50h),0d0h,50h,50h,0d0h,6 dup (50h)
  961.     db    14 dup (50h)                    ; 184
  962.     db    4 dup (0),0f0h,10h,10h,0d0h,6 dup (50h)
  963.     db    4 dup (50h),0d0h,10h,10h,0f0h,6 dup (0)
  964.     db    0,20h,20h,70h,50h,40h,50h,70h,20h,20h,0,0,0,0    ; cent sign
  965.     db    0,0,88h,88h,50h,20h,70h,20h,70h,20h,0,0,0,0    ; Yen
  966.     db    4 dup (0),0f0h,9 dup (30h)
  967.  
  968.     db    5 dup (30h),0f0h,8 dup (0)
  969.     db    5 dup (30h),0f8h,8 dup (0)
  970.     db    5 dup (0),0f8h,8 dup (30h)
  971.     db    5 dup (30h),38h,8 dup (30h)
  972.     db    5 dup (0),0f8h,8 dup (0)            ; 196
  973.     db    5 dup (30h),0f8h,8 dup (30h)
  974.     db    0,0,28h,50h,0,70h,10h,70h,50h,78h,0,0,0,0    ; a tilde
  975.     db    28h,50h,0,30h,48h,48h,78h,48h,48h,48h,0,0,0,0    ; A tilde
  976.     db    4 dup (50h),58h,40h,40h,48h,6 dup (0)
  977.     db    4 dup (0),78h,40h,40h,58h,6 dup (50h)
  978.     db    4 dup (50h),58h,40h,40h,48h,6 dup (0)
  979.     db    4 dup (0),0f0h,0,0,0d8h,6 dup (50h)        ; 202
  980.     db    4 dup (50h),58h,40h,40h,58h,6 dup (50h)
  981.     db    4 dup (0),0f8h,0,0,0f8h,6 dup (0)        ; 205
  982.     db    4 dup (50h),0d8h,0,0,0d8h,6 dup (50h)
  983.     db    0,88h,0,70h,88h,88h,88h,70h,0,88h,4 dup (0)    ; sun/currency
  984.  
  985.     db    0,0,10h,60h,60h,90h,28h,48h,48h,30h,4 dup (0)    ; Icelandic d
  986.     db    0,0,70h,50h,48h,0e8h,48h,48h,50h,70h,0,0,0,0    ; Icelandic D
  987.     db    20h,50h,0,78h,40h,40h,70h,40h,40h,78h,0,0,0,0    ; E caret
  988.     db    0,28h,0,78h,40h,40h,70h,40h,40h,78h,0,0,0,0    ; E umlate
  989.     db    20h,10h,0,78h,40h,40h,70h,40h,40h,78h,0,0,0,0    ; E accent
  990.     db    3 dup (0),20h,60h,20h,20h,20h,70h,5 dup (0)    ; numeral 1
  991.     db    28h,50h,0,70h,5 dup (20h),70h,0,0,0,0        ; I tilde
  992.     db    20h,50h,0,70h,5 dup (20h),70h,0,0,0,0        ; I caret
  993.     db    0,50h,0,70h,5 dup (20h),70h,0,0,0,0        ; I umlate
  994.     db    5 dup (30h),0f0h,8 dup (0)
  995.     db    5 dup (0),38h,8 dup (30h)            ; 218
  996.     db    14 dup (0f8h)
  997.     db    7 dup (0),7 dup (0f8h)
  998.     db    0,4 dup (20h),0,4 dup (20h),0,0,0,0        ; v bkn bar
  999.     db    20h,10h,0,70h,5 dup (20h),70h,0,0,0,0        ; I grave
  1000.     db    14 dup (38h)
  1001.  
  1002.     db    10h,20h,0,30h,48h,48h,48h,68h,48h,30h,0,0,0,0    ; O acute
  1003.     db    0,0,70h,58h,48h,70h,50h,48h,48h,70h,40h,40h,20h,0 ; Beta
  1004.     db    10h,28h,0,30h,48h,48h,48h,68h,48h,30h,0,0,0,0    ; O caret
  1005.     db    0,0,0,30h,48h,58h,48h,68h,48h,30h,0,0,0,0    ; O slash
  1006.     db    0,0,28h,50h,0,70h,50h,50h,50h,70,0,0,0,0    ; o tilde
  1007.     db    28h,50h,0,30h,48h,48h,48h,68h,48h,30h,0,0,0,0    ; O tilde
  1008.     db    5 dup (0),4 dup (48h),78h,40h,40h,80h,0        ; mu
  1009.     db    0,0,40h,40h,40h,70h,88h,88h,70h,40h,40h,0,0,0    ; Icelandic p
  1010.     db    0,0,40h,40h,70h,48h,48h,48h,70h,40h,40h,0,0,0    ; Icelandic P
  1011.     db    10h,20h,0,6 dup (48h),78h,0,0,0,0        ; U acute
  1012.     db    10h,28h,0,6 dup (48h),78h,0,0,0,0        ; U caret
  1013.     db    20h,10h,0,6 dup (48h),78h,0,0,0,0        ; U grave
  1014.     db    0,10h,20h,0,0,4 dup (50h),30h,10h,70h,0,0    ; y acute
  1015.     db    10h,20h,0,88h,88h,50h,20h,20h,20h,20h,0,0,0,0    ; Y acute
  1016.     db    5 dup (0),70h,8 dup (0)                ; minus sign
  1017.     db    0,0,0,10h,20h,40h,8 dup (0)            ; acute
  1018.  
  1019.     db    5 dup (0),70h,8 dup (0)                ; minus sign
  1020.     db    0,0,20h,20h,70h,20h,20h,0,70h,5 dup (0)        ; +/-
  1021.     db    4 dup (0),70h,0,70h,7 dup (0)            ; equals
  1022.     db    0,0c0h,20h,40h,28h,0dh,28h,0d8h,0a8h,48h,78h,8,8,0 ; 3/4
  1023.     db    0,0,78h,0e8h,0e8h,60h,4 dup (28h),4 dup (0)    ; Paragraph
  1024.     db    30h,40h,20h,70h,50h,50h,20h,10h,60h,0,0,0,0    ; section
  1025.     db    4 dup (0),10h,0,78h,0,10h,5 dup (0)        ; divide
  1026.     db    6 dup (0),18h,18h,60h,5 dup (0)            ; cedilla
  1027.     db    0,0,30h,48h,48h,48h,30h,7 dup (0)        ; open circle
  1028.     db    4 dup (0),50h,50h,8 dup (0)            ; diaerese
  1029.     db    4 dup (0),30h,78h,78h,30h,6 dup (0)        ; bullet
  1030.     db    3 dup (0),20h,60h,20h,20h,20h,70h,5 dup (0)    ; numeral 1
  1031.     db    0,70h,10h,30h,10h,10h,70h,7 dup (0)        ; super 3
  1032.     db    0,20h,50h,10h,20h,40h,70h,7 dup (0)        ; super 2
  1033.     db    4 dup (0),5 dup (30h),5 dup (0)            ; square
  1034.     db    14 dup (0FH)                    ; 255, empty
  1035.  
  1036.  
  1037.         ; 256 * sin(x), 0..89 degrees in steps of 1 degree
  1038. sin    db    0,4,8,13,17,22,26,31,35,40,44,48,53,57,61,66,70,74,79,83,87
  1039.     db    91,95,100,104,108,112,116,120,124,128,131,135,139,143,146,150
  1040.     db    154,157,161,164,167,171,174,177,181,184,187,190,193,196,198
  1041.     db    201,204,207,209,212,214,217,219,221,223,226,228,230,232,233
  1042.     db    235,237,238,240,242,243,244,246,247,248,249,250,251,252,252
  1043.     db    253,254,254,255,255,255,255,255
  1044.  
  1045. data1    ends
  1046.  
  1047. code    segment                    ; main body code segment
  1048.     extrn    outchr:near, beep:near, cmblnk:near
  1049.     extrn    cptchr:near, clrbuf:near, iseof:near, unique:near
  1050.     extrn    pcwait:near, spath:near
  1051.  
  1052.     assume    cs:code, ds:data, es:nothing
  1053.  
  1054. ; These far routines are called by the Tek emulator; they are here to provide
  1055. ; a bridge to the main code segment near procedures.
  1056.      
  1057. ; Procedures for calling to the main body of MS Kermit. Most are FAR and
  1058. ; must be in in code segment named code, not in code2.
  1059.  
  1060. outmodem proc    far            ; send Tek char out serial port
  1061.     push    ax
  1062.     mov    ah,al
  1063.     call    outchr            ; outchr works from ah
  1064.     mov    ax,50            ; 50 millsecond pause
  1065.     call    pcwait
  1066.     pop    ax
  1067.     ret
  1068. outmodem ENDP
  1069.  
  1070. tekbeep    proc    far            ; sound a beep from Tek mode
  1071.     call    beep
  1072.     ret
  1073. tekbeep    endp
  1074.  
  1075. tcmblnk    proc    far            ; blank the screen from Tek mode
  1076.     call    cmblnk
  1077.     ret
  1078. tcmblnk    endp
  1079.  
  1080. tcptchr    proc    far            ; call session logger while in Tek
  1081.     call    cptchr            ;  mode
  1082.     ret
  1083. tcptchr    endp
  1084.  
  1085. tiseof    proc    far            ; call iseof while in Tek mode
  1086.     call    iseof
  1087.     ret
  1088. tiseof    endp
  1089.  
  1090. tunique    proc    far            ; reach to real unique name procedure
  1091.     call    unique            ;  while in Tek mode
  1092.     ret
  1093. tunique    endp
  1094.  
  1095. tekwait    proc    far            ; call pcwait while in Tek mode
  1096.     call    pcwait
  1097.     ret
  1098. tekwait    endp
  1099.  
  1100. ; Return in BX the offset of the master color palette table. Used by SET TERM
  1101. ; GRAPHICS COLOR <color value> to obtain foreground and background colors
  1102. ; in palette slots 7 and 0, resp.
  1103. tekgcptr proc    near
  1104.     mov    tekident,1        ; say this is an ident request
  1105.     call    far ptr tekini        ; do init steps to get screen sizes
  1106.     mov    bx,offset mondef    ; default monochrome colors
  1107.     cmp    plotptr,offset pltcga    ; using CGA style graphics?
  1108.     je    tekgcpt1        ; e = yes
  1109.     cmp    graph_mode,mono        ; pure mono text system?
  1110.     je    tekgcpt1        ; e = yes
  1111.     cmp    graph_mode,monoega    ; ega, but monochrome?
  1112.     je    tekgcpt1        ; e = no
  1113.     mov    bx,offset coldef    ; return offset of color palette
  1114. tekgcpt1:mov    havepal,0        ; say don't have a palette setup
  1115.     mov    tekident,0
  1116.     mov    inited,0
  1117.     ret
  1118. tekgcptr endp
  1119.  
  1120. ; These routines can be called by either the main body or from within Tek
  1121. ; mode.
  1122. tekdmp    proc    near            ; Tek screen dump routine
  1123.     call    far ptr dump        ; callable from main body
  1124.     clc
  1125.     ret
  1126. tekdmp    endp
  1127.  
  1128. fspath    proc    far
  1129.     call    spath
  1130.     ret
  1131. fspath    endp
  1132. code    ends
  1133.  
  1134. code1    segment
  1135.     extrn    scrseg:near, atparse:near, frepaint:far
  1136.     assume    cs:code1
  1137.  
  1138. ; Return screen info for Tek screen report: ax=screen height, bx=width,
  1139. ; cx=number of colors (0=none for pure text, 1=b/w, 16=ega)
  1140. tekinq    proc    near
  1141.     mov    tekident,1        ; say this is an ident request
  1142.     call    far ptr tekini        ; do init steps to get screen sizes
  1143.     mov    ax,ybot            ; lowest screen line
  1144.     inc    ax            ; screen height, in lines
  1145.     mov    bx,xmax
  1146.     add    bx,8            ; screen width, in dots
  1147.     cmp    graph_mode,mono        ; pure text mono (no graphics at all)?
  1148.     jne    tekinq1            ; ne = no
  1149.     mov    ax,24            ; bottom screen line
  1150.     mov    bx,80            ; screen width
  1151.     xor    cx,cx            ; pure mono, say 0 colors
  1152.     jmp    short tekinq2
  1153. tekinq1:mov    cx,1            ; say b/w screen
  1154.     cmp    plotptr,offset pltcga    ; using CGA style graphics?
  1155.     je    tekinq2            ; e = yes
  1156.     cmp    graph_mode,monoega    ; monochrome monitor on ega?
  1157.     je    tekinq2            ; e = yes
  1158.     mov    cx,16            ; say 16 colors
  1159. tekinq2:mov    tekident,0
  1160.     ret
  1161. tekinq    endp
  1162.  
  1163. tparstart proc    far            ; start escape sequence parser
  1164.     mov    parstate,0        ; set to initialize automatically
  1165.     mov    pardone,offset tpardone    ; jmp to this when completed
  1166.     mov    parfail,0        ; no failure case jump
  1167.     ret
  1168. tparstart endp
  1169.  
  1170. tparser    proc    far
  1171.     call    atparse            ; reach to real parser
  1172.     ret
  1173. tparser    endp
  1174.  
  1175. tpardone proc    near            ; called by real parser
  1176.     call    far ptr xpardone
  1177.     ret
  1178. tpardone endp
  1179.  
  1180. tekpal    proc    near            ; do palette report tekrpt
  1181.     call    far ptr tekrpt        ; callable from main body
  1182.     ret
  1183. tekpal    endp
  1184.  
  1185. tekrpal    proc    near            ; restore color palette
  1186.     call    far ptr tekxco4        ; callable from main body
  1187.     ret
  1188. tekrpal endp
  1189.  
  1190. tscrseg    proc    far            ; get video segment while in Tek mode
  1191.     call    scrseg
  1192.     ret
  1193. tscrseg    endp
  1194.  
  1195. code1    ends                ; main body code segment
  1196.  
  1197. ; Code segment code2 is allocated to Tektronix emulation
  1198. code2    segment                ; supplementary code segment
  1199.  
  1200.     assume    cs:code2, ds:data, es:nothing
  1201.  
  1202. cspb2    db    256    dup (0)        ; code2 segment patch buffer
  1203.  
  1204. tekxco4    proc    FAR            ; call local tekgco4, return far
  1205.     call    tekgco4
  1206.     ret
  1207. tekxco4    endp
  1208.  
  1209. ; Initialise TEK mode by setting high resolution screen, etc
  1210. tekini    proc    far
  1211.     push    ax            ; do presence tests
  1212.     push    bx
  1213.     push    cx
  1214.     push    dx
  1215.     push    si
  1216.     push    di
  1217.     push    es
  1218.     cmp    tekident,0        ; just identifying?
  1219.     jne    tekin0            ; ne = yes
  1220.     mov    al,flowoff
  1221.     or    al,al            ; able to do xoff?
  1222.     jz    tekin0            ; z = no
  1223.     call    outmodem        ; tell host xoff while we change modes
  1224. tekin0:    test    tekflg,tek_active    ; active now?
  1225.     jnz    tekin2            ; nz = yes
  1226.     cmp    inited,0        ; inited yet?
  1227.     jne    tekin2            ; ne = yes, use existing coloring
  1228.     mov    ax,linetab        ; get default line pattern
  1229.     mov    linepat,ax        ; init active line pattern
  1230.     mov    fillptr,offset filpat1    ; init active fill pointer
  1231.     cmp    havepal,0        ; have a color palette yet?
  1232.     jne    tekin0a            ; ne = yes
  1233.     mov    bx,vtemu.att_ptr    ; emulator screen color ptr
  1234.     mov    al,[bx]
  1235.     mov    gfcol,al        ; save foreground color
  1236.     and    gfcol,0fh        ; save just foreground bits
  1237.     and    al,70h            ; select background color, no bold
  1238.     mov    cl,4
  1239.     shr    al,cl            ; get background colors
  1240.     mov    gbcol,al        ; set graphics background color
  1241. tekin0a:mov    ah,15            ; get current screen mode
  1242.     int    screen
  1243.     and    al,not 80h        ; strip "preserve regen" bit 80h
  1244.     cmp    al,mono            ; mono text mode (7)?
  1245.     je    tekin1            ; e = yes
  1246.     cmp    tekident,0        ; doing an ident request?
  1247.     jne    tekin2            ; ne = yes, don't mess with screen
  1248. tekin1:    mov    curmode,al        ; save mode here
  1249.     mov    ah,3            ; get cursor position
  1250.     xor    bh,bh            ; page 0
  1251.     int    screen
  1252.  
  1253.                     ; Presence tests.
  1254. tekin2:    mov    graph_mode,cga        ; Color. Assume CGA
  1255.     mov    segscn,segcga        ; assume cga screen segment
  1256.     mov    gpage,0            ; graphics page 0 but no page 1
  1257.     mov    word ptr fontlptr,offset font    ; offset of in-built 8x8 font
  1258.     mov    word ptr fontlptr+2,seg font    ; segment
  1259.     cmp    word ptr fontrptr+2,0    ; have a GRight now?
  1260.     jne    tekin2e            ; ne = yes
  1261.     mov    word ptr fontrptr+2,seg font    ; no high bit set font
  1262.     mov    word ptr fontrptr,offset font
  1263. tekin2e:mov    charhgt,8        ; 8 scan lines/char
  1264.     mov    charwidth,8        ; 8 dots across each char
  1265.     mov    putc,offset gputc    ; CGA character display routine
  1266.     mov    gfplot,offset bpltcga    ; CGA area fill routine
  1267.     mov    psetup,offset psetupc    ; CGA plot setup routine
  1268.     mov    plotptr,offset pltcga    ; CGA dot plot routine
  1269.     mov    pincy,offset pincyc    ; CGA inc y routine
  1270.     mov    xmult,5            ; CGA. Scale TEK to PC by 640/1024
  1271.     mov    xdiv,8            ;  so that 0-1023 converts to 0-639
  1272.     mov    ax,640            
  1273.     sub    ax,charwidth
  1274.     mov    xmax,ax            ; x-coord of rightmost character
  1275.     mov    ymult,10        ; vertical scale for IBM is 200/780
  1276.     mov    ydiv,39            ;
  1277.     mov    ybot,199        ; Bottom of screen is Y=199
  1278.     mov    al,tekgraf        ; user video board specification
  1279.     or    al,al            ; auto-sensing?
  1280.     jnz    tekin2d            ; nz = no
  1281.     jmp    tekin2c            ; yes (default)
  1282. tekin2d:cmp    al,1            ; user wants CGA?
  1283.     jne    tekin2a            ; ne = no
  1284.     jmp    tekin13            ; do CGA
  1285. tekin2a:cmp    al,4            ; user wants Hercules?
  1286.     jne    tekin2b            ; ne = no
  1287.     jmp    tekin8            ; do Hercules
  1288. tekin2b:cmp    al,5            ; user wants AT&T style?
  1289.     jne    tekinwy            ; ne = no
  1290.     jmp    tekin7            ; do AT&T kind
  1291.                     ; Wyse-700
  1292. tekinwy:cmp    al,8            ; user wants Wyse-700 1024*780 ?
  1293.     jne    tekinw0            ; ne = no
  1294.     call    chkwyse            ; presence test
  1295.     jc    tekinwf            ; c = failed
  1296.     mov    ax,1024        
  1297.     sub    ax,charwidth
  1298.     mov    xmax,ax            ; x-coord of rightmost character
  1299.     mov    ybot,779        ; Bottom of screen is Y=780
  1300.     mov    xmult,1            ; Wyse. Scale TEK to PC by 1024/1024
  1301.     mov    xdiv,1            ;  so that 0-1023 converts to 0-1023
  1302.     mov    ymult,1            ; vertical scale is 780/780
  1303.     mov    ydiv,1            ;
  1304.     jmp    short tekinw2        ;
  1305. tekinw0:cmp    al,7            ; user wants Wyse-700 1280*780 ?
  1306.     jne    tekinw1            ; ne = no
  1307.     call    chkwyse            ; presence test
  1308.     jc    tekinwf            ; c = failed
  1309.     mov    ax,1280        
  1310.     sub    ax,charwidth
  1311.     mov    xmax,ax            ; x-coord of rightmost character
  1312.     mov    ybot,779        ; Bottom of screen is Y=800
  1313.     mov    xmult,10        ; Wyse. Scale TEK to PC by 1280/1024
  1314.     mov    xdiv,8            ;  so that 0-1023 converts to 0-1279
  1315.     mov    ymult,1            ; vertical scale is 780/780
  1316.     mov    ydiv,1            ;
  1317.     jmp    short tekinw2        ;
  1318. tekinwf:jmp    tekin2c            ; failure jump point
  1319. tekinw1:cmp    al,6            ; user wants Wyse-700 1280*800 ?
  1320.     jne    tekin2c            ; no = no
  1321.     call    chkwyse            ; presence test
  1322.     jc    tekinwf            ; c = failed
  1323.     mov    ax,1280            
  1324.     sub    ax,charwidth
  1325.     mov    xmax,ax            ; x-coord of rightmost character
  1326.     mov    ybot,799        ; Bottom of screen is Y=800
  1327.     mov    xmult,10        ; Wyse. Scale TEK to PC by 1280/1024
  1328.     mov    xdiv,8            ;  so that 0-1023 converts to 0-1279
  1329.     mov    ymult,40        ; vertical scale for IBM is 800/780
  1330.     mov    ydiv,39            ;  so scale those 20 pixels more
  1331. tekinw2:mov    graph_mode,wyse700    ; Assume Wyse Graphics
  1332.     mov    segscn,segwyse        ; assume wyse screen segment
  1333.     mov    gpage,0            ; only one graphics page 0
  1334.     mov    putc,offset gputc    ; CGA character display routine
  1335.     mov    psetup,offset psetupw    ; Wyse plot setup routine
  1336.     mov    plotptr,offset pltcga    ; CGA dot plot routine
  1337.     mov    pincy,offset pincyw    ; Wyse inc y routine
  1338.     jmp    tekin13            ; do Wyse
  1339.                     ; do auto-sensing of display board
  1340.                     ; test for EGA
  1341. tekin2c:mov    ax,1200H        ; EGA: Bios alternate select
  1342.     mov    bl,10H                  ; Ask for EGA info
  1343.     mov    bh,0ffH            ; Bad info, for testing
  1344.     mov    cl,0fH            ; Reserved switch settings
  1345.     int    screen            ; EGA, are you there?
  1346.     and    cl,0fh            ; four lower switches
  1347.     cmp    cl,0cH            ; Test reserved switch settings
  1348.     jb    tekin3            ; b = ega present
  1349.     jmp    tekin7            ; else no EGA, check other adapters
  1350.  
  1351. tekin3:    mov    ax,40h            ; check Bios 40:87h for ega being
  1352.     mov    es,ax            ;  the active display adapter
  1353.     test    byte ptr es:[87h],8    ; is ega active?
  1354.     jz    tekin3a            ; z = yes
  1355.     jmp    tekin7            ; ega is inactive, check others
  1356. tekin3a:cmp    bl,1            ; is there 128KB on ega board?
  1357.     jb    tekin4            ; b = less, so no screen saves
  1358.     mov    gpage,1            ; >=128 KB, use two graphics pages
  1359. tekin4:    mov    graph_mode,ega        ; assume high resolution color
  1360.     cmp    cl,3            ; high resolution color?
  1361.     je    tekin5            ; e = yes
  1362.     cmp    cl,9            ; high resolution color?
  1363.     je    tekin5            ; e = yes
  1364.     mov    graph_mode,monoega    ; assume mono monitor on ega board
  1365.     test    bh,1            ; ega mono mode in effect?
  1366.      jnz    tekin5            ; nz = yes
  1367.     mov    graph_mode,colorega    ; say ordinary cga on ega board, 64KB
  1368.     mov    gpage,1            ; is enough memory with 200 scan lines
  1369.     jmp    short tekin5a        ; use current cga parameters
  1370. tekin5:    mov    ybot,349        ; text screen bottom is 349 on EGA
  1371.     mov    ymult,35        ;
  1372.     mov    ydiv,78            ; scale y by 350/780
  1373. tekin5a:mov    segscn,segega        ; use ega screen segment
  1374.     mov    psetup,offset psetupe    ; plot setup routine
  1375.     mov    plotptr,offset pltega    ; ega dot plot routine
  1376.     mov    gfplot,offset bpltega    ; ega area fill routine
  1377.     mov    pincy,offset pincye    ; inc y routine
  1378.     mov    putc,offset gputc    ; character display routine
  1379.     test    tekflg,tek_sg        ; special graphics?
  1380.     jz    tekin5d            ; z = no, use Tek 8x8 font
  1381.     mov    bh,2            ; 8x14 ROM double dot (EGA, 640x350)
  1382.     mov    charhgt,14        ; 8x14 dots
  1383.     mov    ax,1130h        ; char generator routines, info req
  1384.     int    screen            ; returns es:bp, cx, and dl (rows)
  1385.     mov    word ptr fontlptr,bp    ; offset of GLeft font table
  1386.     mov    ax,es
  1387.     mov    word ptr fontlptr+2,ax    ; segment of font table
  1388.     mov    cx,vtcpage        ; terminal emulation code page
  1389.     cmp    cx,437            ; using CP437?
  1390.     je    tekin5b            ; e = yes, then have the font
  1391.     cmp    havefont,cx        ; do we have this font?
  1392.     je    tekin5d            ; e = yes
  1393.     mov    havefont,cx        ; set rememberance flag, even if bad
  1394.     push    ax            ; save hardware pointer
  1395.     push    bp
  1396.     call    getfont            ; try to get new GRight font for CP
  1397.     pop    bp
  1398.     pop    ax
  1399.     jnc    tekin5d            ; nc = success
  1400. tekin5b:mov    word ptr fontrptr+2,ax    ; segment of hardware font table
  1401.     add    bp,128*14
  1402.     mov    word ptr fontrptr,bp    ; offset of GRight part
  1403. tekin5d:jmp    tekin13            ; end of EGA part, do VGA tests below
  1404.  
  1405. tekin7:    mov    ax,0fc00h        ; Olivetti/AT&T 6300, check rom id
  1406.     mov    es,ax
  1407.     xor    di,di            ; start here
  1408.     mov    graph_mode,olivetti    ; Olivetti
  1409.     mov    cx,attllen        ; length of logo
  1410.     mov    si,offset ATTLOGO    ; master string
  1411.     repe    cmpsb            ; do a match
  1412.     je    tekin7c            ; e = a match
  1413.     mov    di,0050h        ; look here too
  1414.     mov    si,offset ATTLOGO
  1415.     mov    cx,attllen
  1416.     repe    cmpsb
  1417.     je    tekin7c            ; e = a match
  1418.     mov    di,2014h        ; and look here
  1419.     mov    si,offset ATTLOGO
  1420.     mov    cx,attllen
  1421.     repe    cmpsb            ; do a match
  1422.     je    tekin7c            ; e = a match, else try other types
  1423. tekin7a:mov    graph_mode,toshiba
  1424.     mov    ax,0f000h        ; Check for Toshiba T3100, rom scan
  1425.     mov    es,ax
  1426.     mov    di,0014h        ; start here
  1427.     mov    si,offset TOSHLOGO    ; master string
  1428.     mov    cx,toshlen        ; length
  1429.     repe    cmpsb            ; do a match
  1430.     je    tekin7c            ; e = a match, else try other types
  1431. tekin7b:mov    graph_mode,vaxmate    ; DEC VAXmate II
  1432.     mov    ax,0f000h        ; Check for VAXmate II rom signature
  1433.     mov    es,ax
  1434.     mov    di,0e000h        ; start here
  1435.     mov    si,offset DECLOGO    ; master string
  1436.     mov    cx,declen        ; length
  1437.     repe    cmpsb            ; do a match
  1438.     jne    tekin7d            ; ne = mismatch, try other types
  1439.  
  1440.                     ; Olivetti/AT&T, Toshiba, VAXmate
  1441. tekin7c:mov    gpage,0            ; only page 0 with 640 by 400 mode
  1442.     mov    segscn,segcga        ; use cga screen segment (0b800h)
  1443.     mov    psetup,offset psetupo    ; plot setup routine
  1444.     mov    plotptr,offset pltcga    ; cga dot plot routine
  1445.     mov    gfplot,offset bpltcga    ; area fill plot routine
  1446.     mov    pincy,offset pincyh    ; inc y routine (Herc style addresses)
  1447.     mov    putc,offset gputc    ; character display routine
  1448.     mov    ybot,399        ; bottom of screen is y = 399
  1449.     mov    ymult,20        ; vertical scale = 400/780
  1450.     mov    ydiv,39            ; same as cga setup
  1451.     jmp    tekin13
  1452.  
  1453. tekin7d:cmp    curmode,mono        ; mono text mode?
  1454.     je    tekin8            ; e = yes
  1455.     jmp    tekin11            ; ne = no, try cga
  1456.                     ; test for Hercules
  1457. tekin8:    cmp    tv_mode,1        ; Environment active?
  1458.     jne    tekin8a            ; ne = no, ok to test for Hercules
  1459.     jmp    tekin10            ; don't do Herc mode, do Mono
  1460. tekin8a:mov    dx,hstatus        ; Herc status port
  1461.     in    al,dx            ; read it
  1462.     mov    bl,al            ; save here
  1463.     and    bl,80h            ; remember retrace bit
  1464.     mov    cx,0ffffh        ; do many times (for fast machines)
  1465. tekin8b:mov    dx,hstatus        ; check status port
  1466.     in    al,dx
  1467.     and    al,80h            ; select bit
  1468.     jmp    $+2            ; use a little time
  1469.     cmp    bl,al            ; did it change?
  1470.     loope    tekin8b            ; test again if not
  1471.     je    tekin10            ; e = no change in bit, not Herc
  1472.     mov    graph_mode,hercules    ; say have Herc board
  1473.     mov    segscn,seghga        ; assume hga screen segment
  1474.     mov    putc,offset gputc    ; character display routine
  1475.     mov    gfplot,offset bpltcga    ; area fill plot routine
  1476.     mov    psetup,offset psetuph    ; plot setup routine to use
  1477.     mov    plotptr,offset pltcga    ; use cga dot plot routine for Herc
  1478.     mov    pincy,offset pincyh    ; inc y routine
  1479.     mov    xmult,45        ; Scale TEK to Hercules by 720/1024
  1480.     mov    xdiv,64            ;  so that 0-1023 converts to 0-719
  1481.     mov    ax,720            
  1482.     sub    ax,charwidth
  1483.     mov    xmax,ax            ; x-coord of rightmost character
  1484.     mov    ymult,87        ; vertical scale for Hercules is
  1485.     mov    ydiv,195        ;  348/780
  1486.     mov    ybot,347        ; bottom of screen is y = 347
  1487.     mov    ax,seghga        ; segment of Herc video display
  1488.     mov    es,ax
  1489.     mov    al,es:[8000h]        ; read original contents, page 1
  1490.     not    byte ptr es:[8000h]    ; write new pattern
  1491.     mov    ah,es:[8000h]        ; read back
  1492.     not    byte ptr es:[8000h]    ; restore original contents
  1493.     not    ah            ; invert this too
  1494.     cmp    ah,al            ; same (memory present?)
  1495.     jne    tekin9            ; ne = not same, no memory there
  1496.     mov    gpage,1            ; say two pages of display memory
  1497. tekin9:    jmp    tekin13
  1498.                     ; set to MONO
  1499. tekin10:mov    graph_mode,mono        ; force monochrome adapter text
  1500.     mov    segscn,segmono        ; assume mono screen segment
  1501.     call    tscrseg            ; Environments: get virtual screen
  1502.     mov    segscn,ax        ;  seg returned in ax and es:di
  1503.     mov    gpage,0
  1504.     mov    putc,offset mputc    ; character display routine
  1505.     mov    psetup,offset psetupm    ; plot setup routine to use
  1506.     mov    gfplot,offset bpltmon    ; area fill plot routine
  1507.     mov    plotptr,offset pltmon    ; use hga dot plot routine
  1508.     mov    pincy,offset pincym    ; inc y routine
  1509.     mov    xmult,5            ; Scale TEK to mono by 640/1024
  1510.     mov    xdiv,8            ;  so that 0-1023 converts to 0-639
  1511.     mov    ax,640            
  1512.     sub    ax,charwidth
  1513.     mov    xmax,ax            ; x-coord of rightmost character
  1514.     mov    ymult,10        ; vertical scale for mono is 200/780
  1515.     mov    ydiv,39
  1516.     mov    ybot,200        ; bottom of screen is y = 200 for Bios
  1517.     jmp    tekin13            ; Uses TEXT mode, for safety
  1518.  
  1519.                     ; test for CGA
  1520. tekin11:mov    graph_mode,cga        ; set CGA high resolution graphics
  1521.     mov    segscn,segcga        ; CGA screen segment
  1522.     jmp    tekin13
  1523.  
  1524.                     ; Set Graphics mode
  1525. tekin13:cmp    tekident,0        ; just identifying?
  1526.     je    tekin13b        ; e = no
  1527.     jmp    tekin16            ; ne = yes
  1528. tekin13b:cmp    graph_mode,wyse700    ; Wyse ?
  1529.     jne    tekin13a        ; ne = no
  1530.     call    wygraf            ; set Wyse graphics mode, clear regen
  1531.     jmp    tekin16            ; restore screen
  1532. tekin13a:cmp    graph_mode,hercules    ; Hercules?
  1533.     jne    tekin14            ; ne = no
  1534.     call    hgraf            ; set Herc graphics mode, clear regen
  1535.     or    tekflg,tek_active    ; say becoming active
  1536.     jmp    tekin16            ; restore screen
  1537. tekin14:xor    ah,ah            ; set screen mode
  1538.     mov    al,graph_mode        ;  to this screen mode
  1539.     test    flags.vtflg,ttd463+ttd470 ; D463/D470?
  1540.     jnz    tekin14a        ; nz = yes, use EGA modes
  1541.     cmp    tekgraf,3        ; user wants "VGA" modes (640x480)?
  1542.     jne    tekin14a        ; ne = no
  1543.     push    ax
  1544.     mov    ax,1a00h        ; VGA, read display config code
  1545.     int    screen
  1546.     pop    ax
  1547.     cmp    bl,0bh            ; MCGA mono?
  1548.     jne    tekin14b        ; ne = no
  1549.     mov    al,monoega
  1550.     mov    graph_mode,al
  1551.     jmp    short tekin14c
  1552. tekin14b:cmp    bl,0ch            ; MCGA color?
  1553.     jne    tekin14d        ; ne = no
  1554.     mov    al,ega
  1555.     mov    graph_mode,al
  1556. tekin14c:mov    ydiv,78            ; scale y by 350/780
  1557.     mov    segscn,segega        ; use ega screen segment
  1558.     mov    psetup,offset psetupe    ; plot setup routine
  1559.     mov    plotptr,offset pltcga    ; ega dot plot routine
  1560.     mov    gfplot,offset bpltcga    ; ega area fill routine
  1561.     mov    pincy,offset pincye    ; inc y routine
  1562.     mov    putc,offset gputc    ; character display routine
  1563. tekin14d:cmp    al,monoega        ; yes, allow high resolution stuff?
  1564.     jb    tekin14a        ; b = no
  1565.     cmp    al,ega            ; ditto
  1566.     ja    tekin14a        ; a = no
  1567.     add    al,2            ; use modes 17(b/w) and 18(10)(color)
  1568.     mov    ybot,479        ; text screen bottom is 479 on VGA
  1569.     mov    ymult,48
  1570. tekin14a:cmp    tekident,0        ; just identifying screen size etc?
  1571.     jne    tekin16            ; ne = yes, do not invoke graphics
  1572.     cmp    gpage,0            ; only page 0 available?
  1573.     je    tekin15            ; e = yes, and watch for Bios errors
  1574.     cmp    inited,0        ; first time through?
  1575.     je    tekin15            ; e = yes, clear the page of old junk
  1576.     test    tekflg,tek_sg        ; special graphics
  1577.     jnz    tekin15            ; nz = yes, always repaints
  1578.     or    al,80h            ; save regen buffer (save area too)
  1579.  
  1580. tekin15:int    screen            ; Bios Set Mode.
  1581.     mov    ax,40h            ; DOS 4 GRAPHICS.COM may see high bit
  1582.     mov    es,ax            ;  and be confused. Clear it from Bios
  1583.     and    byte ptr es:[49h],7fh    ;  word area for some clones
  1584.     or    tekflg,tek_active    ; say becoming active
  1585.     mov    dgxmax,640-1        ; D470 color
  1586.     mov    dgymax,480-1
  1587.     test    flags.vtflg,ttd463+ttd470 ; DG D463/D470?
  1588.     jz    tekin16            ; z = no
  1589.     or    tekflg,tek_sg        ; say special graphics mode
  1590.     cmp    flags.vtflg,ttd470    ; correct guess?
  1591.     je    tekin16            ; e = yes
  1592.     mov    dgxmax,800-1        ; D463 monochrome
  1593.     mov    dgymax,576-1
  1594.  
  1595. tekin16:cmp    tekident,0        ; just identifying?
  1596.     jne    tekin16a        ; ne = yes
  1597.     cmp    inited,0        ; inited yet?
  1598.     jne    tekin19            ; ne = yes, restore screen
  1599.     mov    ttstate,offset tektxt    ; do displayable text
  1600.     mov    prestate,offset tektxt    ; set a previous state of text
  1601.     mov    inited,1        ; say we have initialized
  1602.     jmp    short tekin16b        ; and init the color palette
  1603. tekin16a:mov    si,offset colpal    ; active color palette
  1604.     cmp    havepal,0        ; have a color palette yet?
  1605.     jne    tekin17            ; yes, use active palette
  1606. tekin16b:mov    si,offset mondef    ; default monochrome colors
  1607.     cmp    plotptr,offset pltcga    ; using CGA style graphics?
  1608.     je    tekin17            ; e = yes
  1609.     cmp    graph_mode,mono        ; pure mono text system?
  1610.     je    tekin17            ; e = yes
  1611.     cmp    graph_mode,monoega    ; ega, but monochrome?
  1612.     je    tekin17            ; e = no
  1613.     mov    si,offset coldef    ; use color palette
  1614. tekin17:mov    havepal,1        ; say have a color palette
  1615.     mov    al,[si+7]        ; foreground color = palette 7
  1616.     mov    gfcol,al
  1617.     mov    al,[si]            ; background color = palette 0
  1618.     mov    gbcol,al
  1619.     mov    cx,16
  1620.     mov    di,offset colpal    ; VT340 active color palette
  1621.     push    es
  1622.     push    ds
  1623.     pop    es
  1624.     cld
  1625.     rep    movsb            ; reinit palette entries
  1626.     pop    es
  1627.     call    fixcolor        ; correct color mapping for some bds
  1628.     mov    al,gfcol
  1629.     mov    tfcol,al        ; remember current coloring
  1630.     mov    al,gbcol
  1631.     mov    tbcol,al
  1632.     cmp    tekident,0        ; just identifying?
  1633.     jne    tekin21            ; ne = yes
  1634.     test    tekflg,tek_sg        ; special graphics active?
  1635.     jnz    tekin20            ; nz = yes
  1636.     call    tekcls            ; clear screen, for ega coloring
  1637.     jmp    short tekin20
  1638.  
  1639. tekin19:cmp    vtclear,0        ; clear screen?
  1640.     je    tekin19a        ; e = no
  1641.     call    tekcls            ; clear screen, use existing colors
  1642.     mov    vtclear,0
  1643.     jmp    short tekin20
  1644. tekin19a:test    flags.vtflg,ttd463+ttd470 ; DG D463/D470?
  1645.     jnz    tekin19b        ; nz = yes
  1646.     test    tekflg,tek_sg        ; special graphics active?
  1647.     jnz    tekin19b        ; nz = yes
  1648.     call    tekrest            ; restore old graphics screen
  1649.     mov    ax,save_xcor        ; and saved cursor
  1650.     mov    x_coord,ax
  1651.     mov    ax,save_ycor
  1652.     mov    y_coord,ax
  1653. tekin19b:mov    al,tfcol        ; and coloring
  1654.     mov    gfcol,al
  1655.     mov    al,tbcol
  1656.     mov    gbcol,al
  1657.     
  1658. tekin20:cmp    tekident,0        ; just identifying screen size etc?
  1659.     jne    tekin21            ; ne = yes, do not invoke graphics
  1660.     test    tekflg,tek_sg        ; special graphics?
  1661.     jz    tekin20a        ; z = no
  1662.     test    flags.vtflg,ttd463+ttd470 ; DG D463/D470?
  1663.     jz    tekin20c        ; z = no
  1664.     mov    al,scbattr        ; get default colors
  1665.     mov    cl,4
  1666.     shr    al,cl            ; get background color bits
  1667.     mov    gbcol,al        ; set the for screen clearing
  1668.     call    tekcls            ; clear screen for nice repainting
  1669.     test    flags.vtflg,ttd463+ttd470 ; DG D463/D470?
  1670.     jz    tekin20a        ; z = no
  1671.     test    dgcross,1        ; is crosshair to be active?
  1672.     jz    tekin20b        ; z = no
  1673.     call    crossini
  1674. tekin20b:call    frepaint        ; repaint screen
  1675. tekin20c:mov    dx,cursor
  1676.     call    teksetcursor        ; set the cursor
  1677. tekin20a:mov    ax,250
  1678.     call    tekwait            ; 250 ms wait for display adapter
  1679.     mov    al,flowon        ; get flowon control byte
  1680.     or    al,al            ; able to send xon?
  1681.     jz    tekin21            ; z = no
  1682.     call    outmodem        ; tell host xon
  1683.     test    flags.vtflg,ttd463+ttd470 ; DG D463/D470?
  1684.     jnz    tekin21            ; nz = yes
  1685.     test    tekflg,tek_sg        ; special graphics?
  1686.     jnz    tekin21            ; nz = yes
  1687.     mov    cx,seg font        ; use Tek 8x8 font for non-DG work
  1688.     mov    word ptr fontlptr+2,cx
  1689.     mov    word ptr fontrptr+2,cx    ; no high bit set font
  1690.     mov    cx,offset font
  1691.     mov     word ptr fontlptr,cx
  1692.     mov    word ptr fontrptr,cx
  1693.     call    setcursor        ; set the cursor
  1694.  
  1695. tekin21:mov    al,chcontrol        ; opaque/transparent char writing
  1696.     mov    bscontrol,al        ; set destructive BS control
  1697.     mov    spcontrol,al        ; set destructive SPACE control
  1698.     mov    tekident,0
  1699.     mov    bypass,0        ; clear Bypass flag
  1700.     clc                ; clear carry for success
  1701.     pop    es
  1702.     pop    di
  1703.     pop    si
  1704.     pop    dx
  1705.     pop    cx
  1706.     pop    bx
  1707.     pop    ax
  1708.     ret
  1709. tekini    endp
  1710.  
  1711. TEKRINT proc    far            ; Tek reinitialization entry point
  1712.     call    far ptr tekend        ; exit cleanly if already in Tek mode
  1713.     xor    ax,ax            ; get a null
  1714.     mov    inited,al        ; do complete reinitialization
  1715.     mov    xcenter,ax        ; forget center of screen
  1716.     mov    ycenter,ax
  1717.     mov    x_coord,ax
  1718.     mov    y_coord,ax
  1719.     mov    vtclear,1        ; clear the screen
  1720.     call    tekini
  1721.     ret
  1722. TEKRINT    endp
  1723.  
  1724. ; End TEK emulation, recover previous screen
  1725. TEKEND    proc    far
  1726.     mov    ttstate,offset tektxt    ; set an initial state
  1727.     mov    prestate,offset tektxt    ; and a previous state
  1728.     test    tekflg,tek_active    ; running as a Tek terminal now?
  1729.     jnz    teknd1            ; nz = yes
  1730.     ret                ; else return as is
  1731. teknd1:    call    remcursor        ; remove text cursor, if any
  1732.     call    crossfin        ; clean up crosshair activity
  1733.     test    tekflg,tek_sg        ; special graphics?
  1734.     jnz    teknd1a            ; nz = yes, do not save screen
  1735.     call    teksave            ; save graphics screen to page 1
  1736.     mov    ax,x_coord        ; save cursor location too
  1737.     mov    save_xcor,ax
  1738.     mov    ax,y_coord
  1739.     mov    save_ycor,ax
  1740. teknd1a:cmp    graph_mode,hercules    ; Hercules?
  1741.     jne    teknd2            ; ne = no
  1742.     call    htext            ; yes then set up Hercules text mode
  1743. teknd2:    call    mousexit        ; restore mouse state, if any
  1744.     xor    ah,ah            ; set video mode
  1745.     mov    al,curmode        ; restore previous screen mode
  1746.     int    screen            ; revert to text screen mode
  1747.     mov    lastc,0
  1748.     mov    bypass,0        ; reset bypass condition
  1749.     mov    visible,0        ; next move is invisible
  1750.     test    tekflg,tek_sg        ; were doing special graphics?
  1751.     jz    teknd3            ; z = no
  1752.     mov    inited,0        ; yes, reinit next time
  1753. teknd3:    and    tekflg,not (tek_active+tek_sg)    ; say we are inactive
  1754.     clc
  1755.     ret
  1756. TEKEND    ENDP
  1757.  
  1758. ; Save EGA/VGA register and Bios info in array egadata.
  1759. ; Returns carry clear if done, else carry set
  1760.  
  1761. ;Terminal emulation. Enter with received character in AL.
  1762. TEKEMU    proc    far            ; main emulator
  1763.     call    tektt            ; local emulator routine
  1764.     ret
  1765. TEKEMU    endp
  1766.  
  1767. tektt    proc    near
  1768.     test    tekflg,tek_active    ; running as a Tek device?
  1769.     jnz    tektt1            ; nz = yes
  1770.     push    ax
  1771.     call    tekini            ; init now
  1772.     pop    ax
  1773.     or    tekflg,tek_dec        ; setup Tek submode of DEC terminal
  1774.     mov    ttstate,offset tektxt    ; initial state
  1775.     mov    prestate,offset tektxt    ; set a previous state of text
  1776.     jnc    tektt1            ; nc = succeeded
  1777.     ret                ; else failed to init, just return
  1778. tektt1:    test    al,80h            ; high bit set?
  1779.     jz    tektt1a            ; z = no
  1780.     cmp    al,9fh            ; in range for C1 controls?
  1781.     ja    tektt1a            ; a = no
  1782.     push    ax            ; save the char
  1783.     mov    al,escape        ; make 7-bit control version
  1784.     call    tektt2            ; act on escape
  1785.     pop    ax
  1786.     sub    al,40h            ; get second char of 7-bit control
  1787.  
  1788. tektt1a:and    al,7fh            ; force Tek chars to be 7 bits
  1789.     or    al,al            ; NUL char?
  1790.     jnz    tektt2            ; nz = no
  1791.     ret                ; yes, ignore it (before logging)
  1792. tektt2:    test    yflags,capt        ; capturing output?
  1793.     jz    tektt4            ; z = no, forget this part
  1794.     push    ax            ; save char
  1795.     call    tcptchr            ; give it captured character
  1796.     pop    ax            ; restore character and keep going
  1797. tektt4:    test    yflags,trnctl        ; debug? if so use tty mode
  1798.     jz    tektt5            ; z = no
  1799.     cmp    al,DEL            ; DEL char?
  1800.     jne    tektt4a            ; ne = no
  1801.     mov    al,5eh            ; make DEL a caret query mark
  1802.     call    outscrn
  1803.     mov    al,3fh            ; the query mark
  1804.     call    outscrn
  1805.     ret
  1806. tektt4a:cmp    al,' '            ; control char?
  1807.     jae    tektt4b            ; ae = no
  1808.     push    ax
  1809.     mov    al,5eh            ; caret
  1810.     call    outscrn
  1811.     pop    ax
  1812.     add    al,'A'-1        ; make char printable
  1813. tektt4b:call    outscrn
  1814.     ret
  1815.  
  1816. tektt5:    cmp    bypass,0        ; Bypass mode off?
  1817.     jne    tektt5a            ; ne = no, on, ignore all incoming
  1818.     call    ttstate            ; do current state
  1819.     ret
  1820. tektt5a:cmp    al,' '            ; incoming control code?
  1821.     jae    tektt5b            ; ae = no
  1822.     mov    bypass,0        ; turn off bypass
  1823.     call    ttstate            ; act on it
  1824. tektt5b:ret
  1825. tektt    endp
  1826.      
  1827. TEKTXT    proc    near            ; Dispatch on text characters
  1828.     mov    ttstate,offset tektxt    ; this is our state
  1829.     push    ax
  1830.     call    setcursor        ; show text cursor
  1831.     pop    ax
  1832.     cmp    al,DEL            ; RUBOUT?
  1833.     jne    tektx1            ; ne = no
  1834.     mov    al,bs            ; make BS
  1835.     jmp    short tektx7
  1836. tektx1:    cmp    al,CR            ; carriage return (^M)?
  1837.     je    tektx7            ; e = yes
  1838.     cmp    al,LF            ; line feed (^J)?
  1839.     je    tektx7            ; e = yes
  1840.     cmp    al,FF            ; form feed (^L)?
  1841.     jne    tektx4            ; ne = no
  1842.     call    tekcls            ; clear the screen
  1843.     ret
  1844. tektx4:    cmp    al,VT            ; vertical tab (^K)?
  1845.     je    tektx7
  1846.     cmp    al,bell            ; bell (^G)?
  1847.     jne    tektx5            ; ne = no
  1848.     call    tekbeep
  1849.     ret
  1850. tektx5:    cmp    al,tab            ; horizontal tab (^I)?
  1851.     je    tektx7            ; e = yes
  1852.     cmp    al,BS            ; backspace (^H)?
  1853.     je    tektx7            ; e = yes
  1854.     cmp    al,' '            ; control char?
  1855.     jae    tektx7            ; ae = no
  1856.     jmp    tekctl            ; process control char
  1857. tektx7:    call    outscrn            ; output character to the screen
  1858. tektx8:    ret
  1859. TEKTXT    endp
  1860.  
  1861.  
  1862. tekctl    proc    near            ; Control characters:
  1863.     cmp    al,GS            ; Line plot command?
  1864.     jne    tekctl1            ; ne = no
  1865.     mov    visible,0        ; next move is invisible
  1866.     and    status,not txtmode    ; set status report byte
  1867.     mov    ttstate,offset tekline    ; expect coordinates next
  1868.     call    remcursor        ; remove text cursor
  1869.     ret
  1870. tekctl1:cmp    al,RS            ; Incremental dot command?
  1871.     jne    tekctl2            ; ne = no
  1872.     and    status,not txtmode    ; set status report
  1873.     mov    ttstate,offset tekrlin    ; expect pen command next
  1874.     call    remcursor        ; remove text cursor
  1875.     ret
  1876. tekctl2:cmp    al,FS            ; Point plot command?
  1877.     jne    tekctl3            ; ne = no
  1878.     mov    visible,0        ; next move is invisible
  1879.     and    status,not txtmode    ; set status report byte
  1880.     mov    ttstate,offset tekpnt
  1881.     call    remcursor        ; remove text cursor
  1882.     ret
  1883. tekctl3:cmp    al,US            ; assert text mode? [bjh]
  1884.     jne    tekctl4            ; ne = no
  1885.     or    status,txtmode        ; set status report byte
  1886.     mov    ttstate,offset tektxt    ; go to TEKTXT next time
  1887.     mov    visible,0        ; next move is invisible
  1888.     call    setcursor        ; restore text cursor
  1889.     ret
  1890. tekctl4:cmp    al,ESCAPE        ; Escape?
  1891.     jne    tekctl5            ; ne = no
  1892.     call    remcursor        ; remove text cursor
  1893.     or    status,txtmode        ; set status report byte
  1894.     cmp    ttstate,offset tekesc    ; already in escape state?
  1895.     je    tekctl7            ; e = yes, nest no further
  1896.     push    ttstate            ; current state
  1897.     pop    prestate        ; save here as previous state
  1898.     mov    ttstate,offset tekesc    ; next state parses escapes
  1899.     ret
  1900.  
  1901. tekctl5:cmp    al,CAN            ; Control X? (exits Tek sub mode)
  1902.     jne    tekctl7            ; ne = no, stay in current state
  1903.     mov    ttstate,offset tektxt    ; back to text mode
  1904.     mov    bypass,1        ; turn on bypass mode
  1905.     cmp    flags.vtflg,tttek    ; main Tek emulator?
  1906.     je    tekctl6            ; e = yes, ignore the ^X
  1907.     call    tekend            ; else exit sub mode
  1908.     and    tekflg,not tek_dec    ; returning to text emulator
  1909.     mov    visible,0        ; next move is invisible
  1910.     call    frepaint        ; regenerate text screen
  1911. tekctl6:mov    prestate,offset tektxt    ; make previous state text
  1912. tekctl7:ret
  1913. tekctl    endp
  1914.  
  1915. TEKESC    proc    near            ; Process ESC <following text>
  1916.     mov    ninter,0        ; initialize parsing
  1917.     mov    ttstate,offset tekesc    ; in case get here from msz file
  1918.     cmp    inited,0        ; inited yet? (msz call)
  1919.     jne    tekesc1            ; ne = yes
  1920.     call    tekini            ; init now
  1921.     mov    prestate,offset tektxt    ; set a previous state of text
  1922.     jnc    tekesc1            ; nc = succeeded
  1923.     ret                ; else failed to init, just return
  1924.     
  1925. tekesc1:cmp    al,20h            ; in intermediates, column 2?
  1926.     jb    tekesc3            ; b = no
  1927.     cmp    al,2fh
  1928.     ja    tekesc3            ; a = no
  1929.     mov    ttstate,offset tekesc1    ; stay in this state while intermeds
  1930.     mov    bx,ninter        ; number of intermediates
  1931.     cmp    bx,maxinter        ; done enough already?
  1932.     jae    tekesc2            ; ae = yes, ignore the excess
  1933.     mov    inter[bx],al        ; store this one
  1934.     inc    ninter            ; one more
  1935.     cmp    inter,'/'        ; HDS2000/3000 Final char?
  1936.     je    tekesc3            ; e = yes, process specially like '['
  1937. tekesc2:ret                ; get more input
  1938.     
  1939.                     ; Final char is in AL, dispatch on it
  1940. tekesc3:mov    ttstate,offset tektxt    ; set new state
  1941.     mov    esctype,al        ; save kind of escape sequence
  1942.     mov    bx,offset esctab    ; ESC dispatch table
  1943.     call    atdispat        ; dispatch on AL
  1944.     ret
  1945. TEKESC    endp    
  1946.  
  1947. tekeseq    proc    near            ; process Escape and Device Contrl seq
  1948.     call    tparstart        ; init escape sequence parser
  1949.     mov    ttstate,offset escparse    ; do parsing next
  1950.     ret
  1951. tekeseq    endp
  1952.  
  1953. ; State for gathering text to feed escape sequence parser
  1954. escparse proc    near
  1955.     cmp    al,' '            ; embedded control code?
  1956.     jb    escpar2            ; b = yes, process now
  1957.     call    tparser            ; far call, to call real parser
  1958.     jnc    escpar1            ; nc = success
  1959.     push    prestate        ; recover previous state
  1960.     pop    ttstate
  1961.     stc
  1962. escpar1:ret
  1963. escpar2:call    tekctl            ; process embedded control code
  1964.     push    prestate        ; get previous state
  1965.     pop    ttstate            ; restore it
  1966.     ret
  1967. escparse endp
  1968.  
  1969. ; Escape sequence parser completion routine
  1970. ; AL has Final character of escape sequence
  1971. XPARDONE PROC    FAR            ; called by tpardone when done
  1972.     cmp    esctype,'['        ; ansi escape sequence (ESC [)?
  1973.     jne    xpardo3            ; ne = no
  1974.     mov    bx,offset anstab    ; ANSI ESC [ table
  1975.     call    atdispat        ; dispatch on Final char in AL
  1976.     jmp    short xpardo5
  1977.  
  1978. xpardo3:cmp    esctype,'/'        ; HDS escape sequence (ESC /)?
  1979.     jne    xpardo4            ; ne = no
  1980.     call    hdsesc            ; analyze
  1981.     jmp    short xpardo5
  1982.  
  1983. xpardo4:cmp    esctype,'P'        ; DCS introducer?
  1984.     jne    xpardo5            ; ne = no
  1985.     call    tekdcs            ; grab parameters etc, prep strings
  1986.     ret
  1987.  
  1988. xpardo5:push    prestate        ; recover previous state
  1989.     pop    ttstate
  1990.     ret
  1991. XPARDONE ENDP
  1992.                 ; ESC <char> action routines
  1993.                 ; exit each by putting prestate into ttstate
  1994.  
  1995. tekenq    proc    near            ; ESC-^E Enquiry for cursor position
  1996.     mov    bypass,1        ; set bypass mode
  1997.     call    sendstat        ; send status
  1998.     push    prestate        ; get previous state
  1999.     pop    ttstate            ; restore it
  2000.     ret
  2001. tekenq    endp
  2002.  
  2003. tekcan    proc    near            ; ESC ^X
  2004.     push    prestate        ; get previous state
  2005.     pop    ttstate            ; restore it
  2006.     jmp    tekctl            ; process in controls section
  2007. tekcan    endp
  2008.  
  2009. tekgin    proc    near            ; ESC-^Z Enter GIN mode
  2010.     cmp    graph_mode,mono        ; Monochrome text mode?
  2011.     je    tekgin1            ; e = yes, no crosshairs in text mode
  2012.     mov    bypass,1        ; turn on GIN mode bypass conditon
  2013.     call    crossini        ; preset crosshairs
  2014. tekgin3:call    far ptr croshair    ; activate the cross-hairs
  2015.     jnc    tekgin3            ; loop until exit is signaled
  2016.     call    crossfin        ; clean up
  2017.     jmp    short tekgin2
  2018. tekgin1:call    tekbeep            ; tell the user we are unhappy
  2019. tekgin2:push    prestate        ; get previous state
  2020.     pop    ttstate            ; restore it
  2021.     ret
  2022. tekgin    endp
  2023.  
  2024. tektwo    proc    near            ; ESC 2 (Exit Tek mode)
  2025.     mov    al,CAN            ; force Control-X
  2026.     jmp    tekcan            ; process there as ESC ^X
  2027. tektwo    endp
  2028.  
  2029. tekqury    proc    near            ; query mark (ESC ? means DEL)
  2030.     mov    al,DEL            ; replace with DEL code
  2031.     push    prestate        ; get previous state
  2032.     pop    ttstate            ; restore it
  2033.     ret
  2034. tekqury    endp
  2035.  
  2036. tekfill    proc    near            ; Fill series ESC @ .. ESC M
  2037.     sub    al,'@'            ; remove bias
  2038.     mov    bl,al
  2039.     xor    bh,bh
  2040.     shl    bx,1            ; make a word index
  2041.     mov    bx,fillist[bx]        ; get pointer to the pattern from list
  2042.     mov    fillptr,bx        ; assign this pattern pointer
  2043.     push    prestate        ; get previous state
  2044.     pop    ttstate            ; restore it
  2045.     ret
  2046. tekfill    endp
  2047.  
  2048. teklpat    proc    near            ; ESC accent grave line pattern series
  2049.     cmp    al,'g'            ; accent ... lowercase g?
  2050.     jbe    teklpa2            ; be = yes
  2051.     cmp    al,'o'            ; bold patterns ESC h..ESC o?
  2052.     ja    teklpa1            ; a = no
  2053.     sub    al,'h'-accent        ; map bold to normal
  2054.     jmp    short teklpa2
  2055. teklpa1:sub    al,'x'-'f'        ; user sets,map x to f, y to g, z to h
  2056. teklpa2:push    bx
  2057.     mov    bl,al
  2058.     sub    bl,accent        ; remove bias
  2059.     cmp    bl,8            ; nine patterns, ignore others
  2060.     jbe    teklpa3            ; be = ok, make others accent, solid
  2061.     xor    bl,bl            ; solid pattern
  2062. teklpa3:xor    bh,bh
  2063.     shl    bx,1            ; make this a word index
  2064.     mov    bx,linetab[bx]        ; get line pattern word
  2065.     mov    linepat,bx        ; save in active word
  2066.     pop    bx            ; return to previous mode
  2067.     push    prestate        ; get previous state
  2068.     pop    ttstate            ; restore it
  2069.     ret
  2070. teklpat    endp
  2071.  
  2072. ; Detect exit Tek submode command ESC [ ? 38 l  from VT340's
  2073. escexit    proc    near
  2074.     cmp    lparam,'?'        ; possible "ESC [ ? 38 l"?
  2075.     jne    escex2            ; ne = no
  2076.     cmp    nparam,1        ; just one numeric parameter?
  2077.     jne    escex2            ; ne = no
  2078.     cmp    al,'l'            ; ESC [ ? Pn l?
  2079.     jne    escex2            ; ne = no
  2080.     cmp    param,38        ; correct value?
  2081.     jne    escex2            ; ne = no
  2082.     cmp    flags.vtflg,tttek    ; are we a full Tek terminal now?
  2083.     je    escex1            ; e = yes, stay that way
  2084.     call    far ptr tekend
  2085.     and    tekflg,not tek_dec    ; returning to text emulator
  2086.     call    frepaint
  2087.     ret
  2088. escex1:    mov    ttstate,offset tektxt
  2089.     mov    al,CAN            ; simulate arrival of Control-X
  2090.     jmp    tektxt            ; process char as text
  2091. escex2:    ret
  2092. escexit    endp
  2093.  
  2094. ; Human Data Systems 2000/3000 style escape sequences (ESC / params Final)
  2095. ; Final character is in AL
  2096. hdsesc    proc    near
  2097.     cmp    al,'x'            ; draw an empty rectangle?
  2098.     jne    hdsesc0            ; ne = no
  2099.     call    rectdraw
  2100.     jmp    short hdsesc2a
  2101. hdsesc0:cmp    al,'y'            ; draw a filled rectangle?
  2102.     jne    hdsesc1            ; ne = no
  2103.     call    rectfil            ;do xhome,yhome,xwidth,yheight,pattern
  2104.     jmp    short hdsesc2a
  2105. hdsesc1:cmp    al,'z'            ; draw and fill rectangle?
  2106.     jne    hdsesc2            ; ne = no
  2107.     call    rectfil            ; do fill before border
  2108.     call    rectdraw        ; do border
  2109.     jmp    short hdsesc2a
  2110. hdsesc2:cmp    ninter,0        ; any intermediates?
  2111.     jne    hdsesc2a        ; ne = yes, failure
  2112.     cmp    lparam,0        ; letter parameter?
  2113.     jne    hdsesc2a        ; ne = yes, failure
  2114.     cmp    nparam,1        ; just zero or one numeric parameter?
  2115.     ja    hdsesc9            ; a = no
  2116.     cmp    al,'a'            ; user defined pattern?
  2117.     jb    hdsesc3            ; b = no
  2118.     cmp    al,'c'
  2119.     ja    hdsesc3            ; a = no
  2120.     sub    al,'a'            ; 'a' is first of three user patterns
  2121.     xor    ah,ah            ;  store as 'f,g,h' in the series
  2122.     mov    bx,ax
  2123.     shl    bx,1            ; make a word index
  2124.     mov    ax,param[0]        ; get the 16-bit pattern
  2125.     mov    linetab[bx+12],ax    ; store in user defined pattern
  2126. hdsesc2a:push    prestate        ; get previous state
  2127.     pop    ttstate            ; restore it
  2128.     ret
  2129.  
  2130. hdsesc3:cmp    al,'d'            ; "Data Level" (pixel ops)?
  2131.     jne    hdsesc4            ; ne = no
  2132.     mov    cx,param        ; get the parameter value
  2133.     mov    al,pixfor        ; assume foreground only ESC / 0 d
  2134.     cmp    cl,1            ; something else?
  2135.     jb    hdsesc3a        ; b = no
  2136.     mov    al,pixbak        ; assume background only ESC / 1 d
  2137.     cmp    cl,2            ; something else?
  2138.     jb    hdsesc3a        ; b = no
  2139.     mov    al,pixxor        ; assume XOR  ESC / 2 d
  2140.     cmp    cl,3            ; something else?
  2141.     jb    hdsesc3a        ; b = no
  2142.     ja    hdsesc3b        ; a = unknown, ignore
  2143.     mov    al,pixfor+pixbak    ; write both absolute  ESC / 3 d
  2144. hdsesc3a:mov    ccode,al        ; use as pixel op coding
  2145. hdsesc3b:push    prestate        ; get previous state
  2146.     pop    ttstate            ; restore it
  2147.     ret
  2148.  
  2149. hdsesc4:cmp    al,'h'            ; set space, backspace control?
  2150.     je    hdsesc4a        ; e = yes
  2151.     cmp    al,'l'            ; reset space, backspace control?
  2152.     jne    hdsesc9            ; ne = no
  2153.     xor    ah,ah            ; say resetting
  2154.     jmp    short hdsesc5
  2155. hdsesc4a:mov    ah,1            ; say setting
  2156. hdsesc5:cmp    param,2            ; space control?
  2157.     jne    hdsesc5a        ; ne = no
  2158.     mov    spcontrol,ah        ; reset (0) or set destructive SPACE
  2159.     push    prestate        ; get previous state
  2160.     pop    ttstate            ; restore it
  2161.     ret
  2162. hdsesc5a:cmp    param,9            ; destructive backspace?
  2163.     jne    hdsesc13        ; ne = no
  2164.     mov    bscontrol,ah        ; reset (0) or set destructive BS
  2165.  
  2166. hdsesc9:cmp    al,'C'            ; user defined fill pattern #1?
  2167.     jne    hdsesc10        ; ne = no
  2168.     mov    di,offset filpat13    ; storage area for user pattern #1
  2169.     jmp    short hdsesc11
  2170. hdsesc10:cmp    al,'D'            ; user defined fill pattern #2?
  2171.     jne    hdsesc11        ; ne = no
  2172.     mov    di,offset filpat14    ; storage area for user pattern #2
  2173. hdsesc11:mov    cx,8            ; do 8 paramters
  2174.     xor    bx,bx
  2175. hdsesc12:mov    ax,param[bx]        ; copy 8 bit fill pattern
  2176.     mov    [di],al            ; to array
  2177.     add    bx,2
  2178.     inc    di
  2179.     loop    hdsesc12
  2180. hdsesc13:push    prestate        ; get previous state
  2181.     pop    ttstate            ; restore it
  2182.     ret
  2183. hdsesc    endp
  2184.  
  2185. ; Analyze ESC [ Pn ; Pn m  color command    
  2186. ; where Pn = 30-37 foreground color, 40-47 background color, ANSI standard
  2187. ; Enter with escape sequence already parsed.
  2188. TEKCOL    proc    near
  2189.     push    si
  2190.     cld
  2191.     mov    al,gfcol        ; update these in case error
  2192.     mov    tfcol,al
  2193.     mov    al,gbcol
  2194.     mov    tbcol,al
  2195.     mov    si,offset param        ; parameters from parser
  2196.     mov    cx,nparam        ; number of parameters
  2197. tekco1:    jcxz    tekco5            ; z = none left
  2198.     lodsw                ; parameter to ax
  2199.     dec    cx
  2200.     or    ax,ax            ; 0, remove intensity, set b/w?
  2201.     jnz    tekco2            ; nz = no
  2202.     mov    tfcol,7            ; regular white
  2203.     mov    tbcol,0            ;  on black
  2204.     jmp    short tekco1
  2205.  
  2206. tekco2:    cmp    ax,1            ; intensity bit?
  2207.     jne    tekco3            ; ne = no
  2208.     or    tfcol,8            ; set foreground intensity
  2209.     jmp    short tekco1
  2210.     
  2211. tekco3:    cmp    ax,30            ; foreground series?
  2212.     jb    tekco1            ; b = no
  2213.     cmp    ax,37
  2214.     ja    tekco4            ; a = no
  2215.     sub    ax,30            ; remove bias
  2216.     push    bx
  2217.     mov    bl,al
  2218.     xor    bh,bh
  2219.     mov    al,byte ptr colortb[bx]    ; reverse coloring
  2220.     pop    bx
  2221.     and    tfcol,not (7)        ; retain intensity bit
  2222.     or    tfcol,al        ; remember foreground color
  2223.     jmp    short tekco1
  2224.  
  2225. tekco4:    cmp    ax,40
  2226.     jb    tekco1
  2227.     cmp    ax,47            ; legal value?
  2228.     ja    tekco1            ; a = no
  2229.     sub    al,40
  2230.     push    bx
  2231.     mov    bl,al
  2232.     xor    bh,bh
  2233.     mov    al,byte ptr colortb[bx]    ; reverse coloring
  2234.     pop    bx
  2235.     mov    tbcol,al        ; remember background color
  2236.     jmp    short tekco1
  2237.  
  2238. tekco5:    cmp    ninter,0        ; intermediates?
  2239.     jne    tekco7            ; ne = yes, no go
  2240.     cmp    lparam,0        ; letter parameter?
  2241.     jne    tekco7            ; ne = yes, no go
  2242.     cmp    nparam,0        ; number of ansi arguments, zero?
  2243.     ja    tekco6            ; a = no, got some
  2244.     mov    tbcol,0            ; none is same as 0, set b/w
  2245.     mov    tfcol,7
  2246. tekco6:    mov    al,tbcol        ; success, store coloring
  2247.     mov    gbcol,al        ; set background color
  2248.     mov    al,tfcol
  2249.     mov    gfcol,al        ; set foreground color
  2250.     call    fixcolor        ; do special ega corrections
  2251.     mov    al,gfcol        ; update these in case error
  2252.     mov    tfcol,al
  2253.     mov    colpal[7],al        ; foreground goes here
  2254.     mov    al,gbcol
  2255.     mov    tbcol,al
  2256.     mov    colpal[0],al        ; background goes here
  2257. tekco7:    pop    si
  2258.     clc
  2259.     ret
  2260. TEKCOL    endp
  2261.  
  2262. ; Revise screen color codes for ega boards with mono displays and limited
  2263. ; memory.
  2264. fixcolor proc    near
  2265.     cmp    graph_mode,ega        ; one of these ega modes?
  2266.     je    fixcol6            ; e = yes
  2267.     cmp    graph_mode,colorega
  2268.     je    fixcol6
  2269.     cmp    graph_mode,monoega
  2270.     je    fixcol6
  2271.     cmp    plotptr,offset pltcga    ; using CGA style graphics?
  2272.     jne    fixcol5            ; ne = no
  2273.     and    gfcol,7            ; strip intensity
  2274.     jmp    short fixcol6        ; keep colors different
  2275. fixcol5:ret                ; else ignore color corrections
  2276. fixcol6:mov    ah,gfcol
  2277.     mov    al,gbcol
  2278.     cmp    plotptr,offset pltcga    ; CGA style?
  2279.     jne    fixcol8            ; ne = no
  2280.     or    ah,ah            ; bright foreground?
  2281.     jnz    fixcol7            ; nz = yes
  2282.     mov    al,1            ; make background illuminated
  2283.     jmp    short fixcol3
  2284. fixcol7:xor    al,al            ; force background to dark
  2285. fixcol8:cmp    graph_mode,monoega    ; monochrome ega display?
  2286.     jne    fixcol3            ; ne = no
  2287.     test    al,7            ; bright backgound?
  2288.     jnz    fixcol1            ; nz = yes
  2289.     mov    ah,1            ; normal foreground
  2290.     test    gfcol,8            ; intensity on?
  2291.     jz    fixcol1            ; z = no
  2292.     mov    ah,5            ; say bright foreground
  2293. fixcol1:test    al,7            ; black backgound?
  2294.     jz    fixcol2            ; z = yes
  2295.     mov    al,1            ; regular video
  2296. fixcol2:cmp    ah,al            ; same color in both?
  2297.     jne    fixcol3            ; ne = no
  2298.     mov    ah,1            ; make foreground regular
  2299.     xor    al,al            ;  and background black
  2300. fixcol3:mov    gfcol,ah
  2301.     mov    gbcol,al
  2302.     cmp    gpage,0            ; minimal memory (64KB mono and ega)?
  2303.     ja    fixcol4            ; a = no, enough, else strange mapping
  2304.     mov    al,gfcol        ; fix coloring to map planes C0 to C1
  2305.     and    al,5            ; and C2 to C3 (as 0, 3, 0Ch, or 0Fh)
  2306.     mov    ah,al            ; make a copy
  2307.     shl    ah,1            ; duplicate planes C0, C2 in C1, C3
  2308.     or    al,ah            ; merge the bits
  2309.     mov    gfcol,al        ; store proper foreground color
  2310.     mov    al,gbcol        ; repeat for background color
  2311.     and    al,5
  2312.     mov    ah,al
  2313.     shl    ah,1
  2314.     or    al,ah
  2315.     mov    gbcol,al
  2316. fixcol4:ret
  2317. fixcolor endp
  2318.  
  2319. tekrid    proc    near            ; report Tek screen parameters
  2320.     cmp    lparam,'?'        ; possible "ESC [ ? 38 l"?
  2321.     jne    tekridx            ; ne = no
  2322.     cmp    nparam,1        ; just one numeric parameter?
  2323.     jne    tekridx            ; ne = no
  2324.     cmp    param,256        ; correct value?
  2325.     je    tekrid1            ; e = yes
  2326. tekridx:ret
  2327. tekrid1:push    es            ; as ESC [ ? 256; height; len; #col n
  2328.     push    ds
  2329.     pop    es
  2330.     cld
  2331.     mov    di,offset rdbuf        ; a temp buffer
  2332.     mov    al,escape        ; report
  2333.     stosb
  2334.     mov    al,'['
  2335.     stosb
  2336.     mov    al,'?'
  2337.     stosb
  2338.     mov    ax,256
  2339.     call    dec2di            ; write ascii digits
  2340.     mov    al,';'
  2341.     stosb
  2342.     mov    ax,ybot            ; do height
  2343.     inc    ax
  2344.     cmp    graph_mode,mono        ; pure mono text system?
  2345.     jne    tekrid7a        ; ne = no
  2346.     mov    ax,24
  2347. tekrid7a:call    dec2di
  2348.     mov    al,';'            ; separator
  2349.     stosb
  2350.     mov    ax,xmax            ; width
  2351.     add    ax,8            ; in dots
  2352.     cmp    graph_mode,mono        ; pure mono text system?
  2353.     jne    tekrid7b        ; ne = no
  2354.     mov    ax,80
  2355. tekrid7b:call    dec2di
  2356.     mov    al,';'            ; separator
  2357.     stosb
  2358.     mov    al,'1'            ; screen colors, assume 1
  2359.     stosb
  2360.     cmp    plotptr,offset pltcga    ; using CGA style graphics?
  2361.     je    tekrid4            ; e = yes
  2362.     cmp    graph_mode,monoega    ; monochrome monitor on ega?
  2363.     je    tekrid4            ; e = yes
  2364.     cmp    graph_mode,mono        ; pure mono text system?
  2365.     jne    tekrid3
  2366.     mov    byte ptr [di-1],'0'    ; say zero colors
  2367.     jmp    short tekrid4
  2368. tekrid3:mov    al,'6'
  2369.     stosb                ; say 16
  2370. tekrid4:mov    al,'n'            ; end of string
  2371.     stosb
  2372.     call    outstrng        ; send the string
  2373.     pop    es
  2374.     ret
  2375. tekrid    endp
  2376.  
  2377. tekprpt    proc    near
  2378.     cmp    nparam,1        ; one or more numeric parameters?
  2379.     jb    tekrprx            ; b = no
  2380.     cmp    param,2            ; "CSI 2 $ u"?
  2381.     jne    tekrprx            ; ne = no
  2382.     cmp    inter,'$'        ; correct Intermediate?
  2383.     jne    tekrprx            ; ne = no
  2384.     call    far ptr tekrpt        ; invoke the palette report generator
  2385. tekrprx:ret
  2386. tekprpt    endp
  2387.  
  2388. tekrpt    proc    FAR            ; report VT340 color palette
  2389.     push    es            ; DECRQTSR(request), DECCTR(response)
  2390.     push    ds
  2391.     pop    es
  2392.     push    di
  2393.     push    bx
  2394.     cld
  2395.     mov    di,offset rdbuf        ; a temp buffer
  2396.     mov    al,escape        ; report
  2397.     stosb
  2398.     cmp    plotptr,offset pltcga    ; using CGA style graphics?
  2399.     je    tekrpt9            ; e = yes
  2400.     cmp    graph_mode,mono        ; pure mono text system?
  2401.     je    tekrpt9            ; e = yes
  2402.     cmp    graph_mode,monoega    ; monochrome monitor on ega?
  2403.     jne    tekrpt10        ; ne = no
  2404. tekrpt9:mov    ax,'0P'            ; b/w systems report DCS 0 $ s ST
  2405.     stosw
  2406.     mov    ax,'s$'
  2407.     stosw
  2408.     call    outstrng
  2409.     jmp    tekrpt8
  2410.  
  2411. tekrpt10:mov    ax,'2P'            ; color systems report DCS 2 $ s...ST
  2412.     stosw
  2413.     mov    ax,'s$'
  2414.     stosw                ; "ESC [ 2 $ s"
  2415.     call    outstrng        ; output this string
  2416.     mov    cx,16            ; number of palette registers to do
  2417.     xor    bx,bx            ; begin with color palette 0
  2418. tekrpt1:push    bx            ; save palette index
  2419.     push    cx            ; save loop counter
  2420.     mov    di,offset rdbuf        ; buffer
  2421.     mov    ax,bx            ; palette number
  2422.     call    dec2di            ; palette register, to buffer
  2423.     mov    ax,'2;'            ; ";2;" means sending RGB values
  2424.     stosw
  2425.     mov    al,';'
  2426.     stosb
  2427.     mov    ah,colpal[bx]        ; get palette iRGB
  2428.     mov    al,rgbbold/4        ; assume dark red for bold black
  2429.     cmp    ah,8            ; bold black?
  2430.     je    tekrpt2            ; e = yes
  2431.     xor    al,al
  2432.     test    ah,4            ; red?
  2433.     jz    tekrpt2            ; z = no
  2434.     mov    al,rgbbold/2        ; say red, 40%
  2435.     test    ah,8            ; bold?
  2436.     jz    tekrpt2            ; z = no
  2437.     mov    al,rgbbold        ; more if bold
  2438. tekrpt2:push    ax
  2439.     xor    ah,ah            ; clear high byte
  2440.     call    dec2di            ; store red
  2441.     pop    ax
  2442.     mov    al,';'            ; separator
  2443.     stosb
  2444.     mov    al,rgbbold/4        ; assume dark green for bold black
  2445.     cmp    ah,8            ; bold black?
  2446.     je    tekrpt4            ; e = yes
  2447.     xor    al,al
  2448.     test    ah,2            ; green?
  2449.     jz    tekrpt4            ; z = no
  2450.     mov    al,rgbbold/2        ; say green, 40%
  2451.     test    ah,8            ; bold?
  2452.     jz    tekrpt4            ; z = no
  2453.     mov    al,rgbbold        ; more if bold
  2454. tekrpt4:push    ax
  2455.     xor    ah,ah            ; clear high byte
  2456.     call    dec2di            ; store green
  2457.     pop    ax
  2458.     mov    al,';'            ; separator
  2459.     stosb
  2460.     mov    al,rgbbold/4        ; assume dark blue for bold black
  2461.     cmp    ah,8            ; bold black?
  2462.     je    tekrpt6            ; e = yes
  2463.     xor    al,al
  2464.     test    ah,1            ; blue?
  2465.     jz    tekrpt6            ; z = no
  2466.     mov    al,rgbbold/2        ; say blue, 40%
  2467.     test    ah,8            ; bold?
  2468.     jz    tekrpt6            ; z = no
  2469.     mov    al,rgbbold        ; more if bold
  2470. tekrpt6:xor    ah,ah            ; clear high byte
  2471.     call    dec2di            ; store blue
  2472.     pop    cx            ; recover loop counter
  2473.     cmp    cx,1            ; doing last item?
  2474.     je    tekrpt7            ; e = yes, do not send another "/"
  2475.     mov    al,'/'            ; separator
  2476.     stosb
  2477. tekrpt7:push    cx
  2478.     call    outstrng        ; output this string
  2479.     pop    cx
  2480.     pop    bx            ; recover palette index
  2481.     inc    bx            ; ready for next palette
  2482.     dec    cx
  2483.     jz    tekrpt8            ; z = done
  2484.     jmp    tekrpt1            ; do all palettes
  2485. tekrpt8:mov    al,escape        ; DCS terminator ST
  2486.     call    outmodem
  2487.     mov    al,'\'
  2488.     call    outmodem
  2489.     pop    bx
  2490.     pop    di
  2491.     pop    es
  2492.     ret
  2493. tekrpt    endp
  2494.  
  2495. ; Output string in rdbuf. Enter with di pointing at last byte+1. Return
  2496. ; with di at the same place.
  2497. outstrng proc    near
  2498.     mov    ttyact,0        ; group output for network
  2499.     push    cx
  2500.     mov    cx,di            ; compute length
  2501.     mov    di,offset rdbuf        ; start of buffer
  2502.     sub    cx,di            ; start of buffer
  2503.     jle    outstn3            ; le = nothing to do
  2504. outstn1:mov    al,[di]
  2505.     inc    di
  2506.     cmp    cx,1            ; last character?
  2507.     ja    outstn2            ; a = no
  2508.     mov    ttyact,1        ; end group output for network
  2509. outstn2:call    outmodem        ; send the byte
  2510.     loop    outstn1            ; do the string
  2511. outstn3:pop    cx
  2512.     ret
  2513. outstrng endp
  2514.  
  2515. ; Process Device Control Strings (DCS or ESC P lead-in chars, parameters,
  2516. ; and Final character already read). Prepare to gather strings.
  2517. tekdcs    proc    near
  2518.     mov    dcsstrf,al        ; record Final char
  2519.     mov    emubufc,0        ; clear string count
  2520.     mov    cx,maxparam        ; number of DCS parameters
  2521.     push    si            ; copy these to the DCS area so that
  2522.     push    di            ;  they are not lost when an ST is
  2523.     push    es            ;  parsed (parser clears ESC items)
  2524.     push    ds
  2525.     pop    es
  2526.     mov    si,offset param        ; ESC paramater storage area, numeric
  2527.     mov    di,offset dparam    ; DCS parameter storage area, numeric
  2528.     cld
  2529.     rep    movsw            ; copy set to DCS storage area
  2530.     mov    cl,lparam         ; copy letter Paramter
  2531.     mov    dlparam,cl
  2532.     mov    cx,maxinter        ; number of intermediate characters
  2533.     mov    si,offset inter        ; source
  2534.     mov    di,offset dinter    ; destination
  2535.     rep    movsb
  2536.     mov    si,nparam        ; number of parameters
  2537.     mov    dnparam,si
  2538.     mov    si,ninter
  2539.     mov    dninter,si        ; number of intermediates
  2540.     pop    es
  2541.     pop    di
  2542.     pop    si
  2543.     cmp    dcsstrf,'q'        ; Sixel Graphics?
  2544.     jne    tekdcs3            ; ne = no
  2545.     mov    ttstate,offset tekgets    ; get string as next state
  2546.     mov    al,chcontrol        ; opaque/transparent char writing
  2547.     or    al,al            ; is it being set?
  2548.     jz    tekdcs2            ; z = no, do not force condition
  2549.     mov    bscontrol,al        ; set destructive BS control
  2550.     mov    spcontrol,al        ; set destructive SPACE control
  2551. tekdcs2:ret
  2552. tekdcs3:cmp    dcsstrf,'p'        ; restore color palette (DCS 2 $ p)?
  2553.     jne    tekdcs1            ; ne = no
  2554.     cmp    nparam,1        ; just one parameter?
  2555.     jne    tekdcs1            ; ne = no
  2556.     cmp    param,2            ; correct parameter?
  2557.     jne    tekdcs1            ; ne = no
  2558.     cmp    dinter,'$'        ; correct intermediate?
  2559.     jne    tekdcs1            ; ne = no
  2560.     mov    ttstate,offset tekrcol    ; get color report as next state
  2561.     ret
  2562. tekdcs1:mov    ttstate,offset tekdcsnul ; consume unknown DCS
  2563.     ret
  2564. tekdcs    endp
  2565.  
  2566. ; Read and discard OSC (ESC ]), PM (ESC ^), APC (ESC _) control sequences
  2567. ; through final ST (ESC \) terminator.
  2568. tekdcsnul proc    near
  2569.     mov    dcsstrf,0        ; simulate a null (dummy) Final char
  2570.     cmp    al,20h            ; control char?
  2571.     jae    tekdcsnu1        ; ae = no, skip
  2572.     jmp    tekctl            ; do control char
  2573. tekdcsnu1:ret
  2574. tekdcsnul endp
  2575.  
  2576. ; State machine to process DCS strings of type "p" (restore color palette)
  2577. ; Enter with "p" char in AL. Callable from outside this file via tekrpal.
  2578. tekrcol    proc    near
  2579.     mov    ttstate,offset tekrco1    ; next state is get parameter
  2580.     push    ax            ; save character
  2581.     push    es
  2582.     push    ds
  2583.     pop    es
  2584.     push    di
  2585.     mov    cx,5            ; five words
  2586.     xor    ax,ax
  2587.     mov    di,offset param        ; clear parameters Pc,Pu,Px,Py,Pz
  2588.     cld
  2589.     rep    stosw
  2590.     pop    di
  2591.     pop    es
  2592.     mov    nparam,0        ; work on initial parameter first
  2593.     pop    ax
  2594. tekrco1:cmp    al,escape        ; escape, as in ESC \?
  2595.     je    tekrcost        ; e = yes, finish command
  2596.     cmp    al,' '            ; control code?
  2597.     jb    tekrco5            ; b = yes, ignore it
  2598.     push    bx
  2599.     mov    bx,nparam        ; parameter number
  2600.     shl    bx,1            ; make it a word index
  2601.     mov    cx,param[bx]        ; accumulated parameter
  2602.     call    getdec            ; accumulate decimal value
  2603.     mov    param[bx],cx        ; remember accumulation
  2604.     pop    bx
  2605.     jnc    tekrco5            ; nc = got a digit char
  2606.     inc    nparam            ; say have another complete parameter
  2607.     cmp    al,'/'            ; this kind of separator?
  2608.     je    tekrco3            ; e = yes, finish
  2609.     cmp    al,';'            ; break char is separator?
  2610.     jne    tekrco4            ; ne = no, decode current sequence
  2611. tekrco3:cmp    nparam,5        ; have 5 params already?
  2612.     jb    tekrco5            ; n = no, continue reading
  2613. tekrco4:call    tekgco4            ; process parameters in msgibm file
  2614.     mov    ttstate,offset tekrcol    ; next state is get parameter
  2615. tekrco5:ret                ; start over on next field
  2616.  
  2617. tekrcost:                ; get here on ST
  2618.     cmp    nparam,5        ; enough parameters to finish cmd?
  2619.     jb    tekrcos1        ; b = no, abandon it
  2620.     call    tekgco4            ; update from last data item
  2621.     mov    al,escape
  2622. tekrcos1:jmp    tekctl
  2623. tekrcol    endp
  2624.  
  2625. ; State machine to process DCS strings of type "q" (Sixel Command and Data)
  2626. ; Enter with new char in AL.
  2627. tekgets    proc    near
  2628.     mov    ttstate,offset tekgets    ; set state to ourselves
  2629.     mov    nparam,0        ; say no pending control sequences
  2630.     cmp    al,20h            ; control character?
  2631.     jae    tekgsch            ; ae = no, analyze
  2632.     jmp    tekctl            ; do control char
  2633.                     ; single sixel char state
  2634. tekgsch:cmp    al,3fh            ; legal sixel data char?
  2635.     jb    tekgrpt            ; b = no, try repeated char
  2636.     mov    cx,1            ; repeat count of 1
  2637.     jmp    sixplt            ; plot the six dots
  2638.  
  2639. tekgrpt:cmp    al,'!'            ; repeated char?
  2640.     jne    tekgera            ; ne = no
  2641.     mov    ttstate,offset tekgrpt0    ; next state is get repeat parameter
  2642.     mov    param,0
  2643.     mov    nparam,0
  2644.     ret
  2645.  
  2646. tekgrpt0:cmp    al,' '            ; control char?
  2647.     jae    tekgrpt1        ; ae = no
  2648.     jmp    tekctl            ; process control char
  2649. tekgrpt1:mov    cx,param        ; first param is used here
  2650.     call    getdec            ; accumulate repeat count to cx
  2651.     mov    param,cx        ; retain current count
  2652.     jc    tekgrpt2        ; c = ended on non-numeric
  2653.     ret                ; get more characters
  2654. tekgrpt2:cmp    al,3fh            ; break char, is it a sixel datum?
  2655.     jb    tekgrpt3        ; b = no, it is illegal, quit
  2656.     call    sixplt            ; plot cx versions of the six bits
  2657.     mov    ttstate,offset tekgets    ; return to sixel idle state
  2658.     ret
  2659. tekgrpt3:jmp    short tekgets        ; reprocess break character
  2660.  
  2661. tekgera:cmp    al,22h            ; double quote raster attribute?
  2662.     jne    tekgco            ; ne = no, try color
  2663.     mov    param,0            ; clear parameters, Pan
  2664.     mov    param[2],0        ; Pad
  2665.     mov    param[4],0        ; Ph
  2666.     mov    param[6],0        ; Pv
  2667.     mov    nparam,0        ; work on initial parameter first
  2668.     mov    ttstate,offset tekgra1    ; next state is get parameter
  2669.     ret
  2670. tekgra1:cmp    al,' '            ; control char?
  2671.     jb    tekgra2            ; b = yes, finish this work first
  2672.     push    bx
  2673.     mov    bx,nparam        ; parameter number
  2674.     shl    bx,1            ; make it a word index
  2675.     mov    cx,param[bx]        ; accumulated parameter
  2676.     call    getdec            ; accumulate decimal value into cx
  2677.     mov    param[bx],cx        ; remember accumulation
  2678.     pop    bx
  2679.     jc    tekgra2            ; c = failure to get a digit char
  2680.     ret
  2681. tekgra2:inc    nparam            ; say have another complete parameter
  2682.     cmp    nparam,4        ; got all four params Pan,Pad,Ph,Pv?
  2683.     je    tekgra4            ; e = yes
  2684.     cmp    al,';'            ; break char is separator?
  2685.     jne    tekgra3            ; ne = no, quit now
  2686.     ret                ; get more characters
  2687. tekgra3:jmp    tekgets            ; restart with the break char
  2688.  
  2689. tekgra4:;;; perform raster attributes work here
  2690.     mov    ttstate,offset tekgets
  2691.     ret
  2692.  
  2693. tekgco:    cmp    al,'#'            ; color introducer?
  2694.     je    tekgco0            ; e = yes
  2695.     jmp    tekgcr            ; ne = no
  2696. tekgco0:mov    ttstate,offset tekgco1    ; next state is get parameter
  2697.     push    ds
  2698.     pop    es
  2699.     push    di
  2700.     mov    cx,5            ; five words
  2701.     xor    ax,ax
  2702.     mov    di,offset param        ; clear parameters Pc,Pu,Px,Py,Pz
  2703.     cld
  2704.     rep    stosw
  2705.     pop    di
  2706.     pop    es
  2707.     mov    nparam,0        ; work on initial parameter first
  2708.     ret
  2709. tekgco1:cmp    al,' '            ; control char?
  2710.     jb    tekgco2            ; b = yes, finish this work first
  2711.     push    bx
  2712.     mov    bx,nparam        ; parameter number
  2713.     shl    bx,1            ; make it a word index
  2714.     mov    cx,param[bx]        ; accumulated parameter
  2715.     call    getdec            ; accumulate decimal value
  2716.     mov    param[bx],cx        ; remember accumulation
  2717.     pop    bx
  2718.     jc    tekgco2            ; c = failure to get a digit char
  2719.     ret
  2720. tekgco2:inc    nparam            ; say have another complete parameter
  2721.     cmp    al,';'            ; break char is separator?
  2722.     jne    tekgco3            ; ne = no, decode current sequence
  2723.     cmp    nparam,5        ; have 5 params already?
  2724.     jae    tekgco3            ; ae = yes, process them now
  2725.     ret                ;  else get more parameters
  2726. tekgco3:cmp    nparam,1        ; just one parameter?
  2727.     je    tekgco3a        ; e = yes, select from palette
  2728.     jb    tekgco3b        ; b = none, reprocess as sixel
  2729.     call    tekgco4            ; process parameters
  2730.     mov    nparam,0        ; clear parameters
  2731.     jmp    tekgets            ; reprocess char as sixel
  2732.  
  2733. tekgco3a:push    bx            ; select color from palette
  2734.     mov    bx,param[0]        ; get color number
  2735.     xor    bh,bh            ; make 0-255
  2736.     mov    bl,colpal[bx]        ; get color from palette
  2737.     mov    gfcol,bl        ; set active foreground color
  2738.     pop    bx
  2739.     push    ax            ; save char in al
  2740.     call    fixcolor        ; fix color too, if req'd
  2741.     pop    ax
  2742. tekgco3b:mov    nparam,0        ; clear parameters
  2743.     jmp    tekgets            ; reprocess char as sixel
  2744.  
  2745.                     ; set IRGB/HLS color to color palette
  2746. tekgco4:cmp    param[2],2        ; Pu (1-2), wanted RBG?
  2747.     je    tekgco4b        ; e = yes
  2748.     cmp    param[2],1        ; Pu, wanted HLS?
  2749.     jne    tekgco4a        ; ne = no
  2750.     jmp    tekgco9            ; do HLS scheme
  2751. tekgco4a:mov    nparam,0        ; clear parameters
  2752.     ret                ; return without doing work
  2753. tekgco4b:push    ax            ; iRGB, save break char in al
  2754.     mov    ax,param[4]        ; red
  2755.     mov    bx,param[6]        ; green
  2756.     mov    dx,param[8]        ; blue
  2757.     xor    cx,cx            ; cl has final color index, 0-15
  2758.     or    ch,al
  2759.     or    ch,bl
  2760.     or    ch,dl            ; any color?
  2761.     jcxz    tekgco7            ; z = no, use cl = 0 black
  2762.     cmp    ax,rgbbold        ; setting red bold?
  2763.     jae    tekgco4c        ; ae = yes
  2764.     cmp    bx,rgbbold        ; setting green bold?
  2765.     jae    tekgco4c        ; ae = yes
  2766.     cmp    dx,rgbbold        ; setting blue bold?
  2767.     jb    tekgco4d        ; b = no
  2768. tekgco4c:mov    cl,8            ; set the bold bit
  2769.     jmp    tekgco4e        ; do hues
  2770. tekgco4d:cmp    ax,rgbbold/2        ; all in dim intensities?
  2771.     jae    tekgco4e        ; ae = no
  2772.     cmp    bx,rgbbold/2        ; green?
  2773.     jae    tekgco4e        ; ae = no
  2774.     cmp    dx,rgbbold/2        ; blue
  2775.     jae    tekgco4e        ; ae = no
  2776.     mov    cl,8            ; use bold black (dark grey)
  2777.     jmp    tekgco7
  2778. tekgco4e:or    ax,ax            ; Hues, any red?
  2779.     jz    tekgco5            ; z = no
  2780.     or    cl,4            ; set red bit
  2781.     cmp    ax,rgbbold/2        ; dim?
  2782.     jae    tekgco5            ; ae = no
  2783.     test    cl,8            ; doing bold?
  2784.     jz    tekgco5            ; z = no
  2785.     xor    cl,4            ; clear dim red
  2786. tekgco5:or    bx,bx            ; any green?
  2787.     jz    tekgco6            ; z = no
  2788.     or    cl,2            ; set green bit
  2789.     cmp    bx,rgbbold/2        ; dim?
  2790.     jae    tekgco6            ; ae = no
  2791.     test    cl,8            ; doing bold?
  2792.     jz    tekgco6            ; z = no
  2793.     xor    cl,2            ; clear dim green
  2794. tekgco6:or    dx,dx            ; any blue?
  2795.     jz    tekgco7            ; z = no
  2796.     or    cl,1            ; set blue bit
  2797.     cmp    dx,rgbbold/2        ; dim?
  2798.     jae    tekgco7            ; ae = no
  2799.     test    cl,8            ; doing bold?
  2800.     jz    tekgco7            ; z = no
  2801.     xor    cl,1            ; clear dim blue
  2802. tekgco7:push    bx
  2803.     mov    bx,param[0]        ; Pc, color palette being defined
  2804.     xor    bh,bh            ; make 0-255
  2805.     mov    colpal[bx],cl        ; store color code in palette
  2806.     pop    bx
  2807.     mov    nparam,0        ; say done with this sequence
  2808.     pop    ax            ; recover break char in al
  2809.     ret
  2810.  
  2811.                     ; Hue, Lightness, Saturation
  2812. tekgco9:push    ax            ; save break char
  2813.     xor    cl,cl            ; assummed color of black
  2814.     mov    ax,param[4]        ; Px, Hue, 60 degree slices
  2815.     push    cx
  2816.     mov    cx,360            ; do modulo 360
  2817.     xor    dx,dx            ; clear high order numerator
  2818.     div    cx            ; dx has remainder
  2819.     pop    cx
  2820.     mov    ax,dx            ; put remainder in ax
  2821.     cmp    ax,30            ; blue?
  2822.     jae    tekgco10        ; ae = no
  2823.     or    cl,1            ; blue
  2824.     jmp    short tekgco15
  2825. tekgco10:cmp    ax,90            ; magenta?
  2826.     jae    tekgco11        ; ae = no
  2827.     or    cl,1+4            ; magenta = blue + red
  2828.     jmp    short tekgco15
  2829. tekgco11:cmp    ax,150            ; red?
  2830.     jae    tekgco12        ; ae = no
  2831.     or    cl,4            ; red
  2832.     jmp    short tekgco15
  2833. tekgco12:cmp    ax,210            ; yellow?
  2834.     jae    tekgco13        ; ae = no
  2835.     or    cl,4+2            ; yellow = reg + green
  2836.     jmp    short tekgco15
  2837. tekgco13:cmp    ax,270            ; cyan?
  2838.     jae    tekgco14        ; ae = no
  2839.     or    cl,2+1            ; cyan = green+blue
  2840.     jmp    short tekgco15
  2841. tekgco14:or    cl,1            ; blue
  2842.  
  2843. tekgco15:mov    ax,param[6]        ; Py, Lightness
  2844.     mov    dx,param[8]        ; Pz, Saturation
  2845.     cmp    ax,86            ; lightness is max?
  2846.     jb    tekgco16        ; b = no
  2847.     mov    cl,0fh            ; greater than 85% means bold white
  2848.     jmp    short tekgco22
  2849. tekgco16:cmp    ax,71            ; high lightness?
  2850.     jb    tekgco17        ; b = not that light
  2851.     or    cl,8            ; turn on bold bit
  2852.     cmp    dx,51            ; saturated?
  2853.     jae    tekgco22        ; ae = yes
  2854.     mov    cl,0fh            ; low saturation yields bold white
  2855.     jmp    short tekgco22
  2856. tekgco17:cmp    ax,57            ; central coloring, upper?
  2857.     jb    tekgco18        ; b = no
  2858.     or    cl,8            ; turn on bold bit
  2859.     cmp    dx,51            ; saturated?
  2860.     jae    tekgco22        ; ae = yes, use bold colors
  2861.     mov    cl,7            ; s < 50 is dim white
  2862.     cmp    dx,11            ; saturated less than 11%
  2863.     jae    tekgco22        ; ae = no
  2864.     xor    cl,cl            ; s < 11 is black here
  2865.     jmp    short tekgco22
  2866. tekgco18:cmp    ax,43            ; dim colors, upper?
  2867.     jb    tekgco19        ; b = no
  2868.     or    cl,8            ; turn on bold bit
  2869.     cmp    dx,51            ; saturated?
  2870.     jae    tekgco22        ; ae = yes, use bold colors
  2871.     and    cl,not 8        ; use dim colors
  2872.     jmp    short tekgco22
  2873. tekgco19:cmp    ax,29            ; dim colors, lower?
  2874.     jb    tekgco20        ; b = no
  2875.     cmp    dx,51            ; saturated?
  2876.     jae    tekgco22        ; ae = yes
  2877.     mov    cl,7            ; use dim white
  2878.     jmp    short tekgco22
  2879. tekgco20:cmp    ax,14            ; dark colors?
  2880.     jb    tekgco21        ; b = no
  2881.     cmp    dx,51            ; saturated?
  2882.     jae    tekgco22        ; ae = yes
  2883. tekgco21:xor    cl,cl            ; use black
  2884. tekgco22:push    bx
  2885.     mov    bx,param[0]        ; Pc, color palette being defined
  2886.     xor    bh,bh            ; get palette 0-255
  2887.     mov    colpal[bx],cl        ; store color code in palette
  2888.     pop    bx
  2889.     mov    nparam,0        ; say done with this sequence
  2890.     pop    ax            ; recover break char
  2891.     ret
  2892.  
  2893. tekgcr:    cmp    al,'$'            ; graphics carriage return?
  2894.     jne    tekgnl            ; ne = no
  2895.     mov    x_coord,0        ; go to left margin, no line feed
  2896.     ret
  2897. tekgnl:    cmp    al,'-'            ; graphics new line?
  2898.     jne    tekgunk            ; ne = no
  2899.     mov    x_coord,0        ; go to left margin, no line feed
  2900.     mov    ax,y_coord        ; bottom of char cell
  2901.     add    ax,6            ; go down 6 dots
  2902.     cmp    ax,ybot            ; wrapping below bottom?
  2903.     jbe    tekgnl1            ; be = no
  2904.     mov    ax,ybot            ; stop at bottom (leaves 2 dots free!)
  2905. tekgnl1:mov    y_coord,ax
  2906.     ret
  2907. tekgunk:mov    ttstate,offset tekgets    ; unknown char
  2908.     cmp    al,' '            ; control char?
  2909.     jae    tekgun1            ; ae = no
  2910.     jmp    tektxt            ; process control char
  2911. tekgun1:ret                ; ignore the unknown char
  2912. tekgets    endp
  2913.  
  2914. ; Accumulate decimal value in CX using ascii char in al.
  2915. ; Return with value in CX. Return carry clear if ended on a digit,
  2916. ; return carry set and ascii char in al if ended on a non-digit.
  2917. getdec    proc    near
  2918.     cmp    al,'0'            ; a number?
  2919.     jb    getdecx            ; b = no, quit
  2920.     cmp    al,'9'
  2921.     ja    getdecx            ; a = not a number, quit
  2922.     sub    al,'0'            ; remove ascii bias
  2923.     xchg    cx,ax            ; put char in cx, decimal value in ax
  2924.     push    dx            ; save reg
  2925.     mul    ten            ; times ten for a new digit
  2926.     pop    dx            ; recover reg, ignore overflow
  2927.     add    al,cl            ; add current digit
  2928.     adc    ah,0            ; 16 bits worth
  2929.     xchg    ax,cx            ; rpt cnt back to cx
  2930.     clc                ; say found a digit
  2931.     ret
  2932. getdecx:stc                ; say non-digit (in al)
  2933.     ret
  2934. getdec    endp
  2935.  
  2936. ; Display lower six bits of AL in a column, a sixel datum. Do CX times.
  2937. ; Location is PC text cursor, x_coord, y_coord, with least significant bit
  2938. ; at the top (at y_coord-8). Increments x_coord by one for each interation
  2939. ; but stops at right margin and does not change y_coord. If dparam[2], P2,
  2940. ; is 1 then color pattern 0 bits in current background, else skip them.
  2941. sixplt    proc    near
  2942.     or    cx,cx            ; repeat count present?
  2943.     jnz    sixplt1            ; nz = yes
  2944.     ret
  2945. sixplt1:push    ax
  2946.     push    bx
  2947.     push    linepat            ; save line pattern
  2948.     sub    al,3fh            ; remove ascii bias from sixel char
  2949.     xor    ah,ah
  2950.     mov    linepat,ax        ; our dot pattern in lower 6 bits
  2951.     mov    di,y_coord        ; text bottom cell line
  2952.     sub    di,charhgt        ; go to top of charhgt high char cell
  2953.     jnc    sixplt2            ; nc = no wrap over top
  2954.     xor    di,di            ; limit to screen top
  2955. sixplt2:mov    bx,di            ; bx = ending y
  2956.     add    bx,5            ; plus our six dots (goes down screen)
  2957.     cmp    bx,ybot            ; wrapping below bottom?
  2958.     jbe    sixplt3            ; be = no
  2959.     mov    bx,ybot            ; stop at bottom
  2960. sixplt3:mov    ax,x_coord        ; left edge of text cell
  2961.     mov    si,ax            ; si=starting, ax=ending PC x coord
  2962.     add    xmax,7            ; refer to right edge, not right char
  2963.     push    es            ; set up for dot plotting, save regs
  2964.     push    si
  2965.     push    di
  2966.     push    dx
  2967.     push    bp
  2968.     mov    dl,ccode        ; existing pixel op code
  2969.     push    dx            ; save ccode around line drawing
  2970.     mov    ccode,pixor        ; set OR pixel op for use by plot()
  2971.     cmp    gfcol,0            ; all black dots?
  2972.     jne    sixplt3a        ; ne = no
  2973.     mov    ccode,pixfor        ; yes, force overwriting to nulls
  2974. sixplt3a:push    cx
  2975.     call    psetup            ; setup display and es:di and es:si
  2976.     pop    cx
  2977.                     ; start sixel repeat loop
  2978. sixplt4:push    cx            ; save sixel repeat count
  2979.     push    di            ; save y starting screen address
  2980.     mov    bp,linepat        ; store active line pattern word in BP
  2981.     mov    cx,6            ; six dots per sixel
  2982.                     ; start six dot loop
  2983. sixplt5:push    cx            ; save dot count
  2984.     mov    cl,pixFor        ; assume foreground coloring
  2985. ;;;;    test    bp,1            ; bit to be plotted, is it a 1?
  2986. ;;;;    jnz    sixplt6            ; nz = yes, plot in foreground color
  2987. ;;;;    cmp    dparam[2],1        ; P2 = 1, skip over 0's?
  2988. ;;;;    je    sixplt6            ; e = yes
  2989. ;;;;    mov    cl,pixbak        ; use background write pixel op
  2990. ;;;;    or    bp,1            ; set pattern bit so we see a pixel
  2991. sixplt6:mov    ccode,cl        ; desired pixel op
  2992.     call    plotptr            ; plot a dot if it is a 1
  2993.     call    pincy            ; next dot down the screen (di)
  2994.     pop    cx            ; recover dot counter
  2995.     loop    sixplt5            ; do each of 6 dots
  2996.                     ;
  2997.     pop    di            ; recover starting y screen coord
  2998.     pop    cx            ; recover repeat count
  2999.     cmp    ax,xmax            ; off right edge?
  3000.     jae    sixplt8            ; ae = yes
  3001.     inc    ax            ; move right one pixel
  3002.     inc    si            ; start and stop x's
  3003. sixplt8:loop    sixplt4            ; repeat sixel cx times
  3004.     pop    dx
  3005.     mov    ccode,dl        ; recover main color code
  3006.     pop    bp
  3007.     pop    dx
  3008.     pop    di
  3009.     pop    si
  3010.     pop    es
  3011.     mov    x_coord,ax        ; new text starting x coord
  3012.     sub    xmax,7            ; restore to right most char cell
  3013.     pop    linepat            ; restore normal line pattern
  3014.     pop    bx
  3015.     pop    ax
  3016.     ret
  3017. sixplt    endp
  3018.  
  3019. ; Process ST or ESC \  String Terminator.
  3020. tekgotst proc    near
  3021.     mov    dcsstrf,0        ; clear DCS Final char
  3022.     mov    nparam,0
  3023.     mov    ninter,0
  3024.     mov    al,colpal[7]        ; reset foreground to palette 7
  3025.     mov    gfcol,al
  3026.     mov    al,colpal[0]        ; and background to palette 0
  3027.     mov    gbcol,al
  3028.     call    fixcolor        ; and fix up coloring, if req'd
  3029.     mov    prestate,offset tektxt    ; reset state of emulator to normal
  3030.     mov    ttstate,offset tektxt
  3031.     call    setcursor        ; restore text cursor
  3032.     ret
  3033. tekgotst endp
  3034.  
  3035. TEKLINE    proc    near            ; GS line drawing
  3036.     cmp    al,' '            ; control char?
  3037.     jae    teklin3            ; ae = no
  3038.     cmp    al,CR            ; exit drawing on CR,LF,RS,US,FS,CAN
  3039.     je    teklin2            ; e = yes, a cr
  3040.     cmp    al,LF            ; these terminate line drawing cmds
  3041.     je    teklin2
  3042.     cmp    al,FS            ; <FS>
  3043.     je    teklin2
  3044.     cmp    al,GS            ; <GS>
  3045.     je    teklin2
  3046.     cmp    al,RS            ; <RS>
  3047.     je    teklin2
  3048.     cmp    al,US            ; <US>
  3049.     je    teklin2
  3050.     cmp    al,CAN            ; and <CAN>
  3051.     je    teklin2            ; BUT ignore other control chars
  3052.     cmp    al,escape        ; escape?
  3053.     je    teklin1            ; e = yes, come back to this state
  3054.     ret                ; ignore stray control char
  3055. teklin1:jmp    tekctl            ; process control char
  3056. teklin2:mov    lastc,0            ; clear last drawing coordinate flag
  3057.     mov    visible,0        ; invisible again
  3058.     jmp    tektxt            ; process char under text mode
  3059.  
  3060. teklin3:call    tekxyc            ; parse coordinates from input bytes
  3061.     jc    teklin4            ; c = done, do the plotting
  3062.     ret                ; nc = not done yet
  3063. teklin4:mov    cl,visible        ; get moveto or drawto variable
  3064.     call    tekdraw            ; move that point
  3065.     mov    visible,1        ; say next time we draw
  3066.     ret
  3067. TEKLINE    endp
  3068.     
  3069. TEKPNT    proc    near            ; FS plot single point
  3070.     cmp    al,' '            ; control char?
  3071.     jae    tekpnt3            ; ae = no
  3072.     cmp    al,CR            ; exit drawing on CR,LF,RS,US,FS,CAN
  3073.     je    tekpnt2            ; e = yes, a cr
  3074.     cmp    al,LF             ; these terminate line drawing cmds
  3075.     je    tekpnt2
  3076.     cmp    al,FS            ; <FS>
  3077.     je    tekpnt2
  3078.     cmp    al,GS            ; <GS>
  3079.     je    tekpnt2
  3080.     cmp    al,RS            ; <RS>
  3081.     je    tekpnt2
  3082.     cmp    al,US            ; <US>
  3083.     je    tekpnt2
  3084.     cmp    al,CAN            ; and <CAN>
  3085.     je    tekpnt2            ; BUT ignore other control chars
  3086.     cmp    al,escape        ; escape?
  3087.     je    tekpnt1            ; e = yes
  3088.     clc
  3089.     ret                ; ignore stray control char
  3090. tekpnt1:jmp    tekctl            ; process control char
  3091. tekpnt2:mov    lastc,0            ; clear last drawing coordinate flag
  3092.     mov    visible,0        ; invisible again
  3093.     jmp    tektxt            ; process char under text mode
  3094.  
  3095. tekpnt3:call    tekxyc            ; parse coordinates
  3096.     jc    tekpnt4            ; c = done, do the plotting
  3097.     ret                ; nc = not done yet
  3098. tekpnt4:xor    cl,cl            ; do not draw
  3099.     call    tekdraw            ; move to the point
  3100.     mov    ax,si            ; copy starting point to end point
  3101.     mov    bx,di            ; ax,bx,si,di are in PC coordinates
  3102.     mov    cl,1            ; make plot visible
  3103.     call    line            ; draw the dot
  3104.     mov    visible,0        ; return to invisibility
  3105.     clc
  3106.     ret
  3107. TEKPNT    endp
  3108.  
  3109. ; Decode graphics x,y components. Returns carry set to say have all
  3110. ; components for a line, else carry clear. Understands 4014 lsb extensions.
  3111. ; Permits embedded escape sequences.
  3112. TEKXYC    proc    near
  3113.     cmp    al,40h
  3114.     jb    tekgh2            ; 20-3F are HIX or HIY
  3115.     cmp    al,60h            ; 40-5F are LOX (causes beam movement)
  3116.     jb    tekgh4            ; 60-7F are LOY
  3117.                     ; extract low-order 5 bits of Y coord
  3118.     mov    ah,tek_loy        ; copy previous LOY to MSB (4014)
  3119.     mov    tek_lsb,ah
  3120.     and    al,1Fh            ; LOY is 5 bits
  3121.     mov    tek_loy,al
  3122.     cmp    lastc,loy        ; 2nd LOY in a row?
  3123.     je    tekgh1            ; e = yes, then LSB is valid
  3124.     mov    tek_lsb,0        ; 1st one, clear LSB
  3125. tekgh1:    mov    lastc,loy        ; LOY seen, expect HIX (instead of HIY)
  3126. tekgh0:    clc                ; c clear = not completed yet
  3127.     ret
  3128. tekghx:    mov    ttstate,offset tektxt    ; go to TEKTXT next time
  3129.     mov    lastc,0            ; clear last drawing coordinate flag
  3130.     or    status,txtmode        ; set text mode in status byte
  3131.     clc                ; carry clear means done
  3132.     ret
  3133.  
  3134.         ; Extract high-order 5 bits (X or Y, depending on lastc)
  3135. tekgh2: and    ax,1Fh            ; just 5 bits
  3136.     mov    cl,5
  3137.     shl    ax,cl            ; shift over 5 bits
  3138.     cmp    lastc,loy        ; was last coordinate a low-y?
  3139.     je    tekgh3            ; e = yes, parse hix
  3140.     mov    tek_hiy,ax        ; this byte has HIY
  3141.     mov    lastc,hiy
  3142.     clc
  3143.     ret
  3144. tekgh3: mov    tek_hix,ax        ; this byte has HIX
  3145.     mov    lastc,hix
  3146.     clc
  3147.     ret
  3148. tekgh4: and    al,1Fh            ; just 5 bits
  3149.     mov    tek_lox,al
  3150.     mov    lastc,lox
  3151.     mov    ax,tek_hix        ; combine HIX*32
  3152.     or    al,tek_lox        ;  with LOX
  3153.     mov    bx,tek_hiy        ; same for Y
  3154.     or    bl,tek_loy
  3155.     stc                ; set c to say completed operation
  3156.     ret
  3157. TEKXYC    endp
  3158.  
  3159. TEKRLIN    proc    near            ; RS relative line drawing
  3160.     cmp    al,' '            ; control char?
  3161.     jae    tekrli1            ; ae = no
  3162.     jmp    tektxt            ; process control char
  3163. tekrli1:cmp    al,' '            ; pen up command?
  3164.     jne    tekrli2            ; ne = no, try pen down
  3165.     mov    visible,0        ; do invisible movements
  3166.     jmp    short tekrli3        ; do the command
  3167. tekrli2:cmp    al,'P'            ; pen down command?
  3168.     jne    tekrli4            ; ne = no, return to text mode
  3169.     mov    visible,1        ; set visible moves
  3170.  
  3171. tekrli3:mov    ax,x_coord        ; PC x coordinate of pen
  3172.     mov    bx,y_coord        ;    y coordinate
  3173.     call    pctotek            ; get current pen position in Tek coor
  3174.     xor    cl,cl            ; invisible, moveto
  3175.     call    tekdraw            ; move that point, set oldx and oldy
  3176.     mov    ttstate,offset tekinc    ; next get incremental movement cmds
  3177.     ret
  3178.  
  3179. tekrli4:mov    visible,0        ; bad char, reset visibility
  3180.     mov    ttstate,offset tektxt    ; assume text
  3181. tekrli5:jmp    ttstate            ; deal with bad char
  3182. TEKRLIN    endp
  3183.                     ; interpret RS inc plot command byte
  3184. TEKINC    proc    near            ; get movement character and do cmd
  3185.     cmp    al,' '            ; control char?
  3186.     jae    tekinc1            ; ae = no
  3187.     jmp    tektxt            ; process control char
  3188. tekinc1:mov    bx,oldx
  3189.     mov    cx,oldy
  3190.     test    al,1            ; 'A', 'E', 'I'?  Do by bit fields
  3191.     jz    tekinc2            ; z = no
  3192.     inc    bx            ; adjust beam position
  3193. tekinc2:test    al,2            ; 'B', 'F', 'J'?
  3194.     jz    tekinc4
  3195.     dec    bx
  3196. tekinc4:test    al,4            ; 'D', 'E', 'F'?
  3197.     jz    tekinc8            ; z = no
  3198.     inc    cx
  3199. tekinc8:test    al,8            ; 'H', 'I', 'J'?
  3200.     jz    tekinc9
  3201.     dec    cx
  3202. tekinc9:cmp    bx,0            ; too far left?
  3203.     jge    tekinc10        ; ge = no
  3204.     xor    bx,bx            ; else stop at the left margin
  3205. tekinc10:cmp    bx,maxtekx-1        ; too far left?
  3206.     jle    tekinc11        ; le = no
  3207.     mov    bx,maxtekx-1        ; else stop that the left margin
  3208. tekinc11:cmp    cx,maxteky-1        ; above the top?
  3209.     jle    tekinc12        ; le = not above the top
  3210.     mov    cx,maxteky-1        ; else stop at the top
  3211. tekinc12:cmp    cx,0            ; below bottom?
  3212.     jge    tekinc13        ; ge = not below bottom
  3213.     xor    cx,cx            ; else stop at the bottom
  3214. tekinc13:mov    ax,bx            ; ax is vector x end point
  3215.     mov    oldx,bx
  3216.     mov    bx,cx            ; bx is vector y end point
  3217.     mov    oldy,cx
  3218.     mov    cl,visible
  3219.     jmp    tekdraw            ; move/draw to that point
  3220. tekincb:mov    visible,0
  3221.     jmp    tektxt            ; reparse the bad char
  3222. TEKINC    endp
  3223.     
  3224.  
  3225. crossini proc    near            ; set crosshairs for initial screen
  3226.     cmp    crossactive,0        ; inited already?
  3227.     je    crossin1        ; e = no
  3228.     ret
  3229. crossin1:mov    ax,xmax            ; right margin minus 7 dots
  3230.     add    ax,7            ; right most dot
  3231.     shr    ax,1            ; central position
  3232.     mov    bx,ybot            ; last scan line
  3233.     shr    bx,1
  3234.     cmp    ax,xcenter        ; same as previous call?
  3235.     jne    crossin2        ; ne = no, recenter
  3236.     cmp    bx,ycenter        ; same as previous call?
  3237.     je    crossin3        ; e = yes, don't recenter crosshairs
  3238. crossin2:
  3239.     mov    xcenter,ax        ; remember center coord
  3240.     mov    ycenter,bx        ; remember center coord
  3241.     mov    xcross,ax        ; save PC coord for crosshair
  3242.     mov    ycross,bx
  3243. crossin3:                ; Mouse setup
  3244.     mov    mousebuf,0        ; assume no active mouse driver
  3245.     mov    al,mouse        ; mouse interrupt 33h
  3246.     mov    ah,35h            ; get vector for mouse driver
  3247.     int    dos
  3248.     mov    ax,es
  3249.     cmp    ax,0f000h        ; in ROM Bios?
  3250.     jae    crosin4            ; ae = yes
  3251.     or    ax,bx            ; check for no vector at all
  3252.     jz    crosin4            ; z = none
  3253.     cmp    byte ptr es:[bx],0cfh    ; is this an IRET instruction?
  3254.     je    crosin4            ; e = yes, not our driver
  3255.     mov    ax,msgetbf        ; get state buffer size (bytes) to BX
  3256.     int    mouse
  3257.     add    bx,15            ; round up to next paragraph
  3258.     shr    bx,1
  3259.     shr    bx,1
  3260.     shr    bx,1
  3261.     shr    bx,1            ; bytes to paragraphs
  3262.     mov    ah,alloc        ; allocate memory
  3263.     int    dos
  3264.     jc    crosin4            ; c = failed
  3265.     mov    mousebuf,ax        ; save seg of the mouse status buffer
  3266.     mov    es,ax
  3267.     xor    dx,dx            ; buffer address to es:dx
  3268.     mov    ax,msgetst        ; get mouse state info
  3269.     int    mouse
  3270.     jnc    crosin2            ; nc = presumed success
  3271.     call    mousefree        ; return mouse save buffer
  3272.     jmp    short crosin4
  3273. crosin2:xor    cx,cx            ; minimum horizontal/vertical motion
  3274.     mov    dx,xmax            ; right most char
  3275.     add    dx,7            ; right most dot (counted from 0)
  3276.     mov    ax,mshoriz        ; set min/max horizontal motion
  3277.     int    mouse
  3278.     mov    dx,ybot            ; max y (counted from 0)
  3279.     mov    ax,msvert        ; set min/max vertical motion
  3280.     int    mouse
  3281.  
  3282. crosin4:mov    ax,linepat        ; save line drawing pattern
  3283.     mov    ginlpsave,ax        ; save it here
  3284.     mov    linepat,0ffffh        ; reset line type to solid
  3285.     cmp    tekflg,tek_active+tek_sg; in DG special graphics mode?
  3286.     jne    crosin5            ; e = yes, DG uses left bottom corner
  3287.     or    dgcross,1        ; say crosshair is activiated
  3288.     and    dgcross,not 8        ; and not invisible
  3289.     mov    xcross,0        ; left side
  3290.     mov    ax,ybot
  3291.     sub    ax,charhgt        ; skip status line
  3292.     mov    ycross,ax        ; bottom
  3293. crosin5:call    crosdrawh        ; draw initial crosshairs
  3294.     call    crosdrawv
  3295.     call    setmouse        ; set mouse there too
  3296.     mov    crossactive,1        ; say we are active
  3297.     ret
  3298. crossini endp
  3299.  
  3300. crossfin proc    near
  3301.     cmp    crossactive,0        ; is crosshair material active?
  3302.     je    crossfin1        ; e = no
  3303.     mov    crossactive,0
  3304.     call    crosdrawh        ; erase crosshairs
  3305.     call    crosdrawv
  3306.     call    mousefree        ; return mouse save buffer
  3307.     mov    ax,ginlpsave
  3308.     mov    linepat,ax        ; restore line pattern
  3309.     mov    ttstate,offset tektxt    ; go to TEKTXT next time
  3310.     mov    lastc,0            ; clear last drawing coordinate flag
  3311.     or    status,txtmode        ; set text mode in status byte
  3312. crossfin1:ret
  3313. crossfin endp
  3314.  
  3315. ; Routine to trigger the crosshairs, wait for a key to be struck, and send
  3316. ; the typed char (if printable ascii) plus four Tek encoded x,y position
  3317. ; coordinates and then a carriage return.
  3318. ; ax, cx, xcross, ycross operate in PC coordinates.
  3319. ; For DG special graphics enter with scan code in AL
  3320. CROSHAIR PROC FAR
  3321.     cmp    tekflg,tek_active+tek_sg; in DG special graphics mode?
  3322.     jne    crosha1a        ; ne = no, try regular Tek GIN mode
  3323.     test    dgcross,8        ; should be on but has been removed?
  3324.     jz    crosha5            ; z = no, cross is visible
  3325.     push    ax
  3326.     call    crosdrawv        ; show vertical line
  3327.     call    crosdrawh
  3328.     pop    ax
  3329.     and    dgcross, not 8        ; say cross is visible again
  3330. crosha5:test    dgcross,2        ; track keyboard?
  3331.     jz    crosha1            ; z = no, try mouse
  3332.     or    al,al            ; anything in keyboard trapping buf?
  3333.     jnz    crosha4b        ; process it as if key scan code
  3334. crosha1:test    dgcross,4        ; track mouse?
  3335.     jnz    short crosha1c        ; nz = yes, try the mouse
  3336.     jmp    croshaexit        ; neither, do nothing
  3337. crosha1a:
  3338.     call    tiseof            ; is stdin at EOF?
  3339.     jc    crosha2            ; c = yes, exit this mode now
  3340.     mov    dl,0ffh
  3341.     mov    ah,dconio        ; read console
  3342.     int    dos
  3343.     jnz    crosha4            ; nz = have char in AL
  3344. crosha1c:
  3345.     cmp    mousebuf,0        ; is mouse driver active?
  3346.     je    croshaexit        ; e = no
  3347.     mov    ax,msread        ; mouse, read status and position
  3348.     int    mouse
  3349.     push    bx            ; save button press information
  3350.     cmp    cx,xcross        ; moved in x direction?
  3351.     je    crosm1            ; e = no
  3352.     push    dx            ; save mouse y
  3353.     call    crosdrawv        ; erase vertical line
  3354.     call    crosdrawh
  3355.     mov    xcross,cx        ; new position
  3356.     call    crosdrawv        ; draw new vertical line
  3357.     call    crosdrawh
  3358.     pop    dx
  3359. crosm1:    cmp    dx,ycross        ; moved in y direction?
  3360.     je    crosm2            ; e = no
  3361.     call    crosdrawh        ; erase horizontal line
  3362.     test    dgcross,1        ; is DG crosshair active?
  3363.     jz    crosm3            ; z = no
  3364.     call    crosdrawv
  3365.     mov    ax,ybot
  3366.     sub    ax,charhgt        ; avoid status line
  3367.     cmp    dx,ax            ; too far down?
  3368.     jbe    crosm3            ; be = no
  3369.     mov    dx,ax            ; stop here
  3370. crosm3:    mov    ycross,dx
  3371.     call    crosdrawh        ; draw new horizontal line
  3372.     test    dgcross,1        ; is DG crosshair active?
  3373.     jz    crosm3a            ; z = no
  3374.     call    crosdrawv
  3375. crosm3a:call    setmouse        ; set mouse there too
  3376. crosm2:    pop    bx
  3377.     test    bx,7            ; mouse, was a button pressed?
  3378.     jz    croshaexit        ; z = no
  3379.     cmp    tekflg,tek_active+tek_sg ; DG special graphics mode?
  3380.     je    crosm4            ; e = yes, do POINT command
  3381.     mov    al,CR            ; simulate a CR
  3382.     jmp    short crosha4
  3383. crosm4:    cmp    bl,1            ; left button? (rt button is 2)
  3384.     je    crosm5            ; e = yes
  3385.     mov    al,RS            ; send DG F1 code RS q for EXECUTE
  3386.     call    outmodem
  3387.     mov    al,'q'
  3388.     call    outmodem
  3389.     clc
  3390.     ret
  3391. crosm5:    call    dgcrossrpt        ; send DG POINT command
  3392. croshaexit:clc                ; c clear means not done yet
  3393.     ret
  3394.  
  3395. crosha4:or    al,al            ; ascii or scan code returned
  3396.     jnz    arrow5            ; nz = ascii char returned
  3397.     call    tiseof            ; is stdin at EOF?
  3398.     jc    crosha2            ; c = yes, exit this mode now
  3399.     mov    ah,coninq        ; read scan code
  3400.     int    dos
  3401. crosha4b:
  3402.     or    al,al            ; Control-Break?
  3403.     jnz    crosha3            ; nz = no, something else
  3404. crosha2:call    crosdrawh        ; erase crosshairs
  3405.     call    crosdrawv
  3406.     mov    ax,ginlpsave
  3407.     mov    linepat,ax        ; restore line pattern
  3408.     ret                ; exit crosshairs mode
  3409.  
  3410. crosha3:cmp    al,homscn        ; is it 'home'?
  3411.     jne    arrow1            ; ne = no, try other keys
  3412.     call    crosdrawh        ; erase crosshairs
  3413.     call    crosdrawv
  3414.     mov    ax,xmax            ; right margin
  3415.     add    ax,7
  3416.     shr    ax,1            ; central position
  3417.     mov    xcross,ax        ; save PC coord for crosshair
  3418.     mov    ax,ybot            ; last scan line
  3419.     shr    ax,1
  3420.     mov    ycross,ax        ; this is the center of the screen
  3421.     call    crosdrawh        ; draw home'd crosshairs
  3422.     call    crosdrawv
  3423.     call    setmouse        ; set mouse there too
  3424.     jmp    croshaexit
  3425.  
  3426. arrow1:    cmp    al,lftarr        ; left arrow?
  3427.     jne    arrow2            ; ne = no
  3428.     mov    cx,-1            ; left shift
  3429.     jmp    short xkeys
  3430. arrow2:    cmp    al,rgtarr        ; right arrow?
  3431.     jne    arrow3            ; ne = no
  3432.     mov    cx,1            ; right shift
  3433.     jmp    short xkeys
  3434. arrow3:    cmp    al,uparr        ; up arrow?
  3435.     jne    arrow4            ; ne = no
  3436.     mov    cx,-1            ; up shift
  3437.     jmp    short vertkey
  3438. arrow4:    cmp    al,dnarr        ; down arrow?
  3439.     jne    badkey            ; ne = no, ignore it
  3440.     mov    cx,1                  ; down shift
  3441.     jmp    short vertkey
  3442.  
  3443. badkey:    call    tekbeep            ; tell user we don't understand
  3444.     jmp    croshaexit        ; keep going
  3445.  
  3446.                     ; Shifted keys yield ascii keycodes
  3447. arrow5:    cmp    al,'C' and 1fh        ; Control-C?
  3448.     je    crosha2            ; e = yes, exit crosshairs mode now
  3449.     cmp    al,shlftarr        ; shifted left arrow?
  3450.     jne    arrow6            ; ne = no
  3451.     mov    cx,-10            ; big left shift
  3452.     jmp    short xkeys
  3453. arrow6:    cmp    al,shrgtarr        ; shifted right arrow?
  3454.     jne    arrow7            ; ne = no
  3455.     mov    cx,10            ; big right shift
  3456.     jmp    short xkeys
  3457. arrow7:    cmp    al,shuparr        ; shifted up arrow?
  3458.     jne    arrow8            ; ne = no
  3459.     mov    cx,-10            ; big up shift
  3460.     jmp    short vertkey
  3461. arrow8:    cmp    al,shdnarr        ; shifted down arrow?
  3462.     jne    charkey            ; ne = no, send this key as is
  3463.     mov    cx,10            ; big down shift
  3464.     jmp    short vertkey
  3465.  
  3466. xkeys:    call    crosdrawv        ; erase vertical line
  3467.     call    crosdrawh
  3468.     add    cx,xcross        ; add increment
  3469.     jns    noxc            ; gone too far negative?
  3470.     xor    cx,cx            ; s = yes, make it 0
  3471. noxc:    mov    ax,xmax
  3472.     add    ax,7            ; right most dot
  3473.     cmp    cx,ax            ; too far right?
  3474.     jb    xdraw9            ; b = no
  3475.     mov    cx,ax            ; yes, make it the right
  3476. xdraw9: mov    xcross,cx        ; new x value for cross hairs
  3477.     call    crosdrawv        ; draw new vertical line
  3478.     call    crosdrawh
  3479.  
  3480.     call    setmouse        ; set mouse there too
  3481.     jmp    croshaexit
  3482.      
  3483. vertkey:call    crosdrawh        ; erase horizontal line
  3484.     call    crosdrawv
  3485.     add    cx,ycross        ; adjust cx
  3486.     jns    noyc            ; gone negative?
  3487.     xor    cx,cx            ; s = yes then make 0
  3488. noyc:    test    dgcross,1        ; is DG crosshair active?
  3489.     jz    noyc2            ; z = no
  3490.     push    ax
  3491.     mov    ax,ybot
  3492.     sub    ax,charhgt        ; avoid status line
  3493.     cmp    cx,ax            ; too far down?
  3494.     jbe    noyc1            ; be = no
  3495.     mov    cx,ax            ; stop here
  3496. noyc1:    pop    ax
  3497.  
  3498. noyc2:    cmp    cx,ybot            ; too high?
  3499.     jb    yok            ; b = no
  3500.     mov    cx,ybot            ; make it maximum
  3501. yok:    mov    ycross,cx        ; save new y crosshair
  3502.     call    crosdrawh        ; draw new vertical line
  3503.     call    crosdrawv
  3504.     call    setmouse        ; set mouse there too
  3505.     jmp    croshaexit
  3506.      
  3507. charkey:call    outmodem        ; send the break character
  3508.     mov    ax,xcross        ; set beam to xcross,ycross
  3509.     mov    bx,ycross        ; must convert to Tek coordinates
  3510.     call    pctotek            ; scale from PC screen coord to Tek
  3511.     push    ax            ; save around drawing
  3512.     push    bx
  3513.     xor    cx,cx            ; just a move
  3514.     call    tekdraw            ; moveto ax,bx in Tek coord
  3515.     pop    bx            ; recover Tek y
  3516.     pop    ax            ; recover Tek x
  3517.     call    sendpos            ; send position report to host
  3518.     call    crossfin        ; finish up
  3519.     STC                ; set carry to say end of GIN mode
  3520.     ret
  3521. CROSHAIR ENDP
  3522.      
  3523. ; draw vertical crosshair line at x = xcross, xor with picture
  3524. crosdrawv proc near
  3525.     push    bp
  3526.     push    x_coord
  3527.     push    y_coord
  3528.     mov    al,ccode        ; save current pixel op
  3529.     push    ax
  3530.     push    cx
  3531.     mov    si,xcross        ; move to x= xcross
  3532.     mov    ax,si            ; ending x coord
  3533.     xor    di,di            ; starting y coord
  3534.     mov    bx,ybot            ; bottom y coord
  3535.     test    dgcross,1        ; DG cursor?
  3536.     jz    crosdrawv2        ; z = no
  3537.     sub    bx,charhgt        ; omit status line
  3538.     test    flags.vtflg,ttd470    ; D470 short cursor
  3539.     jz    crosdrawv2        ; z = no, use D463 large cursor
  3540.     mov    cx,charhgt
  3541.     shr    cx,1            ; half a cell
  3542.     mov    di,ycross        ; D470 start at top of char cell
  3543.     mov    bx,di
  3544.     sub    bx,cx
  3545.     jnc    crosdrawv1        ; nc = in bounds
  3546.     xor    bx,bx            ; clip at top
  3547. crosdrawv1:
  3548.     add    di,cx            ; down half a cell
  3549.     mov    cx,ybot
  3550.     sub    cx,charhgt        ; omit status line
  3551.     dec    cx
  3552.     cmp    di,cx            ; too far down?
  3553.     jbe    crosdrawv2        ; be = no
  3554.     mov    di,cx            ; clip at bottom
  3555. crosdrawv2:mov    cl,pixxor        ; xor pixels
  3556.     call    line            ; draw vertical
  3557.     pop    cx
  3558.     pop    ax            ; recover current pixel op
  3559.     mov    ccode,al        ; restore it
  3560.     pop    y_coord
  3561.     pop    x_coord
  3562.     pop    bp
  3563.     ret
  3564. crosdrawv endp
  3565.  
  3566. ; draw horizontal crosshair line at y = ycross, xor with picture
  3567. crosdrawh proc near
  3568.     push    bp
  3569.     push    x_coord
  3570.     push    y_coord
  3571.     mov    al,ccode        ; save current pixel op
  3572.     push    ax
  3573.     push    cx
  3574.     mov    di,ycross        ; set y = ycross
  3575.     mov    bx,di            ; ending y
  3576.     xor    si,si            ; starting x
  3577.     mov    ax,xmax
  3578.     add    ax,7
  3579.     test    dgcross,1        ; DG cross?
  3580.     jz    crosdrawh1        ; z = no
  3581.     test    flags.vtflg,ttd470    ; D470 short cursor
  3582.     jz    crosdrawh1        ; z = no, use D463 large cursor
  3583.     mov    si,xcross        ; start x
  3584.     mov    ax,si
  3585.     sub    si,7
  3586.     add    ax,7            ; width
  3587. crosdrawh1:
  3588.     mov    cl,pixxor        ; set XOR code
  3589.     call    line            ; draw to (xcross+12, ycross)
  3590.     pop    cx
  3591.     pop    ax            ; recover current pixel op
  3592.     mov    ccode,al        ; restore it
  3593.     pop    y_coord
  3594.     pop    x_coord
  3595.     pop    bp
  3596.     ret
  3597. crosdrawh endp
  3598.           
  3599. ; Set mouse cursor position to xcross,ycross. Ignored if no active mouse.
  3600. setmouse proc    near
  3601.     cmp    mousebuf,0        ; is mouse driver is active?
  3602.     je    setmou1            ; e = no
  3603.     mov    cx,xcross
  3604.     mov    dx,ycross
  3605.     mov    ax,mswrite        ; set mouse position
  3606.     int    mouse
  3607. setmou1:ret
  3608. setmouse endp
  3609.  
  3610. ; Return DOS memory allocated as mouse status buffer
  3611. mousefree proc    near
  3612.     push    es
  3613.     mov    ax,mousebuf        ; seg of mouse save buffer
  3614.     mov    es,ax            ; allocated segment
  3615.     mov    ah,freemem        ; free it
  3616.     int    dos
  3617.     mov    mousebuf,0        ; clear mouse presence too
  3618.     pop    es
  3619.     ret
  3620. mousefree endp
  3621.  
  3622. ; Return mouse state and free state save buffer
  3623. mousexit proc    near
  3624.     mov    ax,mousebuf        ; segment of state save buffer
  3625.     or    ax,ax            ; is mouse driver active?
  3626.     jz    mousex1            ; z = no
  3627.     push    es
  3628.     mov    es,ax
  3629.     xor    dx,dx            ; address is in es:dx
  3630.     mov    ax,mssetst        ; set mouse driver state from buffer
  3631.     int    mouse
  3632.     pop    es
  3633.     call    mousefree        ; return memory to DOS
  3634. mousex1:ret
  3635. mousexit endp
  3636.  
  3637. ; SENDPOS sends position of cross-hairs to the host.
  3638. ; ax has Tek X and bx has Tek Y coord of center of crosshair     
  3639. SENDPOS PROC NEAR
  3640.     push    bx            ; preserve register
  3641.     call    sendxy            ; send x coord
  3642.     pop    ax
  3643.     call    sendxy            ; send y coord
  3644.     mov    al,cr            ; follow up with cr
  3645.     call    outmodem
  3646.     ret
  3647. SENDPOS ENDP
  3648.  
  3649. ; Write binary number in AX as decimal asciiz to buffer pointer DI.
  3650. dec2di    proc    near        ; output number in ax using base in cx
  3651.                 ; corrupts ax, cx, and dx
  3652.     mov    cx,10
  3653. dec2di1:xor    dx,dx        ; clear high word of numerator
  3654.     div    cx        ; (ax / cx), remainder = dx, quotient = ax
  3655.     push    dx        ; save remainder for outputting later
  3656.     or    ax,ax        ; any quotient left?
  3657.     jz    dec2di2        ; z = no
  3658.     call    dec2di1        ; yes, recurse
  3659. dec2di2:pop    dx        ; get remainder
  3660.     add    dl,'0'        ; make digit printable
  3661.     mov    [di],dl        ; store char in buffer
  3662.     inc    di
  3663.     mov    byte ptr[di],0    ; add terminator
  3664.     ret
  3665. dec2di    endp
  3666.      
  3667. ; SENDXY sends value of ax as Tek encoded bytes
  3668. ; ax is in Tek coordinates     
  3669. SENDXY    PROC    NEAR
  3670.     shl    ax,1
  3671.     shl    ax,1            ; move all but lower 5 bits to ah
  3672.     shl    ax,1
  3673.     shr    al,1
  3674.     shr    al,1            ; move low five bits to low 5 bits
  3675.     shr    al,1
  3676.     or    ah,20h            ; make it a printing char as per TEK
  3677.     xchg    al,ah            ; send high 5 bits first
  3678.     call    outmodem
  3679.     xchg    al,ah            ; then low five bits
  3680.     or    al,20h
  3681.     call    outmodem
  3682.     xchg    ah,al            ; al is first sent byte
  3683.     ret
  3684. SENDXY    ENDP
  3685.      
  3686.      
  3687. SENDID    PROC NEAR            ; pretend VT340
  3688.     mov    bx,offset tekid        ; VT320 identification string
  3689. sndid1: mov    al,[bx]            ; get char from sequence
  3690.     or    al,al            ; end of sequence?
  3691.     jz    sndid0            ; z = yes, return
  3692.     call    outmodem        ; send it out the port
  3693.     inc    bx
  3694.     jmp    sndid1
  3695. sndid0:    ret
  3696. SENDID    ENDP
  3697.      
  3698. ; SENDSTAT - send status and cursor position to host
  3699.      
  3700. SENDSTAT PROC NEAR
  3701.     mov    al,STATUS        ; get tek status
  3702.     or    al,20h            ; make it printable
  3703.     call    OUTMODEM        ; and send it
  3704.     mov    ax,oldx            ; now send x coordinate (oldx is Tek)
  3705.     call    SENDXY
  3706.     mov    ax,oldy            ; and y coordinate (oldy is Tek coord)
  3707.     call    SENDXY
  3708.     mov    al,cr            ; end with a cr
  3709.     call    OUTMODEM
  3710.     ret
  3711. SENDSTAT ENDP
  3712.      
  3713.  
  3714. ; Convert X and Y from PC coordinates to Tek coordinates. AX = X, BX = Y
  3715. ; for both input and output.
  3716. pctotek    proc    near
  3717.     mul    xdiv            ; scale from PC screen coord to Tek
  3718.     div    xmult
  3719.     xchg    bx,ax            ; save Tek x coord in bx
  3720.     neg    ax            ; y axis. Turn upside down for Tek
  3721.     add    ax,ybot
  3722.     mul    ydiv            ; scale y from PC screen coord to Tek
  3723.     div    ymult
  3724.     xchg    ax,bx            ; ax has X, bx has Y in Tek coords
  3725.     ret
  3726. pctotek    endp
  3727.  
  3728. ; Routine to output character in AL to the screen.
  3729.  
  3730. OUTSCRN PROC NEAR            ; put one character to the screen
  3731.     cmp    rxtable+256,0        ; translation turned off?
  3732.     je    outscr2            ; e = yes, no translation
  3733.     push    bx
  3734.     mov    bx,offset rxtable    ; address of translate table
  3735.     xlatb                ; new char is in al
  3736.     and    al,7fh            ; retain only lower seven bits
  3737.     pop    bx
  3738.  
  3739. outscr2:mov    ah,ccode        ; assume transparent chars
  3740.     push    ax            ; save ccode
  3741.     mov    ccode,pixfor        ; write in foreground
  3742.     cmp    chcontrol,0        ; transparent char writing?
  3743.     je    outscr3            ; e = yes
  3744.     or    ccode,pixbak        ; write background dots too
  3745. outscr3:call    remcursor        ; remove text cursor symbol
  3746.     cmp    al,' '            ; printable?
  3747.     ja    outscr6            ; a = yes
  3748.     je    outscr5            ; e = space
  3749. outscr4:call    putctrl            ; handle controls at putctrl
  3750.     jmp    short outscr9
  3751. outscr5:cmp    spcontrol,0        ; destructive space?
  3752.     jne    outscr6            ; ne = yes, do actual writing
  3753.     cmp    chcontrol,0        ; write transparently?
  3754.     jne    outscr6            ; ne = no, opaque, draw the char
  3755.     call    testfull        ; check on full screen
  3756.     call    incx            ; move to next char position
  3757.     jmp    short outscr9
  3758.  
  3759. outscr6:call    testfull        ; check for full screen
  3760.     sub    al,' '            ; Tek chars are biased to start at ' '
  3761.     call    putc            ; routine to draw characters
  3762. outscr9:call    setcursor        ; draw text cursor symbol
  3763.     pop    ax            ; recover ccode
  3764.     mov    ccode,ah
  3765.     ret
  3766. OUTSCRN ENDP
  3767.  
  3768. ; Data General D463/D470 support routine, used by touchup
  3769. ; Display whole line, es:si holds char+attribute words, cursor is at DX
  3770. ttxtline proc    far
  3771.     push    word ptr fontlptr
  3772.     push    word ptr fontlptr+2
  3773.     push    word ptr fontrptr
  3774.     push    word ptr fontrptr+2
  3775.     push    dx            ; cursor position
  3776.     push    bx
  3777.     test    dgcross,1        ; is cross hair on?
  3778.     jz    ttxtlin0        ; z = no
  3779.     test    dgcross,8        ; is cross hair invisible?
  3780.     jnz    ttxtlin0        ; nz = yes
  3781.     push    es
  3782.     push    si
  3783.     push    dx
  3784.     call    crosdrawh        ; remove present crosshairs
  3785.     call    crosdrawv
  3786.     or    dgcross,8        ; say cross is invisible
  3787.     pop    dx
  3788.     pop    si
  3789.     pop    es
  3790. ttxtlin0:
  3791.     mov    bl,dh            ; get line row
  3792.     xor    bh,bh
  3793.     mov    charwidth,8        ; use regular width font
  3794.     cmp    dgwindcomp[bx],0    ; regular width chars?
  3795.     pop    bx
  3796.     je    ttxtlin1        ; e = yes
  3797.     cmp    plotptr,offset pltega    ; ega dot plot routine?
  3798.     jne    ttxtlin1        ; no, use 8 wide
  3799.     mov    charwidth,5        ; use compressed font
  3800.     mov    word ptr fontlptr,offset fivedot
  3801.     mov    word ptr fontlptr+2,seg fivedot
  3802.     mov    word ptr fontrptr+2,seg fivedot
  3803.     mov    word ptr fontrptr,offset gr437
  3804.     cmp    vtcpage,437        ; using CP437?
  3805.     je    ttxtlin1              ; e = yes, use GR437 slim font
  3806.     mov    word ptr fontrptr,offset gr850 ; GR850 slim font
  3807. ttxtlin1:mov    ccode,pixfor+pixbak
  3808.     mov    ax,charhgt
  3809.     inc    dh            ; count text lines from 1
  3810.     mul    dh            ; compute scan row
  3811.     dec    ax            ; count scan lines from zero
  3812.     mov    y_coord,ax
  3813.     mov    x_coord,0
  3814.     mov    cx,80            ; normal columns/screen
  3815.     cmp    charwidth,8        ; wide chars?
  3816.     je    ttxtlin2        ; e = yes
  3817.     mov    cx,128            ; 128*5=640
  3818. ttxtlin2:push    charwidth
  3819.     mov    ax,es:[si]        ; char+attribute from virtual screen
  3820.     add    si,2
  3821.     cmp    al,' '            ; space is same pattern, use short cut
  3822.     je    ttxtlin2a        ; e = space
  3823.     cmp    charwidth,8        ; can we use byte-wise short cut?
  3824.     jne    ttxtlin4        ; ne = no
  3825. ttxtlin2a:push    di
  3826.     push    ax
  3827.     sub    si,2
  3828.     mov    di,si
  3829.     cld
  3830.     repe    scasw            ; find repeats
  3831.     je    ttxtlin3
  3832.     sub    di,2            ; inc'd beyond break word, backup
  3833.     add    cx,2            ; and the counter
  3834. ttxtlin3:mov    ax,di
  3835.     sub    ax,si            ; qty repeated, cx dec'd too
  3836.     mov    si,di            ; update source pointer
  3837.     shr    ax,1            ; count words
  3838.     cmp    ax,1
  3839.     jbe    ttxtlin3a        ; be = no change to charwidth
  3840.     mul    charwidth
  3841.     mov    charwidth,ax        ; make wider chars from repeats
  3842. ttxtlin3a:pop    ax
  3843.     pop    di
  3844.  
  3845. ttxtlin4:push    es
  3846.     push    si
  3847.     push    cx
  3848.     mov    gfcol,ah        ; foreground color
  3849.     and    gfcol,0fh        ; lower four bits
  3850.     cmp    plotptr,offset pltega    ; ega dot plot routine?
  3851.     je    ttxtlin4a        ; e = yes
  3852.     xor    ah,ah            ; no background for monochrome systems
  3853.     and    al,7fh            ; no high bit
  3854.     sub    al,' '            ; font begins with space
  3855.     jnc    ttxtlin4a        ; nc = not a control
  3856.     xor    al,al
  3857. ttxtlin4a:mov    cl,4
  3858.     shr    ah,cl
  3859.     and    ah,0fh
  3860.     mov    gbcol,ah        ; background color
  3861.     call    putc        ; draw the char, cursor done separately later
  3862.     pop    cx
  3863.     pop    si
  3864.     pop    es
  3865.     pop    charwidth
  3866.     dec    cx
  3867.     jle    ttxtlin6
  3868.     jmp    ttxtlin2
  3869.  
  3870. ttxtlin6:pop    dx            ; recover cursor
  3871.     pop    word ptr fontrptr+2
  3872.     pop    word ptr fontrptr
  3873.     pop    word ptr fontlptr+2
  3874.     pop    word ptr fontlptr
  3875.     ret
  3876. ttxtline endp
  3877.  
  3878. ; display char in AL, normal attributes in AH, text screen at DX 
  3879. ttxtchr proc    far
  3880.     push    cx
  3881.     push    dx
  3882.     push    word ptr fontlptr
  3883.     push    word ptr fontlptr+2
  3884.     push    word ptr fontrptr
  3885.     push    word ptr fontrptr+2
  3886.     mov    bl,dh            ; get line row
  3887.     xor    bh,bh
  3888.     mov    charwidth,8        ; use regular width font
  3889.     cmp    dgwindcomp[bx],0    ; regular width chars?
  3890.     je    ttxtchr1        ; e = yes
  3891.     cmp    plotptr,offset pltega    ; ega dot plot routine?
  3892.     jne    ttxtchr1        ; no, use 8 wide
  3893.     mov    charwidth,5        ; use compressed font
  3894.     mov    word ptr fontlptr,offset fivedot
  3895.     mov    word ptr fontlptr+2,seg fivedot
  3896.     mov    word ptr fontrptr+2,seg fivedot
  3897.     mov    word ptr fontrptr,offset gr437
  3898.     cmp    vtcpage,437        ; using CP437?
  3899.     je    ttxtchr1              ; e = yes, use GR437 slim font
  3900.     mov    word ptr fontrptr,offset gr850 ; GR850 slim font
  3901. ttxtchr1:mov    ccode,pixfor+pixbak
  3902.     mov    gfcol,ah        ; foreground color
  3903.     and    gfcol,0fh        ; lower four bits
  3904.     cmp    plotptr,offset pltega    ; ega dot plot routine?
  3905.     je    ttxtchr2        ; e = yes
  3906.     xor    ah,ah            ; no background on monochrome systems
  3907.     and    al,7fh            ; no high bit
  3908.     sub    al,' '            ; font begins with space
  3909.     jnc    ttxtchr2        ; nc = not a control
  3910.     xor    al,al            ; omit controls
  3911. ttxtchr2:mov    cl,4
  3912.     shr    ah,cl
  3913.     and    ah,0fh
  3914.     mov    gbcol,ah        ; background color
  3915.     push    ax
  3916.     mov    ax,charwidth
  3917.     mul    dl            ; compute scan column
  3918.     mov    cx,xmax
  3919.     add    cx,8            ; right most dot
  3920.     sub    cx,charwidth        ; right most char cell
  3921.     cmp    cx,ax            ; char still on screen?
  3922.     jc    ttxtchr2a        ; c = out of range
  3923.     mov    x_coord,ax
  3924. ttxtchr2a:pop    ax
  3925.     jc    ttxtchr5        ; c = out of range
  3926.     push    ax
  3927.     mov    ax,charhgt
  3928.     inc    dh            ; count text lines from 1
  3929.     mul    dh            ; compute scan row
  3930.     dec    ax            ; count scan lines from zero
  3931.     mov    y_coord,ax
  3932.     pop    ax
  3933.     mov    cursorst,0        ; say cursor is off (is overwritten)
  3934.     test    dgcross,1        ; is cross hair on?
  3935.     jz    ttxtchr3        ; z = no
  3936.     test    dgcross,8        ; is cross hair invisible?
  3937.     jnz    ttxtchr3        ; nz = yes
  3938.     push    es
  3939.     push    si
  3940.     push    dx
  3941.     push    ax
  3942.     call    crosdrawh        ; remove present crosshairs
  3943.     call    crosdrawv
  3944.     or    dgcross,8        ; say cross is on but invisible
  3945.     pop    ax
  3946.     pop    dx
  3947.     pop    si
  3948.     pop    es
  3949. ttxtchr3:call    putc        ; draw the char, cursor done separately later
  3950. ttxtchr5:
  3951.     pop    word ptr fontrptr+2
  3952.     pop    word ptr fontrptr
  3953.     pop    word ptr fontlptr+2
  3954.     pop    word ptr fontlptr
  3955.     pop    dx
  3956.     pop    cx
  3957.     ret
  3958. ttxtchr endp
  3959.  
  3960. ; Test if screen is full. If full sound beep, wait for any keyboard input
  3961. ; (skip kbd reading if stdin is redirected).
  3962. testfull proc    near
  3963.     push    ax
  3964.     mov    ax,x_coord
  3965.     cmp    ax,xmax            ; at end of the line?
  3966.     jbe    testfu1            ; be = no
  3967.     mov    x_coord,0        ; wrap to next line
  3968.     mov    ax,charhgt
  3969.     add    y_coord,ax        ; next row
  3970. testfu1:mov    ax,ybot            ; get last scan line
  3971.     inc    ax            ; number of scan lines
  3972.     cmp    ax,y_coord        ; minus where char bottom needs to go
  3973.     jae    testfu3            ; ae = enough space for char
  3974.     call    tekbeep            ; tell the user we are waiting
  3975.     call    tiseof            ; EOF on redirected stdin?
  3976.     jc    testfu2            ; c = yes, proceed anyway
  3977.     mov    ah,coninq        ; read keyboad via DOS
  3978.     int    dos            ; wait for keystroke
  3979.     or    al,al            ; scan code being returned?
  3980.     jne    testfu2            ; ne = no
  3981.     mov    ah,coninq        ; clear away scan code too
  3982.     int    dos
  3983. testfu2:call    tekcls            ; clear the screen
  3984.     mov    x_coord,0
  3985.     mov    y_coord,0
  3986. testfu3:pop    ax            ; recover current character
  3987.     ret
  3988. testfull endp
  3989.  
  3990. ; Draw text cursor symbol by xor-ing. Sets xcursor,ycursor to symbol position.
  3991. teksetcursor proc FAR
  3992.     call    remcursor        ; remove old cursor
  3993.     test    atctype,4        ; is cursor to be invisible?
  3994.     jz    teksetcur1        ; z = no
  3995.     ret
  3996. teksetcur1:
  3997.     push    ax
  3998.     mov    ax,charhgt
  3999.     inc    dh            ; count text rows from 1
  4000.     mul    dh            ; compute scan row
  4001.     dec    dh            ; restore DX
  4002.     dec    ax            ; count scan rows from 0
  4003.     mov    y_coord,ax
  4004.     push    bx
  4005.     mov    bl,dh            ; get line row
  4006.     xor    bh,bh
  4007.     mov    ax,8            ; use regular width font
  4008.     cmp    dgwindcomp[bx],0    ; regular width chars?
  4009.     pop    bx
  4010.     je    teksetcur3        ; e = yes
  4011.     cmp    plotptr,offset pltega    ; ega dot plot routine?
  4012.     jne    teksetcur3        ; no, use 8 wide
  4013.     mov    ax,5            ; use compressed font
  4014. teksetcur3:
  4015.     mov    charwidth,ax
  4016.     mul    dl            ; compute scan column
  4017.     push    cx
  4018.     mov    cx,xmax
  4019.     add    cx,8
  4020.     sub    cx,charwidth
  4021.     cmp    ax,cx
  4022.     jbe    teksetcur4        ; be = in range
  4023.     mov    ax,cx
  4024. teksetcur4:pop    cx
  4025.     mov    x_coord,ax
  4026.     pop    ax
  4027.     call    setcursor
  4028.     ret
  4029. teksetcursor endp
  4030.  
  4031. setcursor proc    near
  4032.     cmp    tekcursor,0        ; suppress cursor?
  4033.     je    setcurs0        ; e = yes
  4034.     cmp    cursorst,0        ; is cursor off now?
  4035.     jne    setcurs0        ; ne = no
  4036.     cmp    putc,offset mputc    ; pure mono character display routine?
  4037.     jne    setcurs1        ; ne = no
  4038. setcurs0:ret                ; no cursor for pure mono
  4039. setcurs1:push    ax
  4040.     push    bx
  4041.     push    cx
  4042.     push    dx
  4043.     push    si
  4044.     push    di
  4045.     push    es
  4046.     mov    bh,gbcol
  4047.     mov    bl,gfcol
  4048.     push    bx
  4049.     mov    bh,ccode        ; current drawing code, save it
  4050.     push    bx            ; save ccode
  4051.     push    x_coord            ; save current operating point (PC)
  4052.     push    y_coord
  4053.     mov    ax,x_coord        ; where cursor symbol starts, X axis
  4054.     mov    bx,xmax
  4055.     add    bx,8            ; real screen width
  4056.     sub    bx,charwidth        ; where last char could go
  4057.     cmp    ax,bx            ; beyond last character position?
  4058.     jbe    setcurs2        ; be = no
  4059.     mov    ax,bx            ; yes, stop at last, for wrapping
  4060. setcurs2:mov    xcursor,ax        ; remember where we drew symbol
  4061.     mov    x_coord,ax        ; set this for drawing the symbol
  4062.     mov    ax,y_coord
  4063.     mov    ycursor,ax
  4064.     push    word ptr fontlptr    ; save active font GLeft pointer
  4065.     push    word ptr fontlptr+2
  4066.     mov    ax,charwidth
  4067.     mov    curcharw,ax        ; current cursor width
  4068.     mov    ax,seg defcurpat    ; default Tek cursor pattern, seg
  4069.     mov    word ptr fontlptr+2,ax    ; point to us
  4070.     mov    ax,offset defcurpat     ; default Tek cursor pattern
  4071.     xor    bl,bl            ; initial (and only char in font)
  4072.     test    tekflg,tek_sg        ; special graphics?
  4073.     jz    setcurs4        ; z = no, use default
  4074.     call    dgsetcol
  4075.     and    al,0fh            ; retain foreground dots
  4076.     mov    gfcol,al        ; set foreground coloring
  4077.     mov    cl,atctype        ; active cursor type
  4078.     mov    dgctype,cl        ; type of cursor being written
  4079.     xor    ch,ch
  4080.     jcxz    setcurs5        ; z = nothing to do
  4081.     and    cl,3            ; visible cursor kinds, two bits
  4082.     mov    ax,offset dgcurbpat    ; block pattern
  4083.     cmp    cl,1            ; underline?
  4084.     ja    setcurs3        ; a = no, block
  4085.     mov    ax,offset dgcurupat    ; use DG cursor underline pattern
  4086. setcurs3:cmp    plotptr,offset pltega    ; ega dot plot routine?
  4087.     je    setcurs4        ; e = yes, else CGA style
  4088.     add    ax,5            ; use lower lines of 14L pattern
  4089. setcurs4:mov    word ptr fontlptr,ax    ; set offset of pattern
  4090.     mov    al,gfcol        ; get foreground coloring
  4091.     xor    ah,ah
  4092.     mov    gbcol,ah        ; no change to background
  4093.     mov    curgcol,ax        ; save it for cursor removal
  4094.     mov    ccode,pixxor        ; xor with foreground coloring
  4095.     mov    al,bl            ; symbol code to draw, first in font
  4096.     call    putc            ; routine to draw characters
  4097. setcurs5:
  4098.     pop    word ptr fontlptr+2
  4099.     pop    word ptr fontlptr
  4100.     pop    y_coord
  4101.     pop    x_coord
  4102.     pop    bx            ; recover ccode
  4103.     mov    ccode,bh
  4104.     mov    cursorst,1        ; say cursor is on
  4105.     pop    bx
  4106.     mov    gbcol,bh
  4107.     mov    gfcol,bl
  4108.     pop    es
  4109.     pop    di
  4110.     pop    si
  4111.     pop    dx
  4112.     pop    cx
  4113.     pop    bx
  4114.     pop    ax
  4115.     ret
  4116. setcursor endp
  4117.  
  4118. ; Remove text cursor symbol by xor-ing with itself. Xcursor, ycursor is the
  4119. ; PC coord of the cursor symbol.
  4120. tekremcursor proc FAR
  4121.     call    remcursor
  4122.     ret
  4123. tekremcursor endp
  4124.  
  4125. remcursor proc    near
  4126.     cmp    tekcursor,0        ; suppress cursor?
  4127.     je    remcurs0        ; e = yes
  4128.     cmp    cursorst,0        ; is cursor off now?
  4129.     je    remcurs0        ; e = yes
  4130.     cmp    putc,offset mputc    ; pure mono character display routine?
  4131.     jne    remcurs1        ; ne = no
  4132. remcurs0:ret                ; no cursor for pure mono
  4133. remcurs1:push    ax
  4134.     push    bx
  4135.     push    cx
  4136.     push    dx
  4137.     push    si
  4138.     push    di
  4139.     push    es
  4140.     mov    bh,gbcol
  4141.     mov    bl,gfcol
  4142.     push    bx
  4143.     mov    bh,ccode        ; current drawing code, save it
  4144.     push    bx            ; save ccode
  4145.     push    x_coord            ; save current operating point (PC)
  4146.     push    y_coord
  4147.     mov    ax,xcursor        ; where last cursor was written
  4148.     mov    x_coord,ax        ; setup for xor writing to remove it
  4149.     mov    ax,ycursor
  4150.     mov    y_coord,ax
  4151.     push    word ptr fontlptr
  4152.     push    word ptr fontlptr+2
  4153.     push    charwidth
  4154.     mov    ah,gbcol
  4155.     mov    al,gfcol
  4156.     push    ax
  4157.     mov    ax,curcharw        ; get old cursor char width
  4158.     mov    charwidth,ax
  4159.     mov    ax,curgcol        ; get old cursor colors
  4160.     mov    gfcol,al        ; set it for removal
  4161.     mov    ax,seg defcurpat
  4162.     mov    word ptr fontlptr+2,ax    ; point to our data segment
  4163.     mov    ax,offset defcurpat     ; default cursor pattern
  4164.     xor    bl,bl            ; initial (and only char in font)
  4165.     test    tekflg,tek_sg        ; special graphics?
  4166.     jz    remcurs4        ; z = no, use default
  4167.     mov    cl,dgctype        ; last used emulation cursor type
  4168.     and    cl,3            ; keep just two lower bits
  4169.     xchg    dgctype,cl        ; update cursor type
  4170.     xor    ch,ch
  4171.     jcxz    remcurs5        ; z = nothing to do
  4172.     mov    ax,offset dgcurbpat    ; use block pattern
  4173.     cmp    cl,2            ; last used cursor type
  4174.     je    remcurs3        ; 0/4 is no cursor, 1=uline, 2=block
  4175.     mov    ax,offset dgcurupat    ; use DG cursor underline pattern
  4176. remcurs3:cmp    plotptr,offset pltega    ; ega dot plot routine?
  4177.     je    remcurs4        ; e = yes, else CGA 8x8 style
  4178.     add    ax,5            ; use lower scan lines for mono
  4179. remcurs4:mov    word ptr fontlptr,ax
  4180.     mov    ccode,pixxor        ; xor with foreground coloring
  4181.     mov    gbcol,0            ; no change to background
  4182.     mov    al,bl            ; character from font
  4183.     call    putc            ; routine to draw characters
  4184. remcurs5:
  4185.     pop    ax
  4186.     mov    gbcol,ah
  4187.     mov    gfcol,al
  4188.     pop    charwidth
  4189.     pop    word ptr fontlptr+2
  4190.     pop    word ptr fontlptr
  4191.     pop    y_coord
  4192.     pop    x_coord
  4193.     pop    bx            ; recover ccode
  4194.     mov    ccode,bh
  4195.     mov    cursorst,0        ; say cursor is off
  4196.     pop    bx
  4197.     mov    gbcol,bh
  4198.     mov    gfcol,bl
  4199.     pop    es
  4200.     pop    di
  4201.     pop    si
  4202.     pop    dx
  4203.     pop    cx
  4204.     pop    bx
  4205.     pop    ax
  4206.     ret
  4207. remcursor endp
  4208.       
  4209. ; TEKCLS routine to clear the screen.
  4210. ; Entry point tekcls1 clears screen without resetting current point.     
  4211. TEKCLS    PROC    NEAR
  4212.     test    tekflg,tek_active    ; Tek mode active yet?
  4213.     jnz    tekcls0            ; nz = yes
  4214.     ret                ; else ignore this call
  4215. tekcls0:mov    x_coord,0        ; starting text coordinates
  4216.     mov    y_coord,0
  4217.     mov    oldx,0            ; assumed cursor starting location
  4218.     mov    oldy,maxteky        ;  top right corner (Tek coord)
  4219.     mov    scalex,0        ; clear last plotted point (PC coord)
  4220.     mov    scaley,0
  4221.     mov    lastc,0            ; last parsed x,y coordinate
  4222.     mov    visible,0        ; make lines invisible
  4223.     mov    bypass,0        ; clear bypass condition
  4224.     mov    ttstate,offset tektxt    ; do displayable text
  4225.     mov    prestate,offset tektxt
  4226. tekcls1:push    ax            ; save registers
  4227.     push    cx
  4228.     mov    bl,ccode        ; save pixel op code
  4229.     push    bx
  4230.     cmp    graph_mode,hercules    ; Hercules?
  4231.     jne    tekclsw            ; ne = no
  4232.     call    hgraf            ; set Hercules board to Graphics mode
  4233.     jmp    tekcls7
  4234.  
  4235. tekclsw:cmp    graph_mode,wyse700    ; Wyse 700?
  4236.     jne    tekcls2            ; ne = no
  4237.     call    wygraf            ; set board to Graphics mode & cls
  4238.     jmp    tekcls7
  4239.  
  4240. tekcls2:xor    di,di            ; point to start of screen, di=row
  4241.     mov    ccode,pixbak        ; write in background
  4242.     call    psetup            ; setup graphics routine and es:di
  4243.     mov    cx,4000h        ; CGA, 200 lines times 80 bytes worth
  4244.     cmp    graph_mode,cga        ; cga?
  4245.     je    tekcls3            ; e = yes
  4246.     mov    cx,8000h        ; Olivetti, 400 lines times 80 bytes
  4247.     cmp    graph_mode,olivetti    ; AT&T-Olivetti?
  4248.     je    tekcls3            ; e = yes
  4249.     cmp    graph_mode,toshiba    ; Toshiba?
  4250.     je    tekcls3            ; e = yes
  4251.     cmp    graph_mode,vaxmate    ; VAXmate?
  4252.     jne    tekcls4            ; ne = no
  4253. tekcls3:cld                ; clear screen directly of text stuff
  4254.     xor    ax,ax
  4255.     test    gbcol,7            ; background is dark?
  4256.     jz    tekcls3a        ; z = yes
  4257.     mov    ax,0ffffh        ; light, set all pixels
  4258. tekcls3a:shr    cx,1            ; do words
  4259.     rep    stosw            ; clear the words
  4260.     jmp    short tekcls7
  4261.  
  4262. tekcls4:cmp    graph_mode,ega        ; EGA?
  4263.     je    tekcls5            ; e = yes
  4264.     cmp    graph_mode,monoega    ; EGA with mono display?
  4265.     je    tekcls5            ; e = yes
  4266.     cmp    graph_mode,colorega    ; EGA with medium resolution monitor?
  4267.     je    tekcls5            ; e = yes
  4268.     jmp    short tekcls6        ; else use Bios
  4269.  
  4270. tekcls5:                ; EGA clear screen quickly
  4271.     mov    ax,0ff08h        ; set all 8 bits to be changed
  4272.     call    ega_gc            ; set bit mask register accordingly
  4273.     mov    ax,0003h        ; data rotate reg, write unmodified
  4274.     call    ega_gc            ; 
  4275.     mov    cx,ybot            ; last scan line
  4276.     inc    cx            ; number of scan lines
  4277.     mov    ax,80/2            ; words (2*bytes) per scan line
  4278.     mul    cx
  4279.     mov    cx,ax            ; cx = number of bytes to clear
  4280.     cmp    tekflg,tek_active+tek_sg; in special graphics mode?
  4281.     jne    tekcls5a        ; ne = no, try regular Tek GIN mode
  4282.     test    flags.vtflg,ttd463+ttd470 ; doing DG D463/D470 emulation?
  4283.     jz    tekcls5a        ; z = no
  4284.     call    dgsetcol
  4285.     jmp    short tekcls5b
  4286. tekcls5a:call    fixcolor        ; fix colors first, if req'd
  4287. tekcls5b:mov    al,gbcol        ; select background colour
  4288.     mov    ah,al            ; copy for word stores
  4289.     cld
  4290.     rep    stosw            ; write backgound color
  4291.     jmp    short tekcls7
  4292.  
  4293. tekcls6:push    es            ; clear screen by scrolling up
  4294.     call    tcmblnk            ; clear screen, for Environments
  4295.     pop    es
  4296.  
  4297. tekcls7:xor    si,si            ; starting x  (in case screen is
  4298.     xor    di,di            ; starting y    cleared by user)
  4299.     pop    bx
  4300.     mov    ccode,bl        ; restore pixel op code
  4301.     mov    xcursor,0        ; position of text cursor symbol
  4302.     mov    ycursor,0
  4303.     mov    cursorst,0        ; cursor has been erased
  4304.     call    setcursor        ; draw text cursor symbol
  4305.     pop    cx
  4306.     pop    ax
  4307.     ret
  4308. TEKCLS    ENDP
  4309.      
  4310. ; Routine to draw a line on the screen, using TEKTRONIX coordinates.
  4311. ; X coordinate in AX, 0=left edge of screen, 1023=right edge of screen.
  4312. ; Y coordinate in BX, 0=bottom of screen, 779=top of screen.
  4313. ; CL=0 - invisible move, else draw in foreground colors
  4314.      
  4315. TEKDRAW PROC NEAR
  4316.     mov    si,scalex        ; get old x already scaled
  4317.     mov    di,scaley        ; get old y already scaled
  4318.     call    scale             ; scale new end point to PC coords
  4319.     or    cl,cl            ; invisible drawing?
  4320.     jz    moveto            ; z = just move, skip draw part
  4321.     mov    cl,pixfor        ; draw in foreground color
  4322.     call    LINE            ; draw the line
  4323. moveto:    mov    x_coord,ax        ; update text coordinates to match
  4324.     mov    y_coord,bx        ;  last drawn point
  4325.     ret
  4326. TEKDRAW ENDP
  4327.      
  4328. ; Scale TEKTRONIX coordinates to the currently defined screen coordinates
  4329. ; AX holds X axis, BX holds Y axis. Both are changed from Tektronix coord
  4330. ; to PC coordinates by this procedure.
  4331. SCALE    PROC    NEAR
  4332.     push    dx
  4333.     push    si
  4334.     cmp    ax,1023            ; limit x axis
  4335.     jbe    scale1            ; be = not out of bounds
  4336.     mov    ax,1023
  4337. scale1:    cmp    bx,779            ; limit y axix
  4338.     jbe    scale2            ; be = not out of bounds
  4339.     mov    bx,779
  4340. scale2:    mov    oldx,ax            ; save current Tek x for next draw
  4341.     mov    oldy,bx            ; save current Tek y for next draw
  4342.     mul    xmult            ; scale x-coord
  4343.     mov    si,xdiv            ; get the divisor
  4344.     shr    si,1            ; halve it
  4345.     add    ax,si            ; add in - to round to nearest integer
  4346.     adc    dx,0
  4347.     div    xdiv
  4348.     push    ax
  4349.     mov    ax,bx
  4350.     mul    ymult            ; scale y-coord
  4351.     mov    si,ydiv            ; get divisor
  4352.     shr    si,1            ; halve it
  4353.     add    ax,si            ; add in - to round to nearest integer
  4354.     adc    dx,0
  4355.     div    ydiv
  4356.     mov    bx,ybot
  4357.     sub    bx,ax            ; put new Y in right reg
  4358.     jns    scale3            ; ns = not too far
  4359.     xor    bx,bx
  4360. scale3:    pop    ax            ; put new X in right reg
  4361.     mov    scalex,ax        ; save scaled values
  4362.     mov    scaley,bx
  4363.     pop    si
  4364.     pop    dx
  4365.     ret
  4366. SCALE    ENDP
  4367.       
  4368. ; LINE    Subroutine to plot a line with endpoints in AX,BX and SI,DI.
  4369. ;    fast line drawing routine for the IBM PC
  4370. ;
  4371. ; Registers at CALL
  4372. ; -----------------
  4373. ; SI=Start X coord, all in PC coordinates
  4374. ; DI=Start Y coord
  4375. ; AX=End X coord
  4376. ; BX=End Y coord
  4377. ; CCODE=CL=pixel operation code
  4378. ; LINEPAT=BP= line drawing pattern (is changed here by rotation)
  4379. ; registers are all unchanged
  4380.      
  4381. LINE    PROC    NEAR
  4382.     push    ax
  4383.     push    bx
  4384.     push    cx
  4385.     push    dx
  4386.     push    si
  4387.     push    di
  4388.     push    es
  4389.     mov    bp,linepat        ; store active line pattern word in BP
  4390.     mov    dl,ccode        ; existing pixel op code
  4391.     push    dx            ; save around line drawing
  4392.     mov    ccode,cl    ; save color code in ccode for use by plot()
  4393.             ; first get coord to achieve increasing x; deltax >= 0
  4394.     sub    ax,si            ; deltax = x2 - x1
  4395.     jge    line1            ; ge = going to the right, as desired
  4396.     neg    ax            ; make deltax non-negative
  4397.     sub    si,ax            ; swap the x coordinates
  4398.     xchg    bx,di            ; swap the y coordinates too
  4399.                 ; second, compute deltay. ax = deltax, si = x1
  4400. line1:    sub    bx,di            ; deltay = y2 - y1
  4401.     call    psetup            ; setup display adapter for plotting
  4402.                     ;  and setup es:di to screen memory
  4403.   ; Choose algorithm based on |deltay| < |deltax| (use shallow) else steep.
  4404.   ; We arrange matters such that both deltas are non-negative.
  4405.     or    bx,bx            ; deltay
  4406.     jge    line2            ; ge = non-negative
  4407.     neg    linelen
  4408.     neg    bx            ; make non-negative
  4409. line2:    cmp    bx,ax            ; |deltay| versus |deltax|
  4410.     jbe    shallow            ; be = do shallow algorithm
  4411.     jmp    steep            ; else do steep algorithm
  4412.  
  4413.     ; shallow algorithm, move along x, di=y1, bx=deltay, si=x1, ax=deltax
  4414. shallow:add    bx,bx            ; bx = 2*deltay
  4415.     mov    cx,ax            ; cx = number of steps (deltax here)
  4416.     inc    cx            ; loop dec's cx before testing
  4417.     mov    dx,bx            ; dx holds error
  4418.     sub    dx,ax            ; error = 2*deltay - deltax
  4419.     add    ax,ax            ; ax = 2*|deltax|
  4420. shal1:    call    plotptr            ; Plot(x,y)
  4421.     or    dx,dx
  4422.     jle    shal2            ; le =     error <= 0
  4423.     call    pincy            ; increment y by one scan line
  4424.     sub    dx,ax            ; error = error - 2*deltax
  4425. shal2:    add    dx,bx            ; error = error + 2*deltay
  4426.     inc    si            ; x = next dot right
  4427.     loop    shal1
  4428.     jmp    short plotex
  4429.  
  4430.     ; steep algorithm, move along y, di=y1, bx=deltay, si=x1, ax=deltax
  4431. steep:    add    ax,ax            ; ax = 2*deltax
  4432.     mov    dx,ax            ; dx holds error
  4433.     sub    dx,bx            ; error = 2*deltax (ax) - deltay (bx)
  4434.     mov    cx,bx            ; cx = number of steps (deltay here)
  4435.     inc    cx            ; loop dec's cx before testing
  4436.     add    bx,bx            ; bx = 2*|deltay|
  4437. stee1:    call    plotptr            ; Plot(x,y) x = ax, y = di
  4438.     or    dx,dx
  4439.     jle    stee2            ; le  error <= 0
  4440.     inc    si            ; x = next dot right
  4441.     sub    dx,bx            ; error = error - 2*deltay
  4442. stee2:    add    dx,ax            ; error = error + 2*deltax
  4443.     call    pincy            ; increment y
  4444.     loop    stee1
  4445. ;;;    jmp    plotex
  4446.  
  4447. plotex:    pop    dx            ; dl has orginal pixel op
  4448.     mov    ccode,dl        ; restore it
  4449.     pop    es
  4450.     pop    di
  4451.     pop    si
  4452.     pop    dx            ; restore the world
  4453.     pop    cx
  4454.     pop    bx
  4455.     pop    ax
  4456.     ret
  4457. LINE    ENDP
  4458.  
  4459. ; Draw a rectangle.
  4460. ;  lower left corner: x = param[0], y = param[2], Tek coordinates
  4461. ;  distance: dx = param[4], dy = param[6], Tek coordinates, all positive
  4462. rectdraw proc    near
  4463.     push    x_coord
  4464.     push    y_coord
  4465.     mov    ax,param[0]        ; lower left corner is start, x part
  4466.     mov    bx,param[2]        ; y part
  4467.     push    ax            ; x0
  4468.     push    bx            ; y0
  4469.     xor    cl,cl            ; moveto
  4470.     call    tekdraw
  4471.     pop    bx
  4472.     pop    ax
  4473.     add    bx,param[6]        ; y0 + dy
  4474.     mov    cl,1            ; draw x0,y0  to  x0,y0+dy
  4475.     push    ax
  4476.     push    bx
  4477.     call    tekdraw
  4478.     pop    bx
  4479.     pop    ax
  4480.     add    ax,param[4]        ; x0+dx
  4481.     mov    cl,1            ; draw x0,y0+dy  to  x0+dx,y0+dy
  4482.     push    ax
  4483.     call    tekdraw
  4484.     pop    ax
  4485.     mov    bx,param[2]        ; y0
  4486.     push    bx
  4487.     mov    cl,1
  4488.     call    tekdraw
  4489.     pop    bx
  4490.     mov    ax,param[0]        ; x0
  4491.     mov    cl,1
  4492.     call    tekdraw            ; complete the box
  4493.     pop    y_coord
  4494.     pop    x_coord
  4495.     ret
  4496. rectdraw endp
  4497.  
  4498. ; Fill a rectangle with a given pattern.
  4499. ;  lower left corner: x = param[0], y = param[2], Tek coordinates
  4500. ;  distance: dx = param[4], dy = param[6], Tek coordinates, all positive
  4501. ;  fill pattern = param[8]
  4502. rectfil    proc    near
  4503.     push    oldx
  4504.     push    oldy            ; save regular point/line old coords
  4505.     mov    ax,param        ; get Tek X coord of lower left corner
  4506.     mov    bx,param[2]        ; get Tek Y coord
  4507.     call    scale            ; convert to PC in ax,bx, scalex/y
  4508.     mov    rectx1,ax        ; lower left corner in PC coords
  4509.     mov    recty1,bx
  4510.     mov    ax,param        ; convert ending points, start Tek X
  4511.     add    ax,param[4]        ; Tek X + DX
  4512.     mov    bx,param[2]        ; start Tek Y
  4513.     add    bx,param[6]        ; Tek Y + DY
  4514.     call    scale
  4515.     pop    oldy
  4516.     pop    oldx
  4517.     mov    rectx2,ax        ; upper right corner PC X coord
  4518.     mov    recty2,bx        ; upper right corner PC Y coord
  4519.     mov    si,rectx1        ; starting x PC coord to si
  4520.     mov    di,recty2        ; starting y PC coord to di
  4521.     mov    cx,recty1        ; plotting from top down on screen
  4522.     sub    cx,bx            ; cx = # scan lines - 1
  4523.     mov    numlines,cx        ; remember here
  4524.     mov    bx,param[8]        ; fill pattern number
  4525.     or    bx,bx            ; zero?
  4526.     jz    rectfi1            ; z = yes, use current pointer
  4527.     cmp    bx,numfil        ; pattern number is too large?
  4528.     ja    rectfi1            ; a = yes, use current pointer
  4529.     dec    bx            ; count internally from 0
  4530.     shl    bx,1            ; make this a word pointer
  4531.     mov    bx,fillist[bx]        ; get pointer to pattern
  4532.     mov    fillptr,bx        ; remember it here
  4533. rectfi1:mov    cx,rectx2        ; ending x coord
  4534.     sub    cx,rectx1        ; number of horizontal pixels - 1
  4535.     inc    cx            ; number of horizontal pixels
  4536.     call    psetup            ; set up dsp and di to screen offset
  4537.             ; di points to whole byte, do bits in byte in gfplot
  4538. rectfi2:push    bx
  4539.      mov    bx,recty1        ; lower screen y (larger value)
  4540.     sub    bx,numlines        ; alignment: global screen sync
  4541.     and    bx,7            ; modulo 8
  4542.     add    bx,fillptr        ; offset of fill pattern start
  4543.     mov    bl,[bx]            ; pattern byte
  4544.     mov    fill,bl            ; save here for gfplot
  4545.     pop    bx
  4546.     call    gfplot            ; line fill routine
  4547.     call    pincy            ; next line
  4548.     dec    numlines
  4549.     jns    rectfi2            ; ns = more to do
  4550.     ret
  4551. rectfil    endp
  4552.  
  4553. ; Data General D463/D470 plotting routines
  4554.  
  4555. ; RS G B turn on DG crosshairs
  4556. dgcrosson proc    far
  4557.     test    dgcross,1        ; on now?
  4558.     jnz    dgcroson1        ; nz = yes
  4559.     call    crossini        ; init crosshair routine
  4560.     or    dgcross,1        ; say crosshairs are on
  4561. dgcroson1:ret
  4562. dgcrosson endp
  4563.  
  4564. ; RS G C turn off DG crosshairs
  4565. dgcrossoff proc far
  4566.     test    dgcross,1        ; off now?
  4567.     jz    dgcrosof2        ; z = yes
  4568.     test    dgcross,8        ; on but invisible?
  4569.     jz    dgcrosof1        ; z = no
  4570.     call    crosdrawh        ; restore crosshairs
  4571.     call    crosdrawv
  4572. dgcrosof1:call    crossfin        ; finish crosshair routine & exit
  4573.     and    dgcross,not 1+8        ; say crosshair is deactiviated
  4574. dgcrosof2:ret
  4575. dgcrossoff endp
  4576.  
  4577. ; Set DG crosshairs to DG locations x (ax) and y (bx)
  4578. dgsetcrloc proc    far
  4579.     test    dgcross,1        ; is cross hair on?
  4580.     jz    dgsetcr1        ; z = no
  4581.     test    dgcross,8        ; is cross hair invisible?
  4582.     jnz    dgsetcr1        ; nz = yes
  4583.     push    ax            ; save arguments
  4584.     push    bx
  4585.     call    crosdrawh        ; remove present crosshairs
  4586.     call    crosdrawv
  4587.     pop    bx
  4588.     pop    ax
  4589. dgsetcr1:cmp    ax,dgxmax        ; DG x max, exceeded?
  4590.     jb    dgsetcr2        ; b = in range
  4591.     mov    ax,dgxmax        ; else set to max
  4592.     dec    ax
  4593. dgsetcr2:mov    si,ax
  4594.     call    dg2pcx            ; convert DG to PC x in SI
  4595.     mov    xcross,si
  4596.     mov    di,bx
  4597.     call    dg2pcy            ; convert DG to PC y in DI
  4598.     sub    di,ybot
  4599.     add    di,charhgt
  4600.     neg    di            ; reflect top to bottom
  4601.     mov    ycross,di
  4602.     test    dgcross,1        ; is crosshair on?
  4603.     jz    dgsetcr4        ; z = no
  4604.     call    setmouse        ; set the mouse there too
  4605.     call    crosdrawh        ; draw crosshairs
  4606.     call    crosdrawv
  4607.     and    dgcross,not 8        ; say cross is visible
  4608. dgsetcr4:ret
  4609. dgsetcrloc endp
  4610.  
  4611. ; Data General D463/D470  RS G ? |  report crosshair location
  4612. dgcrossrpt proc    far
  4613.     mov    al,RS            ; report RS O |  <nnnnn> <nnnnn><CR>
  4614.     call    outmodem
  4615.     mov    al,'o'            ; must be lower case, manual is wrong
  4616.     call    outmodem
  4617.     mov    al,'|'
  4618.     call    outmodem
  4619.     mov    al,' '            ; space separator
  4620.     call    outmodem
  4621.     mov    ax,xcross        ; x PC coordinate
  4622.     mov    cx,dgxmax        ; DG max X
  4623.     mul    cx
  4624.     mov    cx,xmax            ; max PC x coordinate
  4625.     add    cx,7            ; account for char width effect
  4626.     div    cx            ; use quotient in AX
  4627.     call    out5digit        ; output 5 digit ASCII result
  4628.     mov    al,' '            ; space separator
  4629.     call    outmodem
  4630.     mov    ax,ybot
  4631.     sub    ax,charhgt
  4632.     mov    cx,ax            ; save PC screen height
  4633.     sub    ax,ycross        ; PC coordinates from bottom
  4634.     mul    dgymax            ; DG max y
  4635.     div    cx            ; use quotient in AX
  4636.     call    out5digit        ; output 5 digit ASCII result
  4637.     mov    al,CR            ; terminal character
  4638.     call    outmodem
  4639.     ret
  4640. dgcrossrpt endp
  4641.  
  4642. ; send 5 digit ASCII number (zero filled on the left) found in AX
  4643. out5digit proc near
  4644.     push    di
  4645.     mov    di,offset stripbc    ; use this as temp buffer
  4646.     mov    word ptr [di],'00'
  4647.     mov    word ptr [di+2],'00'
  4648.     inc    di            ; first digit is always 0
  4649.     cmp    ax,1000
  4650.     jae    out5d2
  4651.     inc    di
  4652.     cmp    ax,100
  4653.     jae    out5d2
  4654.     inc    di
  4655.     cmp    ax,10
  4656.     jae    out5d2
  4657.     inc    di
  4658. out5d2:    call    dec2di            ; convert and write to di
  4659.     mov    di,offset stripbc
  4660.     mov    cx,5
  4661. out5d4:    mov    al,[di]
  4662.     push    cx
  4663.     push    di
  4664.     call    outmodem
  4665.     pop    di
  4666.     pop    cx
  4667.     inc    di
  4668.     loop    out5d4
  4669.     pop    di
  4670.     ret
  4671. out5digit endp
  4672.  
  4673. ; Set Data General coloring for graphics fore/background, gfcol and gbcol,
  4674. ; by breaking apart the "curattr" from text mode.
  4675. dgsetcol proc    near
  4676.     push    ax
  4677.     push    cx
  4678.     mov    al,curattr
  4679.     mov    ah,al            ; copy it
  4680.     and    al,0fh            ; isolate foreground color
  4681.     mov    gfcol,al        ; set it
  4682.     mov    cl,4
  4683.     and    ah,70h
  4684.     shr    ah,cl            ; get to background field
  4685.     cmp    plotptr,offset pltega    ; ega dot plot routine?
  4686.     je    dgsetco2        ; e = yes
  4687.     cmp    ah,al            ; same color for fore/back?
  4688.     jne    dgsetco1        ; ne = no
  4689.     mov    gfcol,0            ; set foreground to black
  4690.     jmp    short dgsetco2
  4691. dgsetco1:xor    ah,ah            ; set background to black
  4692. dgsetco2:mov    gbcol,ah        ; set it
  4693.     pop    cx
  4694.     pop    ax
  4695.     ret
  4696. dgsetcol endp
  4697.  
  4698. dgline    proc    far             ; (x,y,x,y,pattern,mar_bot+mar_top)
  4699.     push    bp
  4700.     mov    bp,sp            ; C calling convention
  4701.     push    es
  4702.     push    si
  4703.     push    di
  4704.     push    dx
  4705.     push    linepat
  4706.     mov    al,gfcol        ; current screen background
  4707.     mov    ah,gbcol
  4708.     push    ax
  4709.     test    dgcross,1        ; is cross hair on?
  4710.     jz    dgline1            ; z = no
  4711.     test    dgcross,8        ; is cross hair invisible?
  4712.     jnz    dgline1            ; nz = yes
  4713.     call    crosdrawh        ; remove present crosshairs
  4714.     call    crosdrawv
  4715.     or    dgcross,8        ; say cross is invisible
  4716. dgline1:call    dgsetcol        ; get current coloring
  4717.  
  4718.     mov    di,[bp+6+6]        ; end y, DG coordinates
  4719.     call    dg2pcy            ; scale to PC y in di
  4720.     add    di,charhgt
  4721.     sub    di,ybot
  4722.     neg    di            ; PC end y, top to bottom flip
  4723.     mov    bx,di            ; PC end y in BX
  4724.  
  4725.     mov    di,[bp+6+2]        ; start y, DG coordinates
  4726.     call    dg2pcy            ; scale to PC y in di
  4727.     add    di,charhgt
  4728.     sub    di,ybot
  4729.     neg    di            ; start y, top to bottom flip
  4730.  
  4731.     mov    si,[bp+6+4]        ; end DG X
  4732.     call    dg2pcx            ; convert to PC x in SI
  4733.     mov    ax,si            ; AX is end x
  4734.  
  4735.     mov    si,[bp+6+0]        ; start x
  4736.     call    dg2pcx            ; convert to PC x in SI
  4737.  
  4738.     mov    cl,pixfor+pixbak    ; do all dots
  4739.     push    [bp+6+8]        ; line pattern
  4740.     pop    linepat            ; set it
  4741.     call    line            ; draw the line
  4742.     pop    ax
  4743.     mov    gfcol,al
  4744.     mov    gbcol,ah
  4745.     pop    linepat
  4746.     pop    dx
  4747.     pop    di
  4748.     pop    si
  4749.     pop    es
  4750.     pop    bp
  4751.     ret
  4752. dgline    endp
  4753.  
  4754. dgbar    proc    far ; (startx,starty,width,height,code, mar_top, mar_bot)
  4755.     push    bp
  4756.     mov    bp,sp            ; C calling convention
  4757.     push    es
  4758.     push    si
  4759.     push    di
  4760.     push    dx
  4761.     mov    ah,gbcol
  4762.     mov    al,gfcol
  4763.     push    ax
  4764.  
  4765.     mov    ax,charhgt        ; current char height
  4766.     mov    dx,[bp+6+10]        ; dx = mar_top
  4767.     mul    dl            ; dots to top of mar_top line
  4768.     mov    yresval,ax        ; top margin line
  4769.     mov    ax,charhgt        ; current char height
  4770.     mov    dx,[bp+6+12]        ; dx = mar_bot
  4771.     mul    dl            ; dots to bot of mar_bot line
  4772.     add    ax,charhgt        ; dots to bottom of mar_bot line
  4773.     mov    yresval+2,ax        ; bottom margin line
  4774.  
  4775.     mov    si,[bp+6+0]        ; DG start x
  4776.     add    si,[bp+6+4]        ; DG x width
  4777.     call    dg2pcx            ; convert to PC x in SI
  4778.     mov    ax,xmax
  4779.     add    ax,7            ; right most dot
  4780.     cmp    si,ax            ; out of bounds?
  4781.     jbe    dgbar1            ; be = no
  4782.     mov    si,ax            ; clip to right margin
  4783. dgbar1:    mov    rectx2,si        ; PC end/right x in rectx2
  4784.  
  4785.     mov    si,[bp+6+0]        ; DG start x
  4786.     call    dg2pcx            ; convert to PC x in SI
  4787.     mov    rectx1,si        ; PC start/left x in rectx1
  4788.  
  4789.     mov    di,[bp+6+2]        ; start y, DG coordinates
  4790.     add    di,[bp+6+6]        ; plus DG height
  4791.     call    dg2pcy            ; convert to PC y in DI
  4792.     add    di,charhgt
  4793.     sub    di,ybot
  4794.     neg    di            ; top to bottom flip
  4795.     cmp    di,yresval        ; above top margin line?
  4796.     jae    dgbar2            ; ae = no
  4797.     mov    di,yresval
  4798. dgbar2:    mov    recty2,di        ; PC end/top y in recty2
  4799.  
  4800.     mov    di,[bp+6+2]        ; start y, DG coordinates
  4801.     call    dg2pcy            ; convert to PC y in DI
  4802.     add    di,charhgt
  4803.     sub    di,ybot
  4804.     neg    di            ; top to bottom flip
  4805.     cmp    di,yresval+2        ; below bottom margin?
  4806.     jbe    dgbar3            ; be = no
  4807.     mov    di,yresval+2        ; clip to bottom margin
  4808. dgbar3:    mov    recty1,di        ; PC start/bot y in recty1
  4809.     call    remcursor        ; remove text cursor
  4810.     test    dgcross,1        ; is cross hair on?
  4811.     jz    dgbar4            ; z = no
  4812.     test    dgcross,8        ; is cross hair visible?
  4813.     jnz    dgbar4            ; nz = no
  4814.     call    crosdrawh        ; remove present crosshairs
  4815.     call    crosdrawv
  4816.     or    dgcross,8        ; say cross is invisible
  4817. dgbar4:    mov    si,rectx1        ; left x PC coord to si
  4818.     mov    di,recty2        ; top y PC coord to di
  4819.     mov    cx,recty1        ; plotting from top down on screen
  4820.     sub    cx,di            ; cx = # scan lines - 1
  4821.     inc    cx
  4822.     mov    numlines,cx        ; remember here
  4823.     call    dgsetcol
  4824.     mov    ccode,pixfor        ; write in foreground color
  4825.     cmp    byte ptr [bp+6+8],0    ; color, 0=background, 1=foreground
  4826.     jne    dgbar5            ; ne = foreground
  4827.     mov    ccode,pixbak        ; write in background color
  4828. dgbar5:    mov    cx,rectx2        ; ending x coord
  4829.     sub    cx,rectx1        ; number of horizontal pixels - 1
  4830.     inc    cx            ; number of horizontal pixels
  4831.     call    psetup            ; set up dsp and di to screen offset
  4832.             ; di points to whole byte, do bits in byte in gfplot
  4833.     mov    fill,0ffffh
  4834. dgbar6:    call    gfplot            ; line fill routine, uses CX
  4835.     call    pincy            ; next line
  4836.     dec    numlines
  4837.     cmp    numlines,0        ; done all lines?
  4838.     jg    dgbar6            ; g = still lines to do
  4839.     pop    ax
  4840.     mov    gbcol,ah
  4841.     mov    gfcol,al
  4842.     pop    dx
  4843.     pop    di
  4844.     pop    si
  4845.     pop    es
  4846.     pop    bp
  4847.     ret
  4848. dgbar    endp
  4849.  
  4850. dgarc    proc    far ;dgarc(center x, center y, radius, start angle, end angle,
  4851. ;                mar_top, mar_bot)
  4852.     push    bp
  4853.     mov    bp,sp
  4854.     mov    al,gfcol
  4855.     mov    ah,gbcol
  4856.     push    ax
  4857.     push    si
  4858.     push    di
  4859.     push    es
  4860.     call    remcursor        ; remove text cursor
  4861.     call    dgsetcol
  4862.     mov    si,[bp+6+0]        ; x center
  4863.     call    dg2pcx            ; x center in PC units in SI
  4864.     inc    si            ; plus one dot safety on PC screen
  4865.     mov    scalex,si        ; store here
  4866.  
  4867.     mov    di,[bp+6+2]        ; y center
  4868.     call    dg2pcy            ; y center in PC units in DI
  4869.     mov    scaley,di        ; store here
  4870.  
  4871.     mov    ax,[bp+6+6]        ; start angle for CCW motion
  4872.     xor    dx,dx
  4873.     mov    cx,360
  4874.     div    cx            ; start angle in ax, modulo 360
  4875.     mov    angle,dx        ; actual start angle, mod 360
  4876.  
  4877.     mov    ax,[bp+6+8]        ; end angle for CCW motion
  4878.     mov    bx,[bp+6+6]        ; start angle
  4879.     mov    cx,bx
  4880.     add    cx,ax
  4881.     cmp    cx,720            ; more than one circle?
  4882.     jb    dgarc1            ; b = no
  4883.     mov    ax,cx            ; make end angle much larger than strt
  4884.     cmp    ax,bx            ; less than starting angle?
  4885.     jae    dgarc1            ; ae = no
  4886.     add    ax,360            ; add one rev
  4887. dgarc1:    cmp    ax,angle        ; starting angle
  4888.     jae    dgarc2            ; ae = angle <= angle+2, is ok
  4889.     cmp    angle,360        ; special case?
  4890.     je    dgarc2            ; e = yes
  4891.     xchg    ax,angle        ; make angle <= angle+2
  4892. dgarc2:    mov    angle+2,ax        ; ending angle
  4893.  
  4894.     mov    ax,charhgt        ; current char height
  4895.     mov    dx,[bp+6+10]        ; dx = mar_top
  4896.     mul    dl            ; dots to top of mar_top line
  4897.     mov    yresval,ax        ; top margin line
  4898.     mov    ax,charhgt        ; current char height
  4899.     mov    dx,[bp+6+12]        ; dx = mar_bot
  4900.     mul    dl            ; dots to bot of mar_bot line
  4901.     add    ax,charhgt        ; dots to bottom of mar_bot line
  4902.     mov    yresval+2,ax        ; bottom margin line
  4903.     test    dgcross,1        ; is cross hair on?
  4904.     jz    dgarc3            ; z = no
  4905.     test    dgcross,8        ; is cross hair invisible?
  4906.     jnz    dgarc3            ; nz = yes
  4907.     call    crosdrawh        ; remove present crosshairs
  4908.     call    crosdrawv
  4909.     or    dgcross,8        ; say cross is invisible
  4910. dgarc3:
  4911.     mov    dl,ccode        ; existing pixel op code
  4912.     push    dx            ; save around line drawing
  4913.     push    linepat
  4914.     mov    si,[bp+6+4]        ; radius
  4915.     mov    di,si
  4916.     call    dg2pcx            ; x axis
  4917.     mov    yresval+4,si        ; save radius in PC x units
  4918.     call    dg2pcy
  4919.     mov    yresval+6,di        ; save radius in PC y units
  4920.     call    dg2pcx
  4921.  
  4922.     mov    bx,angle        ; start angle
  4923.     call    dgasin            ; convert point to SI,DI DG coord
  4924.     call    dg2pcy            ; and to PC y coordinate
  4925.     add    di,scaley        ; add center
  4926.     sub    di,ybot
  4927.     add    di,charhgt
  4928.     neg    di
  4929.     mov    recty1,di        ; y1 in virtual units
  4930.  
  4931.     add    si,scalex        ; add center to PC x coord
  4932.     mov    rectx1,si        ; x1 in virtual units
  4933.     mov    linepat,0ffffh
  4934.     mov    bx,angle        ; start angle
  4935.  
  4936. dgarc4:    inc    bx            ; step angle
  4937.     cmp    bx,angle+2        ; done yet?
  4938.     jbe    dgarc5            ; be = no
  4939.     mov    bx,angle+2        ; end angle
  4940. dgarc5:    mov    angle,bx        ; new start
  4941.     call    dgasin            ; convert BX point to SI,DI PC coord
  4942.     add    di,scaley        ; add center
  4943.     sub    di,ybot            ; flip top to bottom
  4944.     add    di,charhgt
  4945.     neg    di
  4946.     mov    recty2,di        ; y2 in PC units
  4947.     add    si,scalex        ; add center
  4948.     mov    rectx2,si        ; x2 in PC units
  4949.  
  4950.     mov    si,rectx1
  4951.     mov    di,recty1        ; start x,y
  4952.     mov    ax,rectx2    
  4953.     mov    bx,recty2        ; end x,y
  4954.     cmp    di,yresval        ; is start above top margin?
  4955.     jb    dgarc6            ; b = yes, no plot
  4956.     cmp    bx,yresval        ; and end point?
  4957.     jb    dgarc6            ; b = yes, no plot
  4958.     cmp    di,yresval+2        ; is start below bottom margin?
  4959.     ja    dgarc6            ; a = yes, no plot
  4960.     cmp    bx,yresval+2        ; end point?
  4961.     ja    dgarc6            ; a = yes, no plot
  4962.     mov    cl,pixfor
  4963.     call    line            ; draw line segment
  4964. dgarc6:    mov    ax,rectx2        ; shift end to start
  4965.     mov    rectx1,ax
  4966.     mov    ax,recty2
  4967.     mov    recty1,ax
  4968.     mov    bx,angle        ; start angle
  4969.     cmp    bx,angle+2        ; done to end angle yet?
  4970.     jb    dgarc4            ; b = no
  4971.     pop    linepat
  4972.     pop    dx            ; save around line drawing
  4973.     mov    ccode,dl        ; existing pixel op code
  4974.     pop    es
  4975.     pop    di
  4976.     pop    si
  4977.     pop    ax
  4978.     mov    gfcol,al
  4979.     mov    gbcol,ah
  4980.     pop    bp
  4981.     ret
  4982. dgarc    endp
  4983.  
  4984. ; Provide x,y coordinates in DG address frame, given radius and angle (deg,
  4985. ; ccw from the positve x axis). X is in SI, Y is in DI.
  4986. ; Radius is in yresval+4 for x and yresval+6 for y, angle is in bx.
  4987. dgasin    proc    near            ; x = r cos(theta), y = r sin(x)
  4988.     push    ax
  4989.     push    bx
  4990.     push    cx
  4991.     push    dx
  4992.     push    es
  4993.     mov    cx,seg sin        ; sine lookup table, 90/64 deg steps
  4994.     mov    es,cx
  4995.     mov    ax,bx
  4996.     mov    cx,360
  4997.     push    dx
  4998.     xor    dx,dx
  4999.     div    cx            ; remove extra 360's
  5000.     mov    bx,dx            ; keep remainder
  5001.     pop    dx            ; bx now has angle mod 360
  5002.                     ; do quadrants
  5003.     xor    si,si            ; assume right side
  5004.     xor    di,di            ; and top
  5005.     cmp    bx,180            ; left or right?
  5006.     jbe    dgasin1            ; be = right
  5007.     mov    di,-1            ; remember to flip sign
  5008.     sub    bx,360
  5009.     neg    bx
  5010. dgasin1:cmp    bx,90            ; top or bottom
  5011.     jbe    dgasin2            ; be = top
  5012.     mov    si,-1            ; say bottom
  5013.     sub    bx,180            ; flip
  5014.     neg    bx
  5015. dgasin2:cmp    bx,90            ; at the upper limit?
  5016.     jne    dgsin2a            ; ne = no
  5017.     mov    ax,256            ; set 16 bit value
  5018.     jmp    short dgsin2b
  5019. dgsin2a:mov    al,es:sin[bx]        ; 256 times sine
  5020.     xor    ah,ah
  5021. dgsin2b:push    dx
  5022.     mul    yresval+6        ; times radius in y reference frame
  5023.     mov    al,ah
  5024.     mov    ah,dl            ; divide by 256
  5025.     pop    dx
  5026.     or    di,di            ; need a sign change?
  5027.     jz    dgasin3            ; z = no
  5028.     neg    ax            ; flip it
  5029. dgasin3:mov    di,ax
  5030.     
  5031.     sub    bx,90            ; bx is an index by now
  5032.     neg    bx            ; 90 - theta for cos
  5033.     cmp    bx,90            ; at the limit?
  5034.     jne    dgsin3a            ; ne = no
  5035.     mov    ax,256            ; set 16 bit value
  5036.     jmp    short dgsin3b
  5037. dgsin3a:mov    al,es:sin[bx]        ; 256 times cosine
  5038.     xor    ah,ah
  5039. dgsin3b:mul    yresval+4        ; radius in x reference frame
  5040.     mov    al,ah
  5041.     mov    ah,dl            ; divide by 256
  5042.     or    si,si            ; need a sign change?
  5043.     jz    dgasin4            ; z = no
  5044.     neg    ax
  5045. dgasin4:mov    si,ax
  5046.     pop    es
  5047.     pop    dx
  5048.     pop    cx
  5049.     pop    bx
  5050.     pop    ax
  5051.     ret
  5052. dgasin    endp
  5053.  
  5054. ; Convert DG X coordinate in SI to PC screen coordinate in SI
  5055. dg2pcx    proc    near
  5056.     push    ax
  5057.     push    cx
  5058.     push    dx
  5059.     mov    ax,si
  5060.     mov    cx,xmax            ; PC screen width - 8 dots
  5061.     add    cx,7            ; right most dot
  5062.     imul    cx
  5063.     mov    cx,dgxmax        ; DG width
  5064.     idiv    cx            ; AX gets PC dots across
  5065.     mov    si,ax
  5066.     pop    dx
  5067.     pop    cx
  5068.     pop    ax
  5069.     ret
  5070. dg2pcx    endp
  5071.  
  5072. ; Convert DG Y coordinate in DI to PC screen coordinate in DI
  5073. dg2pcy    proc    near
  5074.     push    ax
  5075.     push    cx
  5076.     push    dx
  5077.     mov    ax,di
  5078.     mov    cx,ybot            ; PC screen height
  5079.     sub    cx,charhgt        ; minus status line
  5080.     imul    cx
  5081.     mov    cx,dgymax        ; DG height
  5082.     idiv    cx
  5083.     mov    di,ax            ; ax has PC dots y dots
  5084.     pop    dx
  5085.     pop    cx
  5086.     pop    ax
  5087.     ret
  5088. dg2pcy    endp
  5089.  
  5090. ; Fill non-intersecting polygon whose vertices are specified as x,y word 
  5091. ; pairs in rdbuf+2. Word rdbuf has count of the pairs. Closure is implied. 
  5092. ; Coordinates are DG. Permit up to 255 vertices. PC text lines mar_top
  5093. ; and mar_bot are in the last two words of rdbuf+2.
  5094. dgpoly    proc    far
  5095.     push    linepat            ; save existing line pattern
  5096.     push    si
  5097.     push    di
  5098.     mov    al,gfcol
  5099.     mov    ah,gbcol
  5100.     push    ax
  5101.     call    remcursor        ; remove text cursor
  5102.     test    dgcross,1        ; is cross hair on?
  5103.     jz    dgpoly1            ; z = no
  5104.     test    dgcross,8        ; is cross hair invisible?
  5105.     jnz    dgpoly1            ; nz = yes
  5106.     call    crosdrawh        ; remove present crosshairs
  5107.     call    crosdrawv
  5108.     or    dgcross,8        ; say cross is invisible
  5109. dgpoly1:call    dgsetcol        ; set coloring
  5110.     mov    bx,offset rdbuf        ; list: count, pairs of x,y
  5111.     mov    cx,[bx]            ; get pair count
  5112.     add    bx,2            ; start of x,y word pairs
  5113.     mov    ax,ybot            ; largest PC y value
  5114.     mov    recty1,ax        ; smallest PC y
  5115.     mov    recty2,0        ; largest PC y
  5116. dgpoly2:mov    si,[bx]            ; get DG x
  5117.     call    dg2pcx            ; convert to PC x coord
  5118.     mov    [bx],si            ; write back to list
  5119.     add    bx,2
  5120.     mov    di,[bx]            ; get DG y
  5121.     cmp    di,dgymax        ; too tall?
  5122.     jbe    dgpoly2a        ; be = no
  5123.     mov    di,dgymax        ; clip to top
  5124. dgpoly2a:call    dg2pcy            ; convert to PC y coord
  5125.     sub    di,ybot
  5126.     add    di,charhgt
  5127.     neg    di            ; invert for PC coord
  5128.     mov    [bx],di            ; write back to list
  5129.     cmp    di,recty1        ; smaller?
  5130.     jae    dgpoly3            ; ae = no
  5131.     mov    recty1,di        ; smallest PC y
  5132. dgpoly3:cmp    di,recty2        ; larger?
  5133.     jbe    dgpoly4            ; be = no
  5134.     mov    recty2,di        ; largest PC y
  5135. dgpoly4:add    bx,2
  5136.     loop    dgpoly2            ; do entire list
  5137.                     ; top/bottom margin clipping
  5138.     mov    ax,charhgt        ; current char height
  5139.     mov    dx,[bx]            ; dx = mar_top
  5140.     mul    dl            ; dots to top of mar_top line
  5141.     cmp    ax,recty1        ; is top margin higher (less)?
  5142.     jbe    dgpoly4a        ; be = yes, no top clipping
  5143.     mov    recty1,ax        ; clip to top margin
  5144. dgpoly4a:mov    ax,charhgt        ; current char height
  5145.     mov    dx,[bx+2]        ; dx = mar_bot
  5146.     mul    dl            ; dots to bot of mar_bot line
  5147.     add    ax,charhgt        ; dots to bottom of mar_bot line
  5148.     dec    ax
  5149.     cmp    ax,recty2        ; is bot margin lower (more)?
  5150.     jae    dgpoly4b        ; ae = yes, no bottom clipping
  5151.     mov    recty2,ax        ; clip to bottom margin
  5152. dgpoly4b:mov    si,word ptr rdbuf+2    ; get start of list
  5153.     mov    di,word ptr rdbuf+4
  5154.     mov    [bx],si            ; close the polygon
  5155.     mov    [bx+2],di
  5156.  
  5157.     mov    di,recty1        ; starting scan line, smallest PC y
  5158.     mov    linepat,0ffffh        ; solid lines
  5159. dgpoly5:call    dginter            ; make list of intersections to decbuf
  5160.     cmp    word ptr decbuf,2    ; any elements to be sorted/plotted?
  5161.     jb    dgpoly7            ; b = no
  5162.     call    dgsort            ; sort x list in decbuf
  5163.     mov    bx,offset decbuf+2
  5164. dgpoly6:mov    si,[bx]            ; start x
  5165.     mov    ax,[bx+2]         ; end x
  5166.     mov    cx,xmax            ; right edge clipping test
  5167.     add    cx,7            ; last dot to the right
  5168.     cmp    ax,cx            ; offscreen to the right?
  5169.     jbe    dgpoly6a        ; be = no
  5170.     mov    ax,cx            ; clip to right edge
  5171. dgpoly6a:cmp    si,cx            ; this edge too?
  5172.     jbe    dgpoly6b        ; be = in bounds
  5173.     mov    si,cx
  5174. dgpoly6b:add    bx,4            ; two words processed from list
  5175.     sub    word ptr decbuf,2    ; two x elements taken care of
  5176.     cmp    si,ax            ; same place?
  5177.     je    dgpoly6c        ; e = yes
  5178.     push    bx
  5179.     push    di            ; save reg
  5180.     mov    bx,di            ; end y, start y is in di
  5181.     mov    cl,pixfor        ; do just foreground dots
  5182.     call    line            ; draw the line
  5183.     pop    di
  5184.     pop    bx
  5185. dgpoly6c:cmp    word ptr decbuf,2    ; done all?
  5186.     jge    dgpoly6            ; ge = no, do reset of list
  5187. dgpoly7:inc    di            ; next scan line
  5188.     cmp    di,recty2        ; at end of figure?
  5189.     jbe    dgpoly5            ; be = no, do more scan lines
  5190.     pop    ax
  5191.     mov    gfcol,al
  5192.     mov    gbcol,ah
  5193.     pop    di
  5194.     pop    si
  5195.     pop    linepat            ; restore line pattern
  5196.     ret
  5197. dgpoly    endp
  5198.  
  5199. ; Provide PC x coordinate of intersections of a line with logical scan line 
  5200. ; DI. List of x,y pairs (nodes) is in rdbuf+2 et seq, count of them in rdbuf
  5201. ; Writes x intersections to words in decbuf+2 et seq, count in decbuf.
  5202. dginter proc    near
  5203.     push    dx
  5204.     mov    si,offset decbuf+2    ; final x list
  5205.     mov    word ptr decbuf,0    ; number detected for this scan line
  5206.     mov    bx,offset rdbuf+2    ; index into x,y array
  5207.     mov    cx,[bx-2]        ; count of nodes (3 or more)
  5208. dginter1:push    cx            ; see if line crosses this scan line
  5209.     mov    ax,[bx+2]         ; y[index]
  5210.     mov    cx,[bx+2+4]        ; y[index+1]
  5211.     cmp    ax,cx
  5212.     jbe    dginter2        ; be = ax is higher or same on screen
  5213.     xchg    ax,cx            ; make ax smaller than cx
  5214.  
  5215. dginter2:cmp    di,ax             ; yscan vs y[index]
  5216.     jb    dginter7        ; b = above this scan line
  5217.     cmp    di,cx             ; yscan vs y[index+1]
  5218.     ja    dginter7        ; a = below this line
  5219.     mov    ax,di            ; yscan
  5220.     sub    ax,[bx+2]         ; ax = yscan - y[index]
  5221.     or    ax,ax
  5222.     jnz    dginter5        ; nz = not at a starting node
  5223.     push    ax
  5224.     mov    ax,[bx+2]         ; current y[index]
  5225.     cmp    bx,offset rdbuf+2+2    ; list start (wrap back situation)?
  5226.     jae    dginter3        ; ae = no
  5227.     push    bx
  5228.     mov    bx,word ptr rdbuf    ; count of x,y pairs
  5229.     shl    bx,1
  5230.     shl    bx,1            ; count pairs
  5231.     sub    ax,word ptr rdbuf+2[bx-2] ; y[0] - y[maxindex-1]
  5232.     pop    bx
  5233.     jmp    short dginter4
  5234. dginter3:sub    ax,[bx-2]         ; y[index] - y[index-1]
  5235. dginter4:mov    cx,[bx+2+4]         ; y[index+1]
  5236.     sub    cx,[bx+2]         ; cx = delta y = y[index+1] - y[index]
  5237.     xor    ax,cx            ; compare with above slope
  5238.     pop    ax
  5239.     jns    dginter7        ; ns = same sign, do not count node
  5240.  
  5241. dginter5:or    ax,ax            ; yscan - y[index]
  5242.     jz    dginter6        ; z = at node, don't interpolate
  5243.     mov    cx,[bx+4]         ; x[index+1]
  5244.     sub    cx,[bx]            ; delta x = x[index+1] - x[index]
  5245.     imul    cx
  5246.     mov    cx,[bx+2+4]         ; y[index+1]
  5247.     sub    cx,[bx+2]         ; cx = delta y = y[index+1] - y[index]
  5248.     idiv    cx
  5249. dginter6:add    ax,[bx]            ; plus x[index]
  5250.     mov    [si],ax            ; store in decbuf
  5251.     add    si,2
  5252.     inc    word ptr decbuf        ; say counted a node
  5253. dginter7:pop    cx
  5254.     add    bx,4            ; next x,y pair
  5255.     loop    dginter1
  5256.     pop    dx
  5257.     ret
  5258. dginter endp
  5259.  
  5260. ; Sort array of words decbuf, count then list of elements
  5261. dgsort    proc    near
  5262.     push    dx
  5263.     push    si
  5264.     push    di
  5265.     mov    si,offset decbuf    ; count + list
  5266.     mov    cx,[si]            ; count of items in list
  5267.     dec    cx
  5268.     jcxz    dgsort5    
  5269.     add    si,2            ; point to first element
  5270.     mov    dx,si            ; offset of first element
  5271.     add    dx,cx            ; plus count of elements
  5272.     add    dx,cx            ; offset of last element
  5273. dgsort1:mov    di,si            ; first element
  5274.     add    di,2            ; next element
  5275. dgsort2:mov    ax,[di]            ; next x
  5276.     cmp    ax,[si]            ; current x
  5277.     jae    dgsort3            ; ae = next is larger than current x
  5278.     xchg    ax,[si]            ; interchange elements
  5279.     xchg    ax,[di]
  5280. dgsort3:add    di,2
  5281.     cmp    di,dx            ; finished last element?
  5282.     jbe    dgsort2            ; be = no
  5283.     add    si,2            ; next element of outer loop
  5284.     loop    dgsort1
  5285. dgsort5:pop    di
  5286.     pop    si
  5287.     pop    dx
  5288.     ret
  5289. dgsort    endp
  5290.  
  5291. ;;;;;;; EGA plot support routines
  5292. psetupe    proc    near            ; EGA setup for plotting
  5293.     push    ax
  5294.     mov    linelen,80        ; for y going down screen by pincy
  5295.     mov    ax,segscn        ; set es to screen memory segment
  5296.     mov    es,ax
  5297.     mov    ax,0205h        ; mode: write mode 2
  5298.     call    ega_gc
  5299.     mov    ax,0003h        ; assume writing bits directly
  5300.     test    ccode,pixfor+pixbak    ; direct foreground/background write?
  5301.     jnz    psete2            ; nz = yes
  5302.     mov    ax,1003h        ; assume OR
  5303.     test    ccode,pixor        ; OR?
  5304.     jnz    psete2            ; nz = yes
  5305.     mov    ax,1803h        ; assume XOR
  5306.     test    ccode,pixxor        ; inverting bits?
  5307.     jnz    psete2            ; nz = yes
  5308.     mov    ax,0803h        ; then use AND
  5309. psete2:    call    ega_gc            ; set controller
  5310.     mov    ax,80            ; compute starting point in regen buff
  5311.     mul    di
  5312.     mov    di,ax            ; di = di * 80
  5313.     pop    ax
  5314.     ret
  5315. psetupe    endp
  5316.  
  5317. pincye    proc    near            ; EGA inc y
  5318.     add    di,linelen        ; includes sign of deltay
  5319.     ret
  5320. pincye    endp
  5321.  
  5322. pltega    proc    near        ; EGA plot(x,y). x is in si, y is in di
  5323.     ror    bp,1            ; rotate line pattern
  5324.     jc    pltega1            ; c = a 1 bit to be plotted
  5325.     cmp    ccode,pixfor+pixbak    ; plot both 1's and 0's?
  5326.     je    pltega1            ; e = yes
  5327.     ret                ; else ignore the 0 bit
  5328. pltega1:push    bx
  5329.     push    si
  5330.     push    di
  5331.     mov    bx,xmax
  5332.     add    bx,7            ; last right dot
  5333.     cmp    si,bx            ; going out of bounds?
  5334.     ja    pltega3            ; a = yes, omit the dot plot
  5335.     mov    bx,si            ; want si/8 for bytes along line
  5336.     shr    si,1
  5337.     shr    si,1
  5338.     shr    si,1
  5339.     add    di,si            ; starting point in regen buffer
  5340.     and    bx,0007h        ; leave lower 3 bits for bit in byte
  5341.     mov    bh,masktab[bx]        ; 0-7 into bit mask in byte, x pos
  5342.     mov    bl,ccode        ; get line type code
  5343.     cmp    bl,pixfor+pixbak    ; plot both 1's and 0's?
  5344.     jne    pltega2            ; ne = no
  5345.     mov    bl,pixfor        ; use foreground for ones
  5346.     test    bp,80h            ; bit is a one?
  5347.     jnz    pltega2            ; nz = yes
  5348.     mov    bl,pixbak        ; use background for zeros
  5349. pltega2:call    ega_plt
  5350. pltega3:pop    di
  5351.     pop    si
  5352.     pop    bx
  5353.     ret
  5354. pltega    endp
  5355.  
  5356. ;; Plot bit pattern in "fill" as 8 horizontal pixels, starting at x,y (si,di)
  5357. ; and continuing across the line for cx pixels. psetupe has been called.
  5358. bpltega    proc    near        ; EGA plot(x,y). x is in si, y is in di
  5359.     push    bx
  5360.     push    cx
  5361.     push    si
  5362.     push    di
  5363.     mov    bx,si            ; want si/8 for bytes along line
  5364.     shr    si,1
  5365.     shr    si,1
  5366.     shr    si,1
  5367.     add    di,si            ; starting byte in regen buffer
  5368.                     ; di = offset in regen buffer
  5369.     and    bl,7            ; get bit in byte (di = byte aligned)
  5370.     jz    bplteg1            ; z = aligned already
  5371.     xchg    bl,cl            ; get shift to cl, low count to bl
  5372.     mov    bh,fill            ; 8-bit fill pattern
  5373.     mov    al,bh            ; get complement of pattern too
  5374.     not    al
  5375.     shl    bh,cl            ; trim cl bits from the left
  5376.     shr    bh,cl
  5377.     shl    al,cl            ; trim them from the right edge
  5378.     shr    al,cl            ; restore pattern
  5379.     xchg    cl,bl            ; put count back in cx
  5380.     add    cl,bl            ; add bits taken care of
  5381.     adc    ch,0
  5382.     jmp    short bplteg2        ; do this partial byte now
  5383.  
  5384. bplteg1:mov    bh,fill            ; fill pattern
  5385.     mov    al,bh            ; make inverted pattern
  5386.     not    al
  5387.     cmp    cx,8            ; do all 8 bits?
  5388.     jae    bplteg2            ; ae = yes
  5389.     push    cx            ; final byte fixup
  5390.     sub    cl,8            ; cl = - (number of bits to omit)
  5391.     neg    cl            ; cl = number of bits to omit
  5392.     mov    al,bh            ; get complement of pattern too
  5393.     not    al
  5394.     shr    bh,cl            ; trim them from the right edge
  5395.     shl    bh,cl            ; restore pattern
  5396.     shr    al,cl            ; trim them from the right edge
  5397.     shl    al,cl            ; restore pattern
  5398.     pop    cx
  5399. bplteg2:push    ax
  5400.     cmp    ccode,pixfor+pixbak    ; do both fore and background?
  5401.     jne    bplteg2a        ; ne = no
  5402.     push    bx
  5403.     mov    bh,al            ; get complemented pattern
  5404.     mov    bl,pixbak        ; write background
  5405.     call    ega_plt
  5406.     pop    bx
  5407. bplteg2a:mov    bl,ccode        ; get line type code
  5408.     call    ega_plt
  5409. bplteg3:pop    ax
  5410.     inc    di            ; next byte right
  5411.     sub    cx,8            ; did these
  5412.     cmp    cx,0            ; anything left to do?
  5413.     jg    bplteg1            ; a = yes, repeat
  5414.     pop    di
  5415.     pop    si
  5416.     pop    cx
  5417.     pop    bx
  5418.     ret
  5419. bpltega    endp
  5420.  
  5421. ;;;;;;;; CGA plot support routines
  5422. ; The CGA graphics memory mapping in mode 6 (640 by 200) is 8 dots per byte,
  5423. ; left most dot in the high bit, 80 bytes per scan line, scan line segments
  5424. ; alternating between 0b800h (even lines 0, 2, ...) and 0ba00h (odd lines).
  5425. psetupc    proc    near            ; CGA setup for plotting
  5426.     push    ax
  5427.     push    cx
  5428.     mov    linelen,80        ; 80 bytes per scan line
  5429.     mov    cx,segscn
  5430.     mov    es,cx
  5431.     mov    cx,di            ; save copy of di, start y line
  5432.                     ; compute starting point in regen buff
  5433.     shr    di,1            ; half the lines in each bank
  5434.     mov    ax,80            ; 80 bytes per line
  5435.     mul    di
  5436.     mov    di,ax            ; di = di * 80 / 2
  5437.     test    cx,1            ; even or odd line
  5438.     jz    psetc1            ; z = even
  5439.     add    di,2000h        ; offset to odd bank (seg 0ba00h)
  5440. psetc1:    and    di,3fffh
  5441.     pop    cx
  5442.     pop    ax
  5443.     ret
  5444. psetupc    endp
  5445.  
  5446. pincyc    proc    near            ; CGA inc y
  5447.     cmp    linelen,0        ; increasing or decreasing y?
  5448.     jl    pinyc2            ; l = decreasing
  5449.     cmp    di,2000h        ; in upper bank now?
  5450.     jb    pinyc1            ; b = no, in lower bank
  5451.     add    di,linelen        ; add a line
  5452. pinyc1:    add    di,2000h        ; switch banks
  5453.     and    di,3fffh        ; roll over address
  5454.     ret
  5455. pinyc2:    cmp    di,2000h        ; in upper bank now?
  5456.     jae    pinyc4            ; ae = yes
  5457.     add    di,linelen        ; subtract a line
  5458. pinyc4:    add    di,2000h        ; switch banks
  5459.     and    di,3fffh        ; roll over address
  5460.     ret
  5461. pincyc    endp
  5462.  
  5463. pltcga    proc    near        ; CGA plot(x,y). x is in si, y is in di
  5464.     ror    bp,1            ; rotate line pattern
  5465.     jc    pltcg6            ; c = 1 bit to be plotted
  5466.     cmp    ccode,pixfor+pixbak    ; plot both 1's and 0's?
  5467.     je    pltcg6            ; e = yes
  5468.     ret
  5469. pltcg6:    push    bx        ; used for HGA and Wyse plots also.
  5470.     push    si
  5471.     push    di
  5472.     mov    bx,xmax
  5473.     add    bx,7            ; last right dot
  5474.     cmp    si,bx            ; going out of bounds?
  5475.     ja    pltcg3            ; a = yes, omit the dot plot
  5476.     mov    bx,si            ; want si/8 for bytes along line
  5477.     shr    si,1
  5478.     shr    si,1
  5479.     shr    si,1
  5480.     add    di,si            ; starting point in regen buffer
  5481.     and    bx,0007h        ; leave lower 3 bits for bit in byte
  5482.                     ; di = offset in regen buffer
  5483.     mov    bh,masktab[bx]        ; 0-7 into bit mask in byte. x position
  5484.     mov    bl,ccode        ; get line type code
  5485.     cmp    bl,pixfor+pixbak    ; plot both 1's and 0's?
  5486.     jne    pltcg7            ; ne = no
  5487.     mov    bl,pixfor        ; use foreground for ones
  5488.     test    bp,80h            ; bit is a one?
  5489.     jnz    pltcg7            ; nz = yes
  5490.     mov    bl,pixbak        ; use background for zeros
  5491. pltcg7:
  5492.     test    bl,pixfor+pixor        ; draw in foreground color or OR?
  5493.     jz    pltcg1            ; z = no
  5494.     test    bl,pixor        ; OR?
  5495.     jnz    pltcg5            ; nz = yes
  5496.     test    gfcol,7            ; is foreground dark?
  5497.     jz    pltcg4            ; z = yes, punch a hole
  5498. pltcg5:    or    es:[di],bh        ; drawn
  5499.     jmp    short pltcg3
  5500. pltcg1:    test    bl,pixbak        ; draw in background (erase)?
  5501.     jz    pltcg2            ; z = no
  5502.     test    gbcol,7            ; is background light?
  5503.     jnz    pltcg5            ; nz = yes
  5504. pltcg4:    not    bh            ; invert the bit
  5505.     and    es:[di],bh        ; erase the dot
  5506.     jmp    short pltcg3
  5507. pltcg2:    xor    es:[di],bh        ; xor in this color
  5508. pltcg3:    pop    di
  5509.     pop    si
  5510.     pop    bx
  5511.     ret
  5512. pltcga    endp
  5513.  
  5514. ; Plot bit pattern in fill as 8 horizontal pixels, starting at x,y (si,di)
  5515. ; and continuing across the line for cx pixels. psetupc has been called.
  5516. bpltcga    proc    near        ; CGA plot(x,y). x is in si, y is in di
  5517.     push    bx        ; used for HGA and Wyse plots also.
  5518.     push    cx
  5519.     push    si
  5520.     push    di
  5521.     mov    bx,si            ; want si/8 for bytes along line
  5522.     shr    si,1
  5523.     shr    si,1
  5524.     shr    si,1
  5525.     add    di,si            ; starting byte in regen buffer
  5526.                     ; di = offset in regen buffer
  5527.     and    bl,7            ; get bit in byte (di = byte aligned)
  5528.     jz    bpltcg5            ; z = aligned already
  5529.     xchg    bl,cl            ; get shift to cl, low count to bl
  5530.     mov    bh,fill            ; 8-bit fill pattern
  5531.     shl    bh,cl            ; trim cl bits from the left
  5532.     shr    bh,cl
  5533.     push    cx
  5534.     mov    al,0ffh            ; 1's are original bits to be saved
  5535.     sub    cl,8            ; max field width is 8 bits
  5536.     neg    cl            ; 8-number of bits trimmed from left
  5537.     shl    al,cl            ; al now holds save-field bit pattern
  5538.     pop    cx
  5539.     xchg    cl,bl            ; put count back in cx
  5540.     add    cl,bl            ; add bits taken care of
  5541.     adc    ch,0
  5542.     jmp    short bpltcg4        ; do this partial byte now
  5543.  
  5544. bpltcg5:mov    bh,fill            ; fill pattern
  5545.     xor    al,al            ; assume saving no bits
  5546.     cmp    cx,8            ; do all 8 bits?
  5547.     jae    bpltcg4            ; ae = yes
  5548.     push    cx            ; final byte fixup
  5549.     mov    al,0ffh            ; 1's are original bits to be saved
  5550.     shl    al,cl
  5551.     shr    al,cl            ; al now holds save-field bit pattern
  5552.     sub    cl,8            ; cl = - (number of bits to omit)
  5553.     neg    cl            ; cl = number of bits to omit
  5554.     shr    bh,cl            ; trim them from the right edge
  5555.     shl    bh,cl            ; restore pattern
  5556.     pop    cx
  5557. bpltcg4:mov    bl,ccode        ; get line type code
  5558.     cmp    bl,pixfor+pixbak    ; set both fore and background?
  5559.     jne    bpltcg9            ; ne = no
  5560.     test    gfcol,7            ; is foreground dark?
  5561.     jnz    bpltcg8            ; nz = no
  5562.     not    bh            ; invert the bit pattern
  5563.     or    bh,al            ; set bits to be saved
  5564.     sub    bh,al            ; trim off saved bits from this field
  5565. bpltcg8:mov    ah,es:[di]        ; get contents of memory cell
  5566.     and    ah,al            ; preserve bit field given by al
  5567.     or    bh,ah            ; mask in saved bits
  5568.     mov    es:[di],bh        ; write the byte
  5569.     jmp    short bpltcg3        ; done
  5570. bpltcg9:test    bl,pixfor+pixor        ; draw in foreground?
  5571.     jz    bpltcg1            ; z = no
  5572.     test    bl,pixor        ; OR?
  5573.     jnz    bpltcg7            ; nz = yes
  5574.     test    gfcol,7            ; is foreground dark?
  5575.     jz    bpltcg6            ; z = yes, punch a hole
  5576. bpltcg7:or    es:[di],bh        ; drawn
  5577.     jmp    short bpltcg3
  5578. bpltcg1:test    bl,pixbak        ; draw as background (erase)?
  5579.     jz    bpltcg2            ; z= do not draw as background (erase)
  5580.     test    gbcol,7            ; is background light?
  5581.     jz    bpltcg6            ; z = no
  5582.     or    es:[di],bh        ; drawn
  5583.     jmp    short bpltcg3
  5584. bpltcg6:not    bh
  5585.     and    es:[di],bh        ; erase background dots (0's)
  5586.     jmp    short bpltcg3
  5587. bpltcg2:xor    es:[di],bh        ; xor with these dots
  5588. bpltcg3:inc    di            ; next byte right
  5589.     sub    cx,8            ; did these
  5590.     cmp    cx,0            ; anything left to do?
  5591.     jg    bpltcg5            ; a = yes, repeat
  5592.     pop    di
  5593.     pop    si
  5594.     pop    cx
  5595.     pop    bx
  5596.     ret
  5597. bpltcga    endp
  5598.  
  5599. ;;;;;;; Wyse-700 plot support routines
  5600. ; The Wyse graphics memory map in mode 0D3h (1280 by 800) is 8 dots per byte,
  5601. ; left most dot in the high bit, 160 bytes per scan line, scan line segments
  5602. ; sequence as 0a000h even lines, and same for odd lines
  5603. psetupw proc    near            ; Wyse setup for plotting
  5604.     push    ax
  5605.     push    cx
  5606.     push    dx
  5607.     mov    linelen,160        ; for y going down screen by incy
  5608.     mov    ax,segscn        ; base segment of display memory
  5609.     mov    es,ax
  5610.     mov    cx,di            ; save copy of di, start y line
  5611.                     ; compute starting point in regen buff
  5612.     shr    di,1            ; half the lines in each bank
  5613.     mov    ax,160
  5614.     mul    di
  5615.     mov    di,ax            ; di = di * 160 / 2
  5616.     mov    dx,wymode
  5617.     shr    cx,1            ; compute bank from 1 lsb of line num
  5618.     jnc    psetw2            ; nc = it is in bank 0 (0b000h)
  5619.     mov    ax,wybodd        ; select odd bank
  5620.     out    dx,al
  5621.     jmp    short psetw3
  5622. psetw2: mov    ax,wybeven        ; select even bank
  5623.     out    dx,al
  5624. psetw3: mov    bnkchan, al        ; bank has changed
  5625.     pop    dx
  5626.     pop    cx
  5627.     pop    ax
  5628.     ret
  5629. psetupw endp
  5630.  
  5631. ;
  5632. ; Wyse-700 has two banks. Line 0, 2, 4 ... are in bank 0, and 1, 3, 5 ... are
  5633. ; in bank 1. Lines 0 and 1 have same addresses, lines 2 and 3 have same
  5634. ; addresses etc. We have to change bank every time Y changes but we
  5635. ; have to count new address only after two Y-value changes. Variable
  5636. ; bnkchan is a flag for us to know into which bank to write.
  5637. ;
  5638. pincyw    proc    near            ; Wyse inc y, step offset of line
  5639.     push    ax
  5640.     push    dx
  5641.     mov    dx,wymode        ; Wyse conrol register
  5642.     mov    al,wybeven        ;
  5643.     cmp    bnkchan,wybeven        ; was last write into even bank ?
  5644.     jne    pincywe            ; ne = no
  5645.     mov    al,wybodd        ; yes, set ready for odd bank
  5646.     out    dx,al            ;
  5647.     mov    bnkchan,al        ; set to odd
  5648.     jmp    short pincywo
  5649. pincywe:mov    al,wybeven        ; set ready foe even bank
  5650.     out    dx,al            ; select it
  5651.     mov    bnkchan,al        ; set to odd
  5652. pincywo:cmp    linelen,0        ; increasing y?
  5653.     jg    pinyw2            ; g = yes
  5654.     cmp    al,wybeven        ; from high (1) to low (0) bank ?
  5655.     je    pinyw4            ; e = yes
  5656.     add    di,linelen        ; no, add a line
  5657.     jmp    short pinyw4
  5658. pinyw2: cmp    al,wybodd        ; from low (0) to high (1) bank ?
  5659.     je    pinyw4            ; e = yes
  5660.     add    di,linelen        ; no, add a line
  5661. pinyw4: and    di,0ffffh        ; roll over address
  5662.     pop    dx
  5663.     pop    ax
  5664.     ret
  5665. pincyw    endp
  5666.  
  5667. ;;;;;;; HGA plot support routines
  5668. ; The HGA graphics memory mapping in mode 255 (720 by 348) is 8 dots per byte,
  5669. ; left most dot in the high bit, 90 bytes per scan line, scan line segments
  5670. ; sequence as 0b000h, 0b200h, 0b400h, 0b800h for lines 0-3 and repeat 90 bytes
  5671. ; higher for the rest.
  5672. psetuph    proc    near            ; HGA setup for plotting
  5673.     push    ax
  5674.     push    cx
  5675.     mov    linelen,90        ; for y going down screen by incy
  5676.     mov    ax,segscn        ; base segment of display memory
  5677.     mov    es,ax
  5678.     mov    cx,di            ; save copy of di, start y line
  5679.                     ; compute starting point in regen buff
  5680.     shr    di,1            ; quarter the lines in each bank
  5681.     shr    di,1
  5682.     mov    ax,90
  5683.     mul    di
  5684.     mov    di,ax            ; di = di * 90 / 4
  5685.     and    cx,3            ; compute bank from 2 lsb of line num
  5686.     jcxz    pseth2            ; z means it is in bank 0 (0b000h)
  5687. pseth1:    add    di,2000h        ; add offset for each bank
  5688.     loop    pseth1            ; do cx times
  5689. pseth2:    pop    cx
  5690.     pop    ax
  5691.     ret
  5692. psetuph    endp
  5693.  
  5694. pincyh    proc    near            ; HGA inc y, step offset of line
  5695.     cmp    linelen,0        ; increasing y?
  5696.     jg    pinyh2            ; g = yes
  5697.     cmp    di,2000h        ; in lowest for four banks?
  5698.     ja    pinyh1            ; a = no
  5699.     add    di,linelen        ; yes, add a line
  5700. pinyh1:    add    di,6000h        ; move back by adding a lot
  5701.     and    di,7fffh        ; roll over address
  5702.     ret
  5703. pinyh2:    cmp    di,6000h        ; in top most bank?
  5704.     jb    pinyh4            ; b = no
  5705.     add    di,linelen        ; yes, first add a line
  5706. pinyh4:    add    di,2000h        ; switch to next bank
  5707.     and    di,7fffh        ; roll over address
  5708.     ret
  5709. pincyh    endp
  5710.  
  5711. ;;;;;;; AT&T-Olivetti, Toshiba, VAXmate Graphics Adapter plot support routines
  5712. ; The graphics memory mapping in 640 by 400 mode is 8 dots per byte,
  5713. ; left most dot in the high bit, 80 bytes per scan line, scan line segments
  5714. ; sequence as 0b800h, 0ba00h, 0bc00h, 0be00h for lines 0-3 and repeat 80 bytes
  5715. ; higher for the rest. Use Hercules line incrementing (inc y) and CGA dot
  5716. ; writing. This is a monographic display.
  5717. psetupo    proc    near            ; setup for plotting
  5718.     push    ax
  5719.     push    cx
  5720.     mov    linelen,80        ; for y going down screen by incy
  5721.     mov    ax,segscn        ; base segment of display memory
  5722.     mov    es,ax
  5723.     mov    cx,di            ; save copy of di, start y line
  5724.                     ; compute starting point in regen buff
  5725.     shr    di,1            ; quarter the lines in each bank
  5726.     shr    di,1
  5727.     mov    ax,80
  5728.     mul    di
  5729.     mov    di,ax            ; di = di * 80 / 4
  5730.     and    cx,3            ; compute bank from 2 lsb of line num
  5731.     jcxz    pseto2            ; z means it is in bank 0 (0b800h)
  5732. pseto1:    add    di,2000h        ; add offset for each bank
  5733.     loop    pseto1            ; do cx times
  5734. pseto2:    pop    cx
  5735.     pop    ax
  5736.     ret
  5737. psetupo    endp
  5738.  
  5739. ;;;;;;;; Monochrome, simulate dots with text char
  5740. psetupm    proc    near
  5741.     mov    linelen,1        ; 80 characters but one line
  5742.     ret
  5743. psetupm    endp
  5744.  
  5745. pltmon    proc    near            ; Monochrome dot plot
  5746.     mov    x_coord,si        ; put dot at row=di, col=si, PC Coord
  5747.     mov    y_coord,di
  5748.     push    ax
  5749.     mov    al,'+'-' '        ; our dot character
  5750.     call    mputc            ; display text char
  5751.     pop    ax
  5752.     ret
  5753. pltmon    endp
  5754.  
  5755. ; Plot bit pattern in fill as 8 horizontal pixels, starting at x,y (si,di)
  5756. ; and continuing across the line for cx pixels. Destroys CX.
  5757. bpltmon    proc    near        ; Mono plot(x,y). x is in si, y is in di
  5758.     jmp    pltmon        ; a dummy for the present
  5759. bpltmon    endp
  5760.  
  5761. pincym    proc    near            ; Monochrome inc y
  5762.     add    di,linelen        ; includes sign
  5763.     ret
  5764. pincym    endp
  5765.  
  5766. ; GPUTC - a routine to send text characters from font to true graphics boards
  5767. ; such as EGA, Hercules or CGA. Char is in al. Drawing routine ptr is gcplot.
  5768. gputc    proc    near
  5769.     push    bx            ; first save some registers
  5770.     push    cx
  5771.     push    es
  5772.     push    di
  5773.      mov    bl,al            ; now BL has char to be displayed
  5774.     xor    bh,bh
  5775.                     ; set board mode
  5776.     mov    di,y_coord        ; get current y coord (char bottom)
  5777.     inc    di
  5778.     sub    di,charhgt        ; start charlines-1 lines higher
  5779.     jnc    gputc3            ; nc = ok
  5780.     mov    di,charhgt
  5781.     dec    di
  5782.     mov    y_coord,di        ; reset scan line indicator
  5783.     xor    di,di            ; move up to first line
  5784. gputc3:    call    psetup    ; enter with di=line number, sets es:di to start of
  5785.             ; line in regen buffer and sets byte-wide plot mode
  5786.     mov    si,x_coord        ; si has x-axis in PC screen coord
  5787.     mov    cx,charhgt        ; bytes (scan lines) to transfer
  5788.     call    gcplot            ; call character plot routine
  5789.     call    incx            ; move to next char position
  5790.     pop    di
  5791.     pop    es
  5792.     pop    cx
  5793.     pop    bx
  5794.     ret
  5795. gputc    endp
  5796.  
  5797. putctrl    proc    near            ; CONTROL CHARS = cursor movement
  5798.     cmp    al,FF            ; formfeed?
  5799.      jne    putct0            ; ne = no
  5800.     jmp    TEKCLS            ; FF clears the screen
  5801.  
  5802. putct0:    cmp    al,BS            ; BS? sends (logical) cursor back one
  5803.     jne    putct2            ; ne = no, try next
  5804.     mov    ax,charwidth        ; char width
  5805.     sub    x_coord,ax        ; delete charwidth dots (move left)
  5806.     jnc    putct1            ; nc = ok
  5807.     mov    x_coord,0        ; limit to left margin
  5808. putct1:    cmp    bscontrol,0        ; non-destructive backspace?
  5809.     je    putctx            ; e = yes
  5810.     push    x_coord            ; destructive backspace
  5811.     mov    al,' '            ; a space to be written
  5812.     call    gputc            ; write it
  5813.     pop    x_coord            ; restore cursor
  5814.     ret
  5815.  
  5816. putct2:    cmp    al,TAB            ; tabs move forward one char position
  5817.     jne    putct4            ; ne = not a tab
  5818. ;;;    OR    X_COORD,7*8
  5819.     jmp    incx            ; let incx move cursor right one col
  5820.  
  5821. putct4:    cmp    al,CR            ; <CR> means go to beginning of line
  5822.     jne    putct5
  5823.     mov    x_coord,0        ; zero the x coordinate
  5824.     ret
  5825.  
  5826. putct5:    cmp    al,LF            ; <LF> means go down 8 pixels (1 line)
  5827.     jne    putct7            ; ne = not LF
  5828.     mov    ax,charhgt
  5829.     add    y_coord,ax        ; border managed by outscrn and incx
  5830.     ret
  5831.  
  5832. putct7:    cmp    al,VT            ; <VT> move up screen 1 line (8 pixels)
  5833.     jne    putctx
  5834.     mov    ax,charhgt        ; character height
  5835.     sub    y_coord,ax        ; subtract one line (charhgt pixels)
  5836.     jnc    putctx            ; nc = space left
  5837.     mov    y_coord,ax        ; else set to top of screen
  5838. putctx:    ret
  5839. putctrl    endp
  5840.  
  5841. mputc    proc    near            ; MONO put char in AL via Bios
  5842.     push    bx            ; updates x_coord,y_coord with
  5843.     push    cx            ; new cursor position
  5844.     push    dx
  5845.     xor    ah,ah            ; marker for cursor setting not needed
  5846.  
  5847. mputc1:    push    ax            ; save char and marker
  5848.     mov    cl,3            ; char cell is 8 x 8 dots
  5849.     mov    ax,x_coord        ; get resulting cursor PC positions
  5850.     shr    ax,cl
  5851.     mov    dl,al            ; column
  5852.     mov    ax,y_coord
  5853.     inc    ax
  5854.     sub    ax,charhgt        ; minus (charhgt-1) dots
  5855.     jnc    mputc2            ; nc = non-negative
  5856.     mov    ax,charhgt        ; else start at the top
  5857.     inc    ax
  5858.     mov    y_coord,ax        ; here too
  5859. mputc2:    shr    ax,cl
  5860.     mov    dh,al            ; row
  5861.     mov    ah,2            ; set cursor to x_coord,y_coord
  5862.     xor    bh,bh            ; page 0
  5863.     int    screen
  5864.     pop    ax
  5865.     or    ah,ah            ; write a char in al?
  5866.     jnz    mputcx            ; nz = no
  5867.     mov    ah,09h            ; write char at cursor postion
  5868.     mov    cx,1            ; just one char
  5869.     xor    bh,bh            ; page 0
  5870.     mov    bl,gfcol        ; foreground coloring
  5871.     int    screen
  5872.     inc    dl            ; next column
  5873.     mov    ah,2            ; set real cursor ahead of last char
  5874.     int    screen
  5875.     call    incx            ; move logical cursor
  5876. mputcx:    pop    dx
  5877.     pop    cx
  5878.     pop    bx
  5879.     ret
  5880. mputc    endp
  5881.  
  5882. incx    proc    near            ; move the logical cursor right
  5883.     mov    ax,xmax
  5884.     add    ax,8
  5885.     sub    ax,charwidth        ; last column+1
  5886.     cmp    ax,x_coord        ; beyond right most column?
  5887.     jae    incx1            ; ae = no
  5888.     mov    x_coord,ax        ; set up for wrap
  5889.     ret
  5890. incx1:    mov    ax,charwidth
  5891.     add    x_coord,ax        ; shift the (logical) cursor right
  5892.     ret                ;  one character cell
  5893. incx    endp
  5894.  
  5895. ; Character plot routine. Enter with BL holding char code
  5896. ; cx = number of bytes in char font, es:di = screen memory. Worker for gputc.
  5897. ; ccode: pixbak=plot in backgrd colors, pixfor=foregrd, pixxor=xor with screen
  5898. gcplot    proc    near
  5899.     mov    al,ccode        ; save original ccode and fill pattern
  5900.     mov    ah,fill
  5901.     push    ax
  5902.  
  5903.     push    cx
  5904.     push    ds
  5905.     push    es
  5906.     push    si
  5907.     push    di
  5908.     mov    di,seg dotbuf        ; destination buffer for font dots
  5909.     mov    es,di
  5910.     mov    di,offset dotbuf
  5911.     xor    bh,bh
  5912.     test    bl,80h            ; high bit set?
  5913.     jz    gcplot1            ; z = no
  5914.     lds    si,fontrptr        ; use GRight font set
  5915.     and    bl,not 80h        ; strip high bit now
  5916.     jmp    short gcplot2
  5917. gcplot1:lds    si,fontlptr        ; use GLeft font set
  5918. gcplot2:mov    ax,cx            ; char height (bytes per char)
  5919.     mul    bl            ; bytes into table for char in bl
  5920.     add    si,ax            ; offset into font by char
  5921.     cld
  5922.     rep    movsb            ; copy font dots to dotbuf
  5923.     pop    di
  5924.     pop    si
  5925.     pop    es
  5926.     pop    ds
  5927.     pop    cx
  5928.     xor    bx,bx            ; index into dotbuf
  5929. gcplot3:push    bx
  5930.     push    cx
  5931.     mov    al,dotbuf[bx]        ; get 8 bits from font
  5932.     mov    cx,si            ; x-axis in PC screen coordinates
  5933.     and    cl,0111b        ; bit in byte across the screen
  5934.     ror    al,cl            ; rotate pattern for gfplot filling
  5935.     mov    cx,charwidth        ; do charwidth bits on the line
  5936.     mov    fill,al            ; use "fill" as fill pattern
  5937.     call    gfplot            ; fill a scan line for cx bits
  5938.     call    pincy            ; next scan line (linelen is preset)
  5939.     pop    cx
  5940.     pop    bx
  5941.     inc    bx            ; next byte of char pattern
  5942.     loop    gcplot3
  5943.     pop    ax
  5944.     mov    ccode,al        ; recover variables
  5945.     mov    fill,ah
  5946.     ret
  5947. gcplot    endp
  5948.  
  5949. ; routines to manipulate ega graphics controller and mode register
  5950. ; command code in al, value in ah - destroys al and dx
  5951.      
  5952. ega_gc    proc    near            ; ega graphics controller
  5953.     mov    dx,3ceh
  5954.     out    dx,al            ; output command code
  5955.     inc    dx            ; dx is now data port
  5956.     mov    al,ah            ; get value to al
  5957.     out    dx,al            ; output value
  5958.     ret
  5959. ega_gc    endp
  5960. ega_md    proc    near            ; ega mode controller
  5961.     mov    dx,3c4h
  5962.     out    dx,al            ; output command code
  5963.     inc    dx            ; dx is now data port
  5964.     mov    al,ah            ; get value to al
  5965.     out    dx,al            ; output value
  5966.     ret
  5967. ega_md endp
  5968.      
  5969. ; Plot eight pixels using an EGA board
  5970. ; Enter with ES:[DI] pointing to screen address of byte,
  5971. ; bh has pattern of bits to be set, bl has attributes:
  5972. ;  pixbak = draw in background color, pixfor = draw in foreground color,
  5973. ;  pixor = OR with foreground color, pixxor = XOR with foreground color.
  5974. ; registers preserved
  5975. ; Note: this function operates on 8 pixels. One bits in bh select pixels to
  5976. ; be changed, bl determines which color planes will be affected for every
  5977. ; selected pixel.
  5978. ega_plt proc    near
  5979.     push    ax
  5980.     push    dx
  5981.     mov    dx,3ceh            ; (ega_gc) unprotect the bit positions
  5982.     mov    al,8            ; command to set bit mask register
  5983.     out    dx,al            ; output command code
  5984.     inc    dx            ; dx is now data port
  5985.     mov    al,bh            ; get pixels to be modified (1's)
  5986.     out    dx,al            ; output value (end of ega_gc)
  5987.     pop    dx
  5988.  
  5989.     mov    ah,gfcol        ; foreground color bit planes
  5990. ega1:    test    bl,pixfor+pixor        ; write foreground or OR?
  5991.     jnz    ega3            ; nz = yes
  5992.     mov    ah,gbcol        ; background color bit planes
  5993.     test    bl,pixbak        ; write in background coloring?
  5994.     jnz    ega3            ; nz = yes
  5995.     mov    ah,0fh            ; xor, touch each bit plane
  5996. ega3:    mov    al,es:[di]        ; latch byte
  5997.     mov    es:[di],ah        ; merge with untouched bits
  5998.     pop    ax
  5999.     ret
  6000. ega_plt endp
  6001.  
  6002. ; Presence test for Wyse-700: info in B000h and B800h are supposed to be equal
  6003. chkwyse    proc    near
  6004.     push    es
  6005.     push    ds
  6006.     mov    ax,0b800h        ; CGA segment
  6007.     mov    es,ax
  6008.     mov    ax,0b000h        ; Mono segment
  6009.     mov    ds,ax
  6010.     mov    ch,byte ptr es:[0]    ; CGA seg
  6011.     mov    cl,byte ptr ds:[0]    ; Mono seg
  6012.     push    cx            ; save original contents
  6013.     mov    byte ptr ds:[0],ch    ; copy CGA to Mono
  6014.     cmp    byte ptr ds:[0],ch    ; if different then not Wyse
  6015.     jne    chkwys1            ; ne = not Wyse
  6016.     not    byte ptr es:[0]        ; change CGA contents
  6017.     not    ch            ; and original pattern
  6018.     cmp    ch,byte ptr ds:[0]    ; if different then not Wyse
  6019.     jne    chkwys1            ; ne = not Wyse
  6020.     pop    cx
  6021.     mov    byte ptr es:[0],ch    ; restore CGA
  6022.     mov    byte ptr ds:[0],cl    ; restore Mono
  6023.     pop    ds
  6024.     pop    es
  6025.     clc
  6026.     ret
  6027.  
  6028. chkwys1:pop    cx
  6029.     mov    byte ptr es:[0],ch    ; restore CGA
  6030.     mov    byte ptr ds:[0],cl    ; restore Mono
  6031.     pop    ds
  6032.     pop    es
  6033.     stc
  6034.     ret
  6035. chkwyse    endp
  6036. ;
  6037. ; routine to set Wyse-700 board to graphics mode - 1280 * 800 & cls
  6038. ;
  6039. WYGRAF    PROC    NEAR
  6040.     push    ax
  6041.     push    bx            ; save used registers
  6042.     push    cx
  6043.     push    dx
  6044.     push    di
  6045.     xor    al,al
  6046.     mov    dx,wystoff        ; map video memory offset to zero
  6047.     out    dx,al            ;
  6048.     mov    dx,wystseg        ; map video memory segment to zero
  6049.     out    dx,al            ;
  6050.     mov    ax,segwyse        ; set es to Wyse start segment
  6051.     mov    es,ax            ;
  6052.     mov    al,wybeven        ; graph mode - even bank
  6053.     mov    dx,wymode        ; Wyse mode control register
  6054.     out    dx,al            ; select even bank
  6055.     cld
  6056.     xor    ax,ax            ; zero ax
  6057.     xor    di,di            ; start from zero
  6058.     mov    cx,0ffffh        ; clear 10000h bytes, whole even bank
  6059.     rep    stosb            ; store blanking char in whole screen
  6060.     mov    al,wybodd        ; graph mode - odd bank
  6061.     mov    dx,wymode        ; select it
  6062.     out    dx,al            ;
  6063.     xor    ax,ax            ; zero ax
  6064.     xor    di,di            ;
  6065.     mov    cx,0ffffh        ; clear 10000h bytes, whole odd bank
  6066.     rep    stosb            ; store blanking char in whole screen
  6067.     mov    bnkchan, 0        ; assume bank 0
  6068.     pop    di            ; restore regs
  6069.     pop    dx
  6070.     pop    cx
  6071.     pop    bx
  6072.     pop    ax
  6073.     ret
  6074. WYGRAF    ENDP
  6075.  
  6076. ; routine to set Hercules card to graphics mode - both pages are enabled
  6077.      
  6078. HGRAF    PROC    NEAR
  6079.     push    ax
  6080.     push    bx            ; save used registers
  6081.     push    cx
  6082.     push    si
  6083.     mov    al,grph            ; graph mode
  6084.     lea    si,gtable        ;  requires graphics table
  6085.     xor    bx,bx
  6086.     mov    cx,4000h        ; clear 4000h words
  6087.     test    gbcol,7            ; any (light) background color bits?
  6088.     jz    hgraf1            ; z = no, we are ok
  6089.     dec    bx            ; light background, set all the bits
  6090. hgraf1:    call    setmd            ; and set the mode
  6091.     pop    si
  6092.     pop    cx
  6093.     pop    bx
  6094.     pop    ax
  6095.     ret
  6096. HGRAF    ENDP
  6097.      
  6098. ; set Hercules card to text mode
  6099. HTEXT    PROC    NEAR
  6100.     push    ax
  6101.     push    bx
  6102.     push    cx
  6103.     push    si
  6104.     mov    al,text            ; text mode
  6105.     lea    si,ttable        ; requires text table
  6106.     mov    bx,0720h        ; blank value (space, white on black)
  6107.     mov    cx,2000            ; whole screen to clear (80*25)
  6108.     call    setmd            ; set the mode
  6109.     pop    si
  6110.     pop    cx
  6111.     pop    bx
  6112.     pop    ax
  6113.     ret
  6114. HTEXT    ENDP
  6115.      
  6116. ; Hercules mode set - called from HTEXT and HGRAF
  6117. SETMD    PROC    NEAR
  6118.     push    dx
  6119.     push    ax
  6120.     mov    dx,config        ; configuration port
  6121.     mov    al,genable        ; allow graphics mode to be set
  6122.     out    dx,al
  6123.     pop    ax
  6124.     push    ax
  6125.     push    cx            ; save count
  6126.     mov    dx,cntrl        ; control port
  6127.     out    dx,al            ; set to text or graphics
  6128.     mov    dx,index        ; send 12 bytes from table to 6845
  6129.     mov    cx,12            ; number of registers to load
  6130.     xor    ah,ah            ; start with register 0 of 6845
  6131.     cld
  6132. setmd1:    jmp    $+2            ; small pause for hardware
  6133.     mov    al,ah            ; ah is counter
  6134.     out    dx,al            ; set register
  6135.     inc    dx            ; point to data port
  6136.     lodsb                ; get next byte in table
  6137.     jmp    $+2            ; small pause for hardware
  6138.     out    dx,al            ; and send to 6845
  6139.     inc    ah            ; next register
  6140.     dec    dx            ; point to register port
  6141.     loop    setmd1            ; and continue 'til cx=0
  6142.     pop    cx            ; recover count
  6143.     cld
  6144.     push    di
  6145.     push    es
  6146.     mov    ax,segscn        ; start of screen
  6147.     mov    es,ax
  6148.     xor    di,di
  6149.     mov    ax,bx            ; get blanking character
  6150.     rep    stosw            ; store blanking char in whole screen
  6151.     pop    es
  6152.     pop    di
  6153.     mov    dx,cntrl        ; now to re-enable screen
  6154.     pop    ax            ; get mode
  6155.     or    al,scrn_on        ; enable screen
  6156.     out    dx,al
  6157.     pop    dx
  6158.     ret
  6159. SETMD    ENDP
  6160.      
  6161. teksave    proc    near        ; saves graphics screen from page 0 to page 1
  6162.     mov    temp,1        ; say saving from video to storage
  6163.     push    si
  6164.     push    di
  6165.     cmp    gpage,0        ; only graphics page 0 on display board?
  6166.     je    teksavx        ; e = yes, no saving possible here
  6167.     mov    si,segscn    ; segment (!) of current screen
  6168.     cmp    graph_mode,ega
  6169.     je    teksav1
  6170.     cmp    graph_mode,monoega
  6171.     je    teksav1
  6172.     cmp    graph_mode,colorega
  6173.     je    teksav1
  6174.     cmp    graph_mode,hercules
  6175.     je    teksav2
  6176.     jmp    short teksavx    ; else nothing
  6177. teksav1:mov    di,segega+800h    ; EGA page 1 screen segment
  6178.     call    egasr        ; call common save/restore code
  6179.     jmp    short teksavx
  6180. teksav2:mov    di,seghga+800h    ; Hercules page 1 screen segment
  6181.     call    hgasr        ; call common save/restore code
  6182. teksavx:pop    di
  6183.     pop    si
  6184.     ret
  6185. teksave    endp
  6186.  
  6187. tekrest    proc    near        ; restores graphics screen in page 1 to page 0
  6188.     mov    temp,-1        ; say restoring storage to video
  6189.     push    si
  6190.     push    di
  6191.     cmp    gpage,0        ; only graphics page 0 on display board?
  6192.      jne    tekres0        ; ne = no, more so work to do here
  6193.     call    tekcls1        ;  else clear the screen to color it
  6194.     jmp    short tekresx    ;  and exit
  6195. tekres0:mov    di,segscn    ; segment (!) of new graphics screen
  6196.     cmp    graph_mode,ega
  6197.     je    tekres1
  6198.     cmp    graph_mode,monoega
  6199.     je    tekres1
  6200.     cmp    graph_mode,colorega
  6201.     je    tekres1
  6202.     cmp    graph_mode,hercules
  6203.     je    tekres2
  6204.     jmp    short tekresx    ; else nothing
  6205. tekres1:mov    si,segega+800h    ; segment of EGA page 1
  6206.     call    egasr        ; call common save/restore code
  6207.     jmp    short tekresx
  6208. tekres2:mov    si,seghga+800h    ; segment of Hercules page 1
  6209.     call    hgasr        ; call common save/restore code
  6210. tekresx:pop    di
  6211.     pop    si
  6212.     ret
  6213. tekrest    endp
  6214.  
  6215. egasr    proc    near        ; common code for Tek ega save/restore ops
  6216.     push    ax
  6217.     push    cx
  6218.     push    dx
  6219.     mov    ax,0f00h    ; enable 4 plane set/resets
  6220.     call    ega_gc        ; set controller
  6221.     mov    ax,0f01h    ; enable Set/Reset register
  6222.     call    ega_gc
  6223.     mov    ax,0f02h    ; set color compare register for 4 planes
  6224.     call    ega_gc
  6225.     mov    ax,0905h    ; set mode reg: write latches, read mode
  6226.     call    ega_gc
  6227.     mov    ax,0ff02h    ; enable all planes
  6228.     call    ega_md
  6229.     mov    cx,ybot        ; last scan line
  6230.     inc    cx        ; number of scan lines
  6231.     mov    ax,80        ; bytes per scan line
  6232.     mul    cx
  6233.     mov    cx,ax
  6234.     push    es        ; save es
  6235.     push    ds        ; save ds
  6236.     call    gsems        ; try to store to/from expanded memory
  6237.     jnc    egasr1        ; nc = success
  6238.     mov    es,di        ; destination, set es to video memory
  6239.     mov    ds,si        ; source, set ds to video memory
  6240.     xor    si,si        ; clear offset fields
  6241.     xor    di,di
  6242.     cld            ; byte moves for ega adaptor
  6243.     rep    movsb        ; copy from page (ds:si) to page (es:di)
  6244. egasr1:    pop    ds        ; recover ds
  6245.     pop    es        ; and other registers
  6246.     call    gcreset        ; reset controller
  6247.     pop    dx
  6248.     pop    cx
  6249.     pop    ax
  6250.     ret
  6251. egasr    endp
  6252.  
  6253. ; Transfer video to/from EMS memory for EGA/VGA boards
  6254. ; SI is source seg, DI is dest seg, CX is pixel count, temp > 0 for saving
  6255. ; to ems, temp < 0 for saving to video memory.
  6256. ; Return carry set if failure, else carry clear
  6257. gsems    proc    near
  6258.     cmp    emsrbhandle,0        ; have rollback in expanded memory?
  6259.     jg    gsems1            ; g = yes, else use video memory
  6260.     stc
  6261.     ret
  6262. gsems1:    cmp    cx,emsbytes        ; same as last time used?
  6263.     je    gsems4            ; e = yes, use present allocation
  6264.     mov    ah,emsrelease        ; release handle and memory
  6265.     mov    dx,emsgshandle        ; handle
  6266.     or    dx,dx            ; is handle valid (>= 0)?
  6267.     jl    gsems1a            ; l = no
  6268.     int    emsint            ; ems interrupt
  6269. gsems1a:mov    emsgshandle,-1
  6270.     cmp    temp,0            ; is this a restore operation?
  6271.     jl    gsems1b            ; l = yes, absent ems screen
  6272.     mov    emsbytes,cx        ; remember qty pixel bytes
  6273.     mov    ax,cx
  6274.     add    ax,1000h-1        ; one ems page size/4 - 1 byte
  6275.     mov    cl,12            ; bits to slide
  6276.     shr    ax,cl            ; divide by 4000h bytes per ems page
  6277.     mov    cx,ax            ; save desired page count
  6278.     mov    ah,emsgetnpgs        ; get number 16KB pages free
  6279.     int    emsint            ; to bx
  6280.     cmp    bx,cx            ; ((640x480/8)*4)=153,6400B = 10 pages
  6281.     jae    gsems2            ; ae = have enough space
  6282. gsems1b:mov    emsbytes,0
  6283.     call    gcreset            ; reset controller
  6284.     call    tekcls            ; clear screen
  6285.     clc                ; fake success with fresh screen
  6286.     ret
  6287. gsems2:    mov    bx,cx            ; number of pages wanted
  6288.     mov    ah,emsalloc        ; allocate bx pages
  6289.     int    emsint
  6290.     or    ah,ah            ; successful?
  6291.     jz    gsems3            ; z = yes
  6292.     mov    emsbytes,0
  6293.     stc
  6294.     ret
  6295. gsems3:    mov    emsgshandle,dx        ; returned handle
  6296.     mov    ah,emsgetseg        ; get segment of page frame
  6297.     int    emsint            ;  to bx
  6298.     mov    emsseg,bx        ; save here
  6299.     mov    ah,emsgetver        ; get EMS version number
  6300.     int    emsint            ; to al (high=major, low=minor)
  6301.     cmp    al,40h            ; at least LIM 4.0?
  6302.     jb    gsems4            ; b = no, so no name for our area
  6303.     push    si
  6304.     push    di
  6305.     mov    si,offset emsgsname    ; point to name for graphics area
  6306.     mov    di,offset emsgsname+6    ; add digits
  6307.     mov    ax,emsgshandle
  6308.     call    dec2di            ; write to handle name
  6309.     mov    byte ptr [di],' '    ; must end in a space
  6310.     mov    dx,emsgshandle
  6311.     mov    ax,emssetname        ; set name for handle from ds:si
  6312.     int    emsint
  6313.     pop    di
  6314.     pop    si
  6315.  
  6316. gsems4:    call    gcreset            ; reset controller
  6317.     mov     ax,0005h         ; read mode 0, write mode 0
  6318.     call    ega_gc
  6319.     cmp    temp,0            ; get direction of saving/restoring
  6320.     jl    gsems7            ; l = restore (storage to video)
  6321.                     ; Save (video to ems)
  6322.     mov    ax,emsseg        ; get ems segment
  6323.     mov    es,ax            ; set destination
  6324.     mov    ds,si            ; save (video to storage)
  6325.     xor    bx,bx            ; page 0
  6326.     call    getpage            ; get EMS page bx
  6327.     xor    di,di            ; start of page frame
  6328.     mov    cx,4            ; plane loop
  6329.     
  6330. gsems4a:push    cx            ; save plane counter
  6331.     call    selplane        ; select plane in cl (1..4)
  6332.     push    ds
  6333.     mov    cx,seg emsbytes
  6334.     mov    ds,cx
  6335.     mov    cx,emsbytes        ; pixel counter
  6336.     pop    ds
  6337.     xor    si,si            ; start of video buffer
  6338.  
  6339. gsems5:    mov    ax,cx            ; save total byte count
  6340.     cmp    cx,dx            ; larger than one page?
  6341.     jbe    gsems6            ; be = no
  6342.     mov    cx,dx            ; one page
  6343. gsems6:    sub    ax,cx            ; ax is bytes remaining to do
  6344.     sub    dx,cx            ; bytes to be used in EMS page
  6345.     cld
  6346.     rep    movsb            ; video to ems page
  6347.     mov    cx,ax            ; pixels to do
  6348.     or    dx,dx            ; EMS bytes left in page?
  6349.     jnz    gsems6a            ; nz = yes
  6350.     inc    bx            ; next ems page
  6351.     call    getpage
  6352.     xor    di,di            ; start of page
  6353. gsems6a:inc    cx            ; inc for loop dec below
  6354.     loop    gsems5            ; do all pixels
  6355.  
  6356.     pop    cx            ; recover plane counter
  6357.     loop    gsems4a            ; do next plane
  6358.     clc
  6359.     ret
  6360.                     ; copy from ems to video
  6361. gsems7:    mov    es,di            ; destination segment (video)
  6362.     mov    ax,emsseg        ; get ems segment
  6363.     mov    ds,ax            ; set source
  6364.     xor    bx,bx            ; page
  6365.     call    getpage            ; get EMS page bx
  6366.     xor    si,si            ; start of frame buffer
  6367.     mov    cx,4            ; plane counter
  6368.  
  6369. gsems7a:push    cx            ; save plane counter
  6370.     call    selplane        ; select plane in cl (1..4)
  6371.     push    ds
  6372.     mov    cx,seg emsbytes
  6373.     mov    ds,cx
  6374.     mov    cx,emsbytes        ; pixel counter
  6375.     pop    ds
  6376.     xor    di,di            ; start of video buffer
  6377.  
  6378. gsems8:    mov    ax,cx            ; save total byte count
  6379.     cmp    cx,dx            ; larger than this page can hold?
  6380.     jbe    gsems9            ; be = no
  6381.     mov    cx,dx            ; use value available
  6382. gsems9:    sub    ax,cx            ; ax is bytes remaining to do
  6383.     sub    dx,cx            ; bytes to be used in EMS page
  6384.     cld
  6385.     rep    movsb            ; EMS page to video
  6386.     mov    cx,ax            ; pixels to do
  6387.     or    dx,dx            ; EMS bytes left in page?
  6388.     jnz    gsems9a            ; nz = yes
  6389.     inc    bx            ; next ems page
  6390.     call    getpage
  6391.     xor    si,si            ; start of page
  6392. gsems9a:inc    cx            ; inc for loop dec below
  6393.     loop    gsems8            ; do all pixels
  6394.  
  6395.     pop    cx            ; recover plane counter
  6396.     loop    gsems7a            ; do next plane
  6397.     clc
  6398.     ret
  6399. gsems    endp
  6400.  
  6401. ; Get EMS logical page BX into EMS physical page 0
  6402. ; Returns in DX the number of free bytes (16KB). Modifies AX
  6403. getpage    proc    near
  6404.     push    ds
  6405.     mov    ax,seg emsgshandle
  6406.     mov    ds,ax
  6407.     mov    ah,emsmapmem        ; map logical page in bx
  6408.     xor    al,al            ;  to physical page zero
  6409.     mov    dx,emsgshandle        ; our ems handle
  6410.     int    emsint
  6411.     mov    dx,4000h        ; bytes in this page
  6412.     pop    ds
  6413.     ret
  6414. getpage    endp
  6415.  
  6416. ; Select EGA video plane in cl (1..4) for r/w
  6417. selplane proc    near
  6418.     push    cx
  6419.     push    dx
  6420.     dec    cl            ; count planes as 0..3
  6421.     and    cl,3            ; range bound (planes 0..3)
  6422.     mov    ah,cl            ; binary value for read map select
  6423.     mov    al,4            ; read map select register
  6424.     call    ega_gc            ; set read map plane
  6425.     mov    ah,1            ; convert to plane number
  6426.     shl    ah,cl            ; convert plane number to bit position
  6427.     mov    al,2            ; map mask register
  6428.     call    ega_md            ; select plane for writing
  6429.     pop    dx
  6430.     pop    cx
  6431.     ret
  6432. selplane endp
  6433.  
  6434. ; Reset EGA board prior to video<->ems copying
  6435. gcreset proc    near
  6436.     push    ax
  6437.     push    dx
  6438.     mov    ax,0ff08h    ; bit mask reg to all 8 bits
  6439.     call    ega_gc
  6440.     mov    ax,0003h    ; direct write
  6441.     call    ega_gc            
  6442.     mov    ax,0004h    ; read map select to map 0
  6443.     call    ega_gc
  6444.     mov    ax,0000h    ; set/reset latches
  6445.     call    ega_gc
  6446.     mov    ax,0001h    ; set/reset enable, disable
  6447.     call    ega_gc
  6448.     mov    ax,0f02h    ; enable all planes for write
  6449.     call    ega_md
  6450.     pop    dx
  6451.     pop    ax
  6452.     ret
  6453. gcreset endp
  6454.  
  6455. hgasr    proc    near        ; Hercules save restore screen
  6456.     push    cx
  6457.     mov    cx,4000h    ; number of words to move
  6458.     push    es        ; save es
  6459.     push    ds        ; save ds
  6460.     mov    es,di        ; destination, set es to video memory
  6461.     mov    ds,si        ; source, set ds to video memory
  6462.     xor    si,si        ; clear offset fields
  6463.     xor    di,di
  6464.     cld
  6465.     rep    movsw        ; copy from page [si] to page [di]
  6466.     pop    ds        ; recover ds
  6467.     pop    es        ; and other registers
  6468.     pop    cx
  6469.     ret
  6470. hgasr    endp
  6471.  
  6472. dump    proc    FAR            ; Write screen as TIFF v5.0 file
  6473.     push    ax
  6474.     push    bx
  6475.     push    cx
  6476.     push    dx
  6477.     push    si
  6478.     push    di
  6479.     call    remcursor        ; remove the cursor from the screen
  6480.     mov    si,offset dumpname    ; name of dump file
  6481.     mov    di,offset rdbuf        ; destination
  6482.     push    es
  6483.     push    ds
  6484.     pop    es
  6485.     mov    cx,dumplen        ; length of dump name
  6486.     cld
  6487.     rep    movsb            ; copy it, asciiz
  6488.     pop    es
  6489.     mov    ax,offset rdbuf        ; address to ax for unique
  6490.     call    tunique            ; get unique name into ax
  6491.     mov    dx,ax            ; ds:dx is asciiz filename
  6492.     xor    cx,cx            ; normal attributes
  6493.     mov    ah,creat2        ; create the file
  6494.     int    dos
  6495.     jc    dmp3            ; c = failure
  6496. dmp1:    mov    dhandle,ax        ; file handle
  6497.     call    dmpdate            ; do time stamp
  6498.     cmp    plotptr,offset pltcga    ; using CGA style graphics?
  6499.     jne    dmp2            ; ne = no
  6500.     call    cgadmp            ; do CGA style dump routine
  6501.     jmp    short dmp3
  6502. dmp2:    call    egadmp
  6503. dmp3:    jnc    dmp5            ; nc = successful dump
  6504.     mov    cx,4
  6505. dmp4:    push    cx
  6506.     call    tekbeep            ; make a noise
  6507.     mov    ax,250            ; wait 250ms
  6508.     call    tekwait
  6509.     pop    cx
  6510.     loop    dmp4            ; four beeps
  6511. dmp5:    mov    cursorst,1        ; pretend cursor was on
  6512.     call    remcursor        ; restore the cursor to the screen
  6513.     mov    cursorst,1        ; say it is on
  6514.     pop    di
  6515.     pop    si
  6516.     pop    dx
  6517.     pop    cx
  6518.     pop    bx
  6519.     pop    ax
  6520.     ret
  6521. dump    endp
  6522.  
  6523. ; CGA TIFF 5.0 screen-to-file dump routine
  6524. cgadmp    proc    near
  6525.     push    es            ; do the bookkeeping math first
  6526.     mov    bps.entval,1        ; bits/sample, mono
  6527.     mov    photo.entval,1        ; mono, one bit after the other
  6528.     mov    word ptr cmap.entcnt,0    ; no palette color map entries
  6529.     mov    ax,xmax            ; image width - 8 pixels
  6530.     add    ax,8            ; plus 8, for pixels per line
  6531.     mov    iwidth.entval,ax    ; store in directory
  6532.     mov    xresval,ax        ; x resolution
  6533.     mov    xresval+2,0        ; high order part
  6534.     mov    ax,ybot            ; lines per screen - 1
  6535.     inc    ax            ; lines per screen
  6536.     mov    ilength.entval,ax    ; image length, scan lines
  6537.     mov    yresval,ax        ; y resolution
  6538.     mov    yresval+2,0        ; high order part
  6539.     mov    cx,25            ; try dividing into this many strips
  6540. cgadmp5:xor    dx,dx            ; image pixels
  6541.     mov    ax,yresval        ; number of scan lines
  6542.     div    cx            ; try dividing into 25 strips,ax=quo
  6543.     or    dx,dx            ; did we get null remainder?
  6544.     loopnz    cgadmp5            ; nz = no, try again with fewer strips
  6545.     inc    cx            ; inc for dec by loop, cx = # strips
  6546.     mov    word ptr strip.entcnt,cx ; store number of strips
  6547.     mov    word ptr sbc.entcnt,cx    ; store number of strip byte counts
  6548.     mov    rps.entval,ax        ; rows per strip
  6549.     push    cx
  6550.     mov    cx,iwidth.entval    ; dots per line (row)
  6551.     shr    cx,1            ; get bytes/row
  6552.     shr    cx,1
  6553.     shr    cx,1
  6554.     mul    cx            ; rows/strip * bytes/row = bytes/strip
  6555.     pop    cx
  6556.     push    cx            ; save strip count for loop below
  6557.     push    ds            ; ax = bytes per strip
  6558.     pop    es            ; es:di to our data segment
  6559.     mov    di,offset stripbc    ; where to write strip byte counts
  6560.     cld
  6561.     rep    stosw            ; write ax as bytes/strip, cx times
  6562.     pop    cx            
  6563.     mov    dx,ax            ; bytes/strip = increment, put here
  6564.     mov    di,offset stripoff    ; where we write
  6565.     mov    ax,offset pixdata-offset header ; where first strip starts
  6566. cgadmp4:stosw                ; write strip file offset
  6567.     mov    word ptr [di],0        ; high order part
  6568.     add    di,2            ; next double word
  6569.     add    ax,dx            ; next file strip offset
  6570.     loop    cgadmp4            ; do all strip offsets
  6571.                     ; file i/o starts here
  6572.     mov    bx,dhandle        ; dump's file handle
  6573.     mov    dx,offset header    ; write TIFF header and directory
  6574.     mov    cx,tifflen        ; length of header plus directory
  6575.     mov    ah,write2
  6576.     int    dos
  6577.     jc    cgadmp2            ; c = failure
  6578.     xor    di,di            ; start at y = top
  6579.     call    psetup            ; setup cga and di
  6580.     mov    cx,ybot            ; number of scan lines-1
  6581.     inc    cx            ; number of scan lines
  6582. cgadmp1:push    cx
  6583.     mov    cx,iwidth.entval    ; dots per line (row)
  6584.     shr    cx,1            ; get bytes/row
  6585.     shr    cx,1
  6586.     shr    cx,1            ; line length, bytes
  6587.     mov    dx,di            ; offset in screen buffer
  6588.     mov    bx,dhandle        ; file handle
  6589.     push    ds
  6590.     mov    ax,segscn        ; screen seg
  6591.     mov    ds,ax
  6592.     mov    ah,write2        ; write directly from screen memory
  6593.     int    dos
  6594.     pop    ds
  6595.     jc    cgadmp2            ; c = failure
  6596.     call    pincy            ; next line down, y = y + 1
  6597.     pop    cx
  6598.     loop    cgadmp1            ; do all scan lines
  6599. cgadmp2:mov    ah,close2        ; close the file
  6600.     int    dos
  6601.     mov    dhandle,-1        ; set handle to unused
  6602.     pop    es
  6603.     ret
  6604. cgadmp    endp
  6605.  
  6606. ; EGA TIFF 5.0 screen-to-file dump routine
  6607. egadmp    proc    near
  6608.     push    es            ; do the bookkeeping math first
  6609.     mov    bps.entval,4        ; bits/sample, iRGB
  6610.     mov    photo.entval,3        ; photo interp, palette
  6611.     mov    word ptr cmap.entcnt,3*16 ; palette color map entries
  6612.     mov    ax,xmax            ; image width - 8 pixels
  6613.     add    ax,8            ; plus 8, for pixels per line
  6614.     mov    iwidth.entval,ax    ; store in directory
  6615.     mov    xresval,ax        ; x resolution
  6616.     mov    xresval+2,0        ; high order part
  6617.     mov    ax,ybot            ; lines per screen - 1
  6618.     inc    ax            ; lines per screen
  6619.     mov    ilength.entval,ax    ; image length, scan lines
  6620.     mov    yresval,ax        ; y resolution
  6621.     mov    yresval+2,0        ; high order part
  6622.     mov    cx,25            ; try dividing into this many strips
  6623. egadmp10:xor    dx,dx            ; image pixels
  6624.     mov    ax,yresval        ; number of scan lines
  6625.     div    cx            ; try dividing into 25 strips, ax=quo
  6626.     or    dx,dx            ; did we get null remainder?
  6627.     loopnz    egadmp10        ; nz = no, try again with fewer strips
  6628.     inc    cx            ; inc for dec by loop, cx = # strips
  6629.     mov    word ptr strip.entcnt,cx ; store number of strips
  6630.     mov    word ptr sbc.entcnt,cx    ; store number of strip byte counts
  6631.     mov    rps.entval,ax        ; rows per strip
  6632.     shl    ax,1
  6633.     shl    ax,1            ; times 4 bits / pixel
  6634.     push    cx
  6635.     mov    cx,iwidth.entval    ; dots per line (row)
  6636.     shr    cx,1            ; get bytes/row
  6637.     shr    cx,1
  6638.     shr    cx,1
  6639.     mul    cx            ; rows/strip * bytes/row = bytes/strip
  6640.     pop    cx
  6641.     push    cx            ; save strip count for loop below
  6642.     push    ds            ; ax = bytes per strip
  6643.     pop    es            ; es:di to our data segment
  6644.     mov    di,offset stripbc    ; where to write strip byte counts
  6645.     cld
  6646.     rep    stosw            ; write ax as bytes/strip, cx times
  6647.     pop    cx            
  6648.     mov    dx,ax            ; bytes/strip = increment, put here
  6649.     mov    di,offset stripoff    ; where we write
  6650.     mov    ax,offset pixdata-offset header ; where first strip starts
  6651.     xor    bx,bx
  6652. egadmp11:stosw                ; write strip file offset
  6653.     mov    es:[di],bx        ; high order part
  6654.     add    di,2            ; next double word
  6655.     add    ax,dx            ; next file strip offset
  6656.     adc    bx,0
  6657.     loop    egadmp11        ; do all strip offsets
  6658.                     ; screen to file i/o starts here
  6659.     mov    bx,dhandle        ; dump's file handle
  6660.     mov    dx,offset header    ; write TIFF header and directory
  6661.     mov    cx,tifflen        ; length of header plus directory
  6662.     mov    ah,write2
  6663.     int    dos
  6664.     jnc    egadmp12
  6665.     jmp    egadmp9            ; c = failure
  6666. egadmp12:
  6667.     xor    di,di            ; start at y = top
  6668.     call    psetup            ; setup adapter and es:di
  6669.     xor    di,di
  6670.     mov    bx,offset rdbuf        ; set buffer address
  6671.     mov    cx,ybot            ; number of scan lines-1
  6672.     inc    cx            ; number of scan lines
  6673. egadmp1:push    cx            ; save scan line counter
  6674.     mov    cx,iwidth.entval    ; dots per line (row)
  6675.     shr    cx,1            ; get bytes/row
  6676.     shr    cx,1
  6677.     shr    cx,1            ; 8*dots across the screen (640)
  6678. egadmp2:push    cx            ; save counter of inner loops
  6679.     mov    cx,4            ; number of planes to do
  6680.     mov    word ptr [bx],0        ; clear the four bytes for this loop
  6681.     mov    word ptr [bx+2],0
  6682. egadmp3:push    cx            ; save plane counter
  6683.     push    bx            ; don't advance buffer pointer here
  6684.     mov    dx,3ceh            ; (ega_gc)
  6685.     mov    al,4            ; command to select read map register
  6686.     out    dx,al            ; output command code
  6687.     inc    dx            ; dx is now data port
  6688.     mov    al,cl            ; do planes 3(I), then 2(R),1(G),0(B)
  6689.     dec    al            ; cx is one higher than plane
  6690.     out    dx,al            ; output value (end of ega_gc)
  6691.     mov    al,es:[di]        ; latch byte
  6692.                     ; got 8 bits from a plane
  6693.     mov    cx,4            ; do this for four output bytes
  6694. egadmp4:mov    ah,[bx]            ; eventually iRGB in each nibble
  6695.     shl    al,1            ; get left most pixel bit in plane
  6696.     jnc    egadmp5
  6697.     or    ah,8            ; set high nibble least sig bit
  6698. egadmp5:shl    al,1            ; odd numbered pixel
  6699.      rcl    ah,1            ; set low nibble least sig bit if c
  6700.     mov    [bx],ah
  6701.     inc    bx            ; next byte
  6702.     loop    egadmp4            ; do all four bytes
  6703.  
  6704.     pop    bx
  6705.     pop    cx            ; restore plane counter
  6706.     loop    egadmp3            ; do all planes
  6707.  
  6708.     inc    di            ; next screen memory address
  6709.     add    bx,4            ; just did four bytes
  6710.     cmp    bx,offset rdbuf+80    ; at end of 80 bytes?
  6711.     jb    egadmp6            ; b = no
  6712.     call    egadmpw            ; write the buffer
  6713.     mov    bx,offset rdbuf        ; reset buffer address
  6714.     jnc    egadmp6            ; nc = success
  6715.     pop    cx            ; clean stack
  6716.     pop    cx
  6717.     jmp    egadmp9            ; error
  6718.  
  6719. egadmp6:pop    cx            ; recover bytes per line counter
  6720.     loop    egadmp2            ; next group across scan line
  6721.     pop    cx            ; recover scan line counter
  6722.     loop    egadmp1            ; do next scan line
  6723.     call    egadmpw            ; flush the buffer for last scan line
  6724. egadmp9:mov    ah,close2        ; close the file
  6725.     mov    bx,dhandle
  6726.     int    dos
  6727.     mov    dhandle,-1        ; set handle to unused
  6728.     xor    di,di
  6729.     call    psetup
  6730.     pop    es
  6731.     ret
  6732.                        ; local worker
  6733. egadmpw:push    bx            ; write tempbuf from start to [bx-1]
  6734.     push    cx
  6735.     mov    dx,offset rdbuf        ; work buffer
  6736.     mov    cx,bx            ; buffer pointer to next free byte
  6737.     sub    cx,dx            ; buffer size to write
  6738.     cmp    cx,0
  6739.     jle    egadmpw1        ; le = nothing to write
  6740.     mov    bx,dhandle        ; file handle
  6741.     mov    ah,write2        ; write cx bytes from rdbuf
  6742.     int    dos
  6743.     jc    egadmpw2        ; c = error
  6744.     cmp    ax,cx            ; wrote all?
  6745.     jne    egadmpw2        ; ne = no
  6746. egadmpw1:clc                ; clc
  6747.     pop    cx
  6748.     pop    bx
  6749.     ret
  6750. egadmpw2:stc                ; carry set for failure
  6751.     pop    cx
  6752.     pop    bx
  6753.     ret
  6754. egadmp    endp
  6755.  
  6756. ; Worker. Write Kermit version and current date and time in TIFF header
  6757. dmpdate    proc    near
  6758.     mov    di,offset prog+10    ; place for version in prog field
  6759.     mov    ax,version        ; Kermit version
  6760.     call    dec2di            ; write the version
  6761.     mov    ah,getdate        ; DOS date (cx= yyyy, dh= mm, dl= dd)
  6762.     int    dos
  6763.     mov    di,offset dandt        ; where to write
  6764.     mov    ax,cx            ; get yyyy
  6765.     push    dx
  6766.     call    dec2di            ; write to buffer
  6767.     pop    dx
  6768.     mov    byte ptr [di],':'
  6769.     inc    di
  6770.     mov    al,dh            ; mm
  6771.     cmp    al,10            ; leading digit?
  6772.     jae    dmpdat1            ; ae = yes
  6773.     mov    byte ptr [di],'0'    ; make our own
  6774.     inc    di
  6775. dmpdat1:xor    ah,ah
  6776.     push    dx
  6777.     call    dec2di
  6778.     mov    byte ptr [di],':'
  6779.     pop    dx
  6780.     inc    di
  6781.     mov    al,dl            ; dd
  6782.     cmp    al,10            ; leading digit?
  6783.     jae    dmpdat2            ; ae = yes
  6784.     mov    byte ptr [di],'0'    ; make our own
  6785.     inc    di
  6786. dmpdat2:xor    ah,ah
  6787.     call    dec2di
  6788.     mov    byte ptr [di],' '
  6789.     inc    di
  6790.     mov    ah,gettim        ; DOS tod (ch=hh, cl=mm, dh=ss, dl=.s)
  6791.     int    dos
  6792.     push    dx            ; save dx
  6793.     xor    ah,ah
  6794.     mov    al,ch            ; Hours
  6795.     cmp    al,10            ; leading digit?
  6796.     jae    dmpdat3            ; ae = yes
  6797.     mov    byte ptr [di],'0'    ; make our own
  6798.     inc    di
  6799. dmpdat3:push    cx
  6800.     call    dec2di            ; write decimal asciiz to buffer
  6801.     pop    cx
  6802.     mov    byte ptr [di],':'
  6803.     inc    di
  6804.     xor    ah,ah
  6805.     mov    al,cl            ; Minutes
  6806.     cmp    al,10            ; leading digit?
  6807.     jae    dmpdat4            ; ae = yes
  6808.     mov    byte ptr [di],'0'    ; make our own
  6809.     inc    di
  6810. dmpdat4:call    dec2di            ; write decimal asciiz to buffer
  6811.     mov    byte ptr [di],':'
  6812.     inc    di
  6813.     pop    dx
  6814.     xor    ah,ah
  6815.     mov    al,dh            ; Seconds
  6816.     cmp    al,10            ; leading digit?
  6817.     jae    dmpdat5            ; ae = yes
  6818.     mov    byte ptr [di],'0'    ; make our own
  6819.     inc    di
  6820. dmpdat5:call    dec2di            ; write decimal asciiz to buffer
  6821.     inc    di
  6822.     ret
  6823. dmpdate    endp
  6824.  
  6825. ; Read 8x14 GRight font for current Code Page from DOS file EGA.CPI to 
  6826. ; array fontgright. Returns carry set if failed.
  6827. getfont proc    near
  6828.     mov    ax,offset fontfile    ; EGA.CPI filename
  6829.     call    fspath            ; search path for it
  6830.     jnc    getfont1        ; nc = found, ax has full path
  6831.     ret                ; not found, fail
  6832. getfont1:mov    dx,ax            ; point to name from spath
  6833.     mov    ah,open2        ; open file
  6834.     xor    al,al            ; 0 = open for reading
  6835.     cmp    dosnum,300h        ; at or above DOS 3?
  6836.     jb    getfont2        ; b = no, so no shared access
  6837.     or    al,40h            ; open for reading, deny none
  6838. getfont2:int    dos
  6839.     jnc    getfont3        ; nc = success
  6840.     ret                ; failure
  6841.  
  6842. getfont3:mov    temp,ax            ; file handle
  6843.     mov    bx,ax            ; handle
  6844.     mov    cx,23            ; read "head" information, 23 bytes
  6845.     mov    dx,offset stripoff    ; ds:dx = temp work buffer
  6846.     mov    ah,readf2        ; read file
  6847.     int    dos
  6848.     jnc    getfont4        ; nc = successful read
  6849. getfont3a:jmp    getfont12        ; fail
  6850.  
  6851. getfont4:cmp    byte ptr stripoff,0ffh    ; file signature
  6852.     jne    getfont3a        ; ne = not a CPI file internally
  6853.     mov    dx,word ptr stripoff[19] ; offset of word "info"
  6854.     mov    cx,word ptr stripoff[21] ; high order part
  6855.     mov    ah,lseek
  6856.     xor    al,al            ; seek from BOF
  6857.     int    dos
  6858.     mov    cx,2            ; read a word
  6859.     mov    dx,offset stripoff
  6860.     mov    ah,readf2
  6861.     int    dos
  6862.     mov    di,word ptr stripoff    ; number of Code Page entities
  6863.  
  6864. getfont6:mov    bx,temp            ; handle
  6865.     mov    cx,128            ; buffer with font info
  6866.     mov    dx,offset stripoff
  6867.     mov    ah,readf2
  6868.     int    dos
  6869.     cmp    word ptr stripoff[8],'GE' ; "EGA"?
  6870.     jne    getfont7        ; ne = no, keep looking
  6871.     mov    dx,vtcpage        ; current Code Page
  6872.     cmp    word ptr stripoff[16],dx ; Code Page ident, same?
  6873.     je    getfont8        ; e = yes
  6874. getfont7:mov    dx,word ptr stripoff[2] ; ptr to next CP entry
  6875.     mov    cx,word ptr stripoff[4] ; high order part
  6876.     mov    bx,temp            ; file handle for seeking
  6877.     mov    ah,lseek
  6878.     xor    al,al            ; seek from BOF
  6879.     int    dos
  6880.     dec    di            ; one less Code Page
  6881.     cmp    di,0            ; done all?
  6882.     jg    getfont6        ; g = no, get next header
  6883.     stc                ; failed to find CP material
  6884.     jmp    getfont12        ; fail
  6885.                     ; found CP section, find fonts
  6886. getfont8:mov    dx,word ptr stripoff[24]  ; offset of fonts data
  6887.     mov    cx,word ptr stripoff[26]  ; high order part
  6888.     mov    ah,lseek
  6889.     xor    al,al            ; seek from BOF
  6890.     int    dos
  6891.     mov    bx,temp            ; handle
  6892.     mov    cx,6            ; read font's "dathead"
  6893.     mov    dx,offset stripoff
  6894.     mov    ah,readf2
  6895.     int    dos
  6896.     mov    di,word ptr stripoff[2] ; number of fonts in this CP item
  6897.  
  6898. getfont9:mov    bx,temp            ; handle
  6899.     mov    cx,6            ; read fonthead: hgt,width,0,0,# chars
  6900.     mov    dx,offset stripoff
  6901.     mov    ah,readf2
  6902.     int    dos
  6903.     mov    ax,word ptr stripoff    ; cell height (low byte)
  6904.     push    ax            ; save for test below
  6905.     mov    cl,ah            ; cell width (typically 8)
  6906.     mul    cl            ; number of bytes per char
  6907.     mul    word ptr stripoff[4]    ; number chars in table=bits to skip
  6908.     mov    cx,8            ; divide by 8 for bytes, hope is ok
  6909.     div    cx
  6910.     xor    cx,cx            ; high part, for lseek
  6911.     mov    dx,ax            ; low part (whole bytes)
  6912.     pop    ax
  6913.     cmp    ax,8*256+14         ; is this font 14x8?
  6914.     je    getfont10        ; e = yes, that is what we want
  6915.     mov    bx,temp            ; handle
  6916.     mov    ah,lseek
  6917.     mov    al,1            ; seek from current position
  6918.     int    dos
  6919.     dec    di            ; one less font in this CP section
  6920.     cmp    di,0            ; done all?
  6921.     jg    getfont9        ; g = no
  6922.     stc
  6923.     jmp    short getfont12        ; fail
  6924.                     ; read the 8x14 patterns
  6925. getfont10:mov    dx,128*14        ; bytes in GLeft patterns (128 chars)
  6926.     xor    cx,cx
  6927.     mov    bx,temp            ; handle
  6928.     mov    ah,lseek
  6929.     mov    al,1            ; seek from current position
  6930.     int    dos
  6931.                     ; malloc memory for font table
  6932.     mov    bx,(128*14)/16        ; paragraphs for 128*14 bytes
  6933.     mov    cx,bx            ; remember desired paragraphs
  6934.     mov    ah,alloc        ; allocate a memory block
  6935.     int    dos
  6936.     jc    getfont12        ; c = error, not enough memory
  6937.      cmp    bx,cx            ; obtained vs wanted
  6938.     jae    getfont11        ; ae = enough
  6939.     mov    es,ax            ; allocated segment
  6940.     mov    ah,freemem        ; free it
  6941.     int    dos
  6942.     jmp    short getfont12        ; quit here
  6943.  
  6944. getfont11:mov    word ptr fontrptr+2,ax    ; address of allocated memory
  6945.     mov    word ptr fontrptr,0    ; offset is zero
  6946.     mov    cx,128*14        ; bytes in GRight patterns
  6947.     mov    bx,temp            ; handle
  6948.     push    ds
  6949.     mov    ds,ax
  6950.     xor    dx,dx            ; ds:dx is buffer, from malloc
  6951.     mov    ah,readf2
  6952.     int    dos
  6953.     pop    ds
  6954.     jnc    getfont12        ; nc = success
  6955.     mov    ax,word ptr fontrptr+2    ; get segment
  6956.     mov    es,ax            ; allocated segment
  6957.     mov    ah,freemem        ; free it
  6958.     int    dos
  6959.     stc                ; say failure
  6960. getfont12:pushf                ; save carry bit
  6961.     mov    bx,temp            ; handle
  6962.     mov    ah,close2        ; close file
  6963.     int    dos
  6964.     popf
  6965.     ret
  6966. getfont endp
  6967.  
  6968. ; Dispatch table processor. Enter with BX pointing at table of {char count,
  6969. ; address of action routines, characters}. Jump to matching routine or return.
  6970. ; Enter with AL holding received Final char.
  6971. atdispat proc near
  6972.     mov    cl,[bx]            ; get table length from first byte
  6973.     xor    ch,ch
  6974.     mov    di,bx            ; main table
  6975.     add    di,3            ; point di at first char in table
  6976.     push    es
  6977.     push    ds
  6978.     pop    es            ; use data segment for es:di below
  6979.     cld                ; set direction forward
  6980.     repne    scasb            ; find matching character
  6981.     pop    es
  6982.     je    atdisp2            ; e = found a match, get action addr
  6983.     cmp    al,' '            ; control char?
  6984.     jb    atdisp1            ; b = yes
  6985.     ret                ; ignore escape sequence
  6986. atdisp1:jmp    tekctl            ; process control char
  6987. atdisp2:sub    di,bx            ; distance scanned in table
  6988.     sub    di,4            ; skip count byte, address word, inc
  6989.     shl    di,1            ; convert to word index
  6990.     inc    bx            ; point to address of action routines
  6991.     mov    bx,[bx]            ; get address of action table
  6992.     jmp    word ptr [bx+di]    ; dispatch to the routine
  6993. atdispat endp
  6994.  
  6995. ansich    proc    near            ; insert Pn spaces at and after cursor
  6996.     mov    cx,param        ; get Pn
  6997.     or    cx,cx
  6998.     jnz    ansich1            ; got a value
  6999.     inc    cx            ; zero means one
  7000. ansich1:push    x_coord
  7001.     push    y_coord
  7002.     and    x_coord,not 7        ; modulo 8x8 cells
  7003.     mov    ax,xmax            ; start of last cell
  7004.     sub    ax,x_coord        ; start of current cell
  7005.     shr    ax,1            ; divide by 8 dots per char
  7006.     shr    ax,1
  7007.     shr    ax,1
  7008.     cmp    ax,cx            ; want more spaces than are on line?
  7009.     jae    ansich2            ; ae = no
  7010.     mov    cx,ax            ; clip to right margin
  7011.     jcxz    ansich3            ; z = nothing to do
  7012. ansich2:push    cx
  7013.     mov    al,' '            ; a space
  7014.     call    putc            ; write to screen
  7015.     pop    cx
  7016.     loop    ansich2            ; do them
  7017. ansich3:pop    x_coord
  7018.     pop    y_coord
  7019.     call    remcursor        ; remove text cursor symbol
  7020.     call    setcursor        ; draw cursor at new location
  7021.     ret
  7022. ansich    endp
  7023.                     ; scaled by text screen height
  7024. atcuu    proc    near            ; cursor up Pn lines
  7025.     cmp    param,0            ; empty arg?
  7026.     jne    atcuu1            ; got a value
  7027.     inc    param            ; zero means one
  7028. atcuu1:    mov    ax,y_coord        ; where we are now
  7029.     add    ax,4            ; round up a smidge
  7030.     mov    cl,byte ptr low_rgt+1    ; highest text line
  7031.     xor    ch,ch
  7032.     mul    cx            ; proportion
  7033.     xor    dx,dx
  7034.     mov    cx,ybot            ; highest scan line
  7035.     div    cx            ; end, estimate currren text line
  7036.     sub    ax,param
  7037.     inc    ax            ; count lines from 1 again
  7038.     mov    param,ax        ; new text row
  7039.     jmp    atcva            ; do as absolute
  7040. atcuu    endp
  7041.  
  7042.                     ; scaled by text screen height
  7043. atcud    proc    near            ; cursor down Pn lines
  7044.     cmp    param,0            ; get Pn
  7045.     jne    atcud1            ; ne = got a value
  7046.     inc    param            ; zero means one
  7047. atcud1:    mov    ax,y_coord        ; where we are now
  7048.     add    ax,4            ; round up a smidge
  7049.     mov    cl,byte ptr low_rgt+1    ; highest text line
  7050.     xor    ch,ch
  7051.     mul    cx            ; proportion
  7052.     xor    dx,dx
  7053.     mov    cx,ybot            ; highest scan line
  7054.     div    cx            ; end, estimate currren text line
  7055.     inc    ax            ; count lines from 1 again
  7056.     add    param,ax        ; new text row
  7057.     jmp    atcva            ; do as absolute
  7058. atcud    endp
  7059.  
  7060. atcuf    proc    near            ; cursor forward Pn columns
  7061.     mov    ax,param        ; get Pn
  7062.     or    ax,ax
  7063.     jnz    atcuf1            ; got a value
  7064.     inc    ax            ; zero means one
  7065. atcuf1:    shl    ax,1            ; times 8 dots per char cell
  7066.     shl    ax,1
  7067.     shl    ax,1            ; Tek columns worth
  7068.     and    x_coord,not 7        ; modulo 8x8 cells
  7069.     add    x_coord,ax        ; forward to absolute column
  7070.     mov    ax,xmax
  7071.     cmp    x_coord,ax        ; beyond right most cell?
  7072.     jbe    atcuf2            ; be = no
  7073.     mov    x_coord,ax        ; limit to right
  7074. atcuf2:    call    remcursor        ; remove text cursor symbol
  7075.     call    setcursor        ; draw cursor at new location
  7076.     ret
  7077. atcuf    endp
  7078.  
  7079. atcub    proc    near            ; cursor left/back Pn columns
  7080.     mov    ax,param        ; get Pn
  7081.     or    ax,ax
  7082.     jnz    atcub1            ; got a value
  7083.     inc    ax            ; zero means one
  7084. atcub1:    shl    ax,1
  7085.     shl    ax,1
  7086.     shl    ax,1            ; times 8 dots per cell
  7087.     and    x_coord,not 7        ; modulo 8x8 cells
  7088.     mov    cx,xmax
  7089.     cmp    x_coord,cx        ; beyond last col (wrap pending)?
  7090.     jbe    atcub3            ; be = no
  7091.     mov    x_coord,cx        ; set to last col
  7092. atcub3:    sub    x_coord,ax        ; back up
  7093.     jnc    atcub2            ; nc = ok
  7094.     mov    x_coord,0        ; stop in column zero
  7095. atcub2:    call    remcursor        ; remove text cursor symbol
  7096.     call    setcursor        ; draw cursor at new location
  7097.     ret
  7098. atcub    endp
  7099.  
  7100. atcnl    proc    near            ; do Pn cr/lf's
  7101.     mov    x_coord,0        ; to left margin
  7102.     jmp    atcud            ; do the cursor downs
  7103. atcnl    endp
  7104.  
  7105. atcpl    proc    near            ; do Pn cursor ups
  7106.     jmp    atcuu            ; do the cursor ups
  7107. atcpl    endp
  7108.  
  7109.                     ; scaled by text screen width
  7110. atcha    proc    near            ; cursor to absolute column
  7111.     and    x_coord,not 7        ; modulo 8x8 cells
  7112.     mov    ax,param        ; get Pn
  7113.     or    ax,ax
  7114.     jz    atcha1            ; z = zero already
  7115.     dec    param            ; count columns from 0
  7116.     mov    ax,xmax            ; number of Tek dots/row
  7117.     mul    param            ; times columns they want
  7118.     mov    cl,byte ptr low_rgt    ; number of last text column
  7119.     xor    ch,ch
  7120.     xor    dx,dx
  7121.     div    cx            ; scale to ~80 column screen
  7122.     cmp    ax,xmax            ; too far?
  7123.     jbe    atcha1            ; be = no
  7124.     mov    ax,xmax            ; right most column
  7125. atcha1:    mov    x_coord,ax
  7126.     call    remcursor        ; remove text cursor symbol
  7127.     call    setcursor        ; draw cursor at new location
  7128.     ret
  7129. atcha    endp
  7130.                     ; scaled by text screen height
  7131. atcva    proc    near            ; cursor to absolute row
  7132.     dec    param            ; count from 0
  7133.     mov    ax,param        ; desired text row
  7134.     or    ax,ax            ; zero or now -1?
  7135.     jg    atcva1            ; g = no, further down
  7136.     mov    ax,7            ; bottom of top text cell
  7137.     jmp    short atcva2
  7138. atcva1:    mov    ax,ybot
  7139.     inc    ax            ; number of scan lines on screen
  7140. ;;;;    and    ax,not 7        ; whole 8x8 char cells
  7141.     mul    param            ; times row they want
  7142.     mov    cl,byte ptr low_rgt+1    ; number of last text line (0..23)
  7143.     xor    ch,ch
  7144.     xor    dx,dx
  7145.     div    cx            ; scale to ~24 line screen 
  7146.     mov    cx,ybot
  7147. ;;;;    and    cx,not 7        ; whole 8x8 char cells
  7148.     cmp    ax,cx            ; too far?
  7149.     jbe    atcva2            ; be = no
  7150.     mov    ax,cx
  7151. atcva2:    mov    y_coord,ax        ; go to that line
  7152.     call    remcursor        ; remove text cursor symbol
  7153.     call    setcursor        ; draw cursor at new location
  7154.     ret
  7155. atcva    endp
  7156.     
  7157. atcup    proc    near            ; cursor to absolute row, column
  7158.     call    atcva            ; process param[0] as absolute row
  7159.     push    param[2]        ; column
  7160.     pop    param
  7161.     jmp    atcha            ; process param[2] as absolute column
  7162. atcup    endp
  7163.  
  7164. ated    proc    near            ; erase display
  7165.     mov    al,spcontrol        ; preserve space control
  7166.     mov    rdbuf,al        ; save here
  7167.     mov    spcontrol,1        ; turn on destructive space
  7168.     push    x_coord
  7169.     push    y_coord            ; save cursor
  7170.     cmp    param,0            ; cursor to end of screen?
  7171.     je    ated1            ; e = yes
  7172.     cmp    param,1            ; start of screen to cursor?
  7173.     je    ated3            ; e = yes
  7174.     cmp    param,2            ; entire screen?
  7175.     je    ated5            ; e = yes
  7176.     ret                ; else ignore
  7177.  
  7178. ated1:    mov    param,0            ; cursor to end of this line
  7179.     call    atel            ; erase cursor to end of line
  7180.     add    y_coord,8        ; look at next line
  7181.     mov    ax,ybot
  7182.     cmp    y_coord,ax        ; are we at the end now?
  7183.     ja    ated6            ; a = yes
  7184.     mov    x_coord,0        ; start of line is here
  7185.     jmp    ated1            ; do through last line
  7186.  
  7187. ated3:    and    y_coord,not 7        ; modulo 8x8 char cells
  7188.     mov    cx,y_coord        ; start of screen to cursor
  7189.     shr    cx,1            ; char lines at 8 dots/char
  7190.     shr    cx,1
  7191.     shr    cx,1
  7192.     dec    cx            ; omit current line= # whole lines
  7193.     or    cx,cx            ; any whole lines?
  7194.     jle    ated3b            ; le = no
  7195.     mov    y_coord,7        ; start at the top line
  7196. ated3a:    push    cx
  7197.     mov    param,2            ; entire line
  7198.     call    atel            ; erase entire line
  7199.     add    y_coord,8        ; next line
  7200.     pop    cx
  7201.     loop    ated3a
  7202. ated3b:    mov    param,1            ; start of line to cursor
  7203.     call    atel            ; erase to cursor on this (last) line
  7204.     jmp    short ated6
  7205.  
  7206. ated5:    call    tekcls            ; erase whole screen
  7207.  
  7208. ated6:    mov    al,rdbuf        ; spacing control
  7209.     mov    spcontrol,al
  7210.     pop    y_coord
  7211.     pop    x_coord
  7212.     call    remcursor        ; remove last cursor
  7213.     call    setcursor        ; set cursor to original position
  7214.     ret
  7215. ated    endp
  7216.  
  7217. atech    proc    near            ; erase Pn chars from cursor to eol
  7218.     mov    al,spcontrol        ; preserve space control
  7219.     mov    rdbuf,al        ; save here
  7220.     mov    spcontrol,1        ; turn on destructive space
  7221.     push    x_coord
  7222.     push    y_coord            ; save cursor
  7223.     mov    cx,x_coord
  7224.     and    cx,not 7        ; modulo 8x8 cells
  7225.     mov    ax,xmax
  7226.     sub    ax,cx            ; number of chars remaining on line
  7227.     shr    ax,1
  7228.     shr    ax,1
  7229.     shr    ax,1
  7230.     inc    ax            ; count cursor cell
  7231.     mov    cx,param        ; how many chars to erase
  7232.     or    cx,cx
  7233.     jz    atech1            ; z = zero, use one
  7234.     inc    cx
  7235. atech1:    cmp    ax,cx            ; want more than line length?
  7236.     jae    atech2            ; ae = no
  7237.     mov    cx,ax            ; clip at right margin
  7238.     or    cx,cx
  7239.     jle    atech3            ; le = nothing to do
  7240. atech2:    push    cx
  7241.     mov    al,' '
  7242.     call    outscrn            ; write spaces
  7243.     pop    cx
  7244.     loop    atech2
  7245. atech3:    mov    al,rdbuf        ; spacing control
  7246.     mov    spcontrol,al
  7247.     pop    y_coord
  7248.     pop    x_coord
  7249.     call    remcursor        ; remove last cursor
  7250.     call    setcursor        ; set cursor to original position
  7251.     ret
  7252. atech    endp
  7253.  
  7254. atel    proc    near            ; erase on this line
  7255.     call    remcursor        ; remove cursor
  7256.     push    x_coord
  7257.     push    y_coord
  7258.     cmp    param,0            ; cursor to end of line?
  7259.     je    atel1            ; e = yes
  7260.     cmp    param,1            ; start of line to cursor?
  7261.     je    atel3            ; e = yes
  7262.     cmp    param,2            ; whole line?
  7263.     jne    atel5            ; ne = no, fail
  7264.     mov    x_coord,0        ; erase entire line
  7265.  
  7266. atel1:    mov    cx,xmax            ; cursor to end of line
  7267.     mov    ax,x_coord
  7268.     and    ax,not 7        ; modulo 8x8 cells
  7269.     sub    cx,ax
  7270.     shr    cx,1
  7271.     shr    cx,1
  7272.     shr    cx,1            ; 8 dots/char
  7273.     inc    cx            ; count the cursor cell
  7274.     or    cx,cx
  7275.     jle    atel5            ; le = do nothing
  7276.     mov    al,spcontrol        ; preserve space control
  7277.     mov    rdbuf,al        ; save here
  7278.     mov    spcontrol,1        ; turn on destructive space
  7279. atel2:    push    cx            ; start of line to cursor
  7280.     mov    al,' '
  7281.     call    outscrn
  7282.     pop    cx
  7283.     loop    atel2
  7284.     mov    al,rdbuf        ; space control
  7285.     mov    spcontrol,al        ; restored
  7286. atel5:    pop    y_coord
  7287.     pop    x_coord
  7288.     call    remcursor        ; remove last cursor
  7289.     call    setcursor        ; set cursor to original position
  7290.     ret
  7291. atel3:    mov    cx,x_coord        ; start of line to cursor
  7292.     shr    cx,1
  7293.     shr    cx,1
  7294.     shr    cx,1
  7295.     inc    cx            ; count cursor cell
  7296.     mov    x_coord,0        ; go to start of line
  7297.     jmp    atel2            ; do the loops
  7298. atel    endp
  7299. code2    ends
  7300.     end
  7301.