home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / mskermit / msgibm.asm < prev    next >
Assembly Source File  |  2020-01-01  |  243KB  |  7,513 lines

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