home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / extra / nyenhuis3.arc / MSGIBM.ASM < prev    next >
Assembly Source File  |  1990-01-16  |  154KB  |  4,748 lines

  1.      Name msgibm
  2. ; File MSGIBM.ASM
  3.     include mssdef.h
  4. ; Tektronix emulator for use with MS Kermit/IBM.
  5. ; Edit history:
  6. ; Last edit 16 Jan 1990
  7. ; 8 June 1989 Added Wyse-700 support from Mikko Laanti.
  8. ; 21 Nov 1988 Version 2.32
  9. ; 1 Nov 1987 Heavy rewrite to integrate code into regular MS Kermit/IBM
  10. ;  material. [jrd]
  11. ;==============================================================================
  12. ; Original version for TI Pro computers by
  13. ; 12-Dec-84  Joe Smith, CSM Computing Center, Golden CO 80401
  14. ; adapted to IBM PC June 1987 by    Brian Holley,
  15. ;                    Faculty of Economics and Politics
  16. ;                    University of Cambridge, England
  17. ;                    Email: BJH6@UK.AC.CAM.PHX
  18. ; Upgraded and integrated into MS Kermit 2.30 by Joe Doupnik, Utah State Univ.
  19. ;
  20. ;           Description of Tektronix commands
  21. ;
  22. ; ESC CONTROL-E (ENQ) requests a status report
  23. ; ESC FORMFEED erases the screen.
  24. ; ESC CONTROL-X turns on bypass mode (no screen characters).
  25. ; ESC CONTROL-Z turns on the crosshairs (not on 4006 or 4025)
  26. ; ESC ? is replaced by DEL code, to assist line plots with 7 bit systems.
  27. ; ESC [ Pn ; Pn m  set screen colors. Pn = 30 + sum of colors for foregnd,
  28. ;  40 + sum of colors for background, Pn = 0 sets b/w, Pn = 1 for high
  29. ;  intensity. Colors are red = 1, green = 2, blue = 4.
  30. ; ESC [ ? 3 8 l  exits Tek mode and returns to host text terminal type
  31. ;  (VT102 if none defined yet). This is an extension from DEC VT340's.
  32. ; ESC [ ? 256 n  invokes a screen size report, for Word Perfect. Report is
  33. ;   ESC [ ? 256; height; width; num colors n   where num colors is 0, 1 or
  34. ;   16; report ESC [ ? 24; 80; 0 n  for pure text mono systems.
  35. ; ESC @  through  ESC M  sets default fill pattern as below (1=@...).
  36. ; ESC Z  report terminal type (as VT320)
  37. ; ESC [ 2; 2 $ u  host request color palette report.
  38. ; ESC / xhome;yhome;xwidth;yheight x           draw an empty rectangle
  39. ; ESC / xhome;yhome;xwidth;yheight;pattern y   fill rectangle with pattern
  40. ; ESC / xhome;yhome;xwidth;yheight;pattern z   fill rect with pattern+border
  41. ;  where x/yhome is the lower left Tek corner, xwidth and yheight are the
  42. ;  Tek width and height. All values are decimal numbers.
  43. ;  Patterns 0:use default, 1:solid, 2:grey, 3:left to right slant, 4:right to
  44. ;  left slant, 5:horizontal lines, 6:vertical lines, 7:slanted cross-hatch,
  45. ;  8:vertical cross-hatch, 9:checkerboard; 10:dotted, 11:horiz herringbone,
  46. ;  12:vertical herringbone,13 and above:border without fill. All are tiling
  47. ;  8x8 pixel patterns.
  48. ; ESC / param a, ... ESC / param c  set user definable line drawing pattern
  49. ;  to 16 bit value of param; plot as lsb first.
  50. ; ESC / 2 h or l,  ESC / 9 h or l. h is set, l is reset, 2 is destructive
  51. ;  space and 9 is destructive backspace. Defaults are reset.
  52. ; ESC x  ESC y  ESC z   selects one of these user definable patterns above.
  53. ; ESC P  P1; P2; P3 q string ESC \        a Sixel Graphics command
  54. ;   P1 and P3 ignored, P1 = 1 means draw 0 bits in background, else skip them.
  55. ;   string is
  56. ;     sixel chars (3fh..7eh, lower 6 bits+3fh, displayed lsb at the top)
  57. ;     ! Pn sixel char        where Pn is a repeat count
  58. ;     " Pc; Pad; Ph; Pv        raster attributes (all ignored for now)
  59. ;     # Pc; Pu; Px; Py; Pz  coloring as follows
  60. ;    Pc is color palette, 0-15
  61. ;    Pu is color units, 1=HLS, 2=RGB
  62. ;    For Hue Lightness Saturation:
  63. ;        Px = Hue angle, 0-360 degrees. The colors are mapped around
  64. ;        the color wheel in 60 degree segments as Hues:
  65. ;        0-29 deg = blue, 30-89 = magenta (blue + red), 90-149 = red,
  66. ;        150-209 = yellow (red + green), 210-269 = green,
  67. ;        270-329 = cyan (green + blue), 330-359 = blue.
  68. ;        Py = Lightness, 0-100%, Pz = Saturation, 0-100%
  69. ;          Lightness    Sat = 51-100    Sat = 11-50     Sat = 0-10
  70. ;          86-100    bold white    bold white     bold white
  71. ;          71-85        bold hue    bold white     bold white
  72. ;          57-70        bold hue    grey (dim white) grey
  73. ;          43-56        bold hue    dim hue         black
  74. ;          29-42        dim hue        grey         grey
  75. ;          14-28        dim hue        black         black
  76. ;           0-13     black        black         black
  77. ;        Note that Py = Pz = 50 gives the widest spectrum.
  78. ;    For RGB: Px = red, 0-100%, Py = green, 0-100%, Pz = blue, 0-100%
  79. ;        If any color exceeds 50% then the bold bit is turned on for
  80. ;        the ensemble (IBM ega display adapter constraint for RGBi).
  81. ;
  82. ;    Palette registers can be selected by the substring
  83. ;        # Pc    followed by a non-numeric char other than ";"
  84. ;            and Pc is the palette register, 0-15.
  85. ;
  86. ;     $  (dollar sign )     meaning go to left margin
  87. ;     -  (minus)         meaning go to left margin 6 dots down.
  88. ;   This command yields one or more sets of 6 vertically arranged dots. They
  89. ;   are placed starting at the top and left side of the current text cell.
  90. ;   Escape sequences are permitted within string and occur without disruption.
  91. ; CONTROL-] (GS) turns on plot mode, the first move will be with beam off.
  92. ; CONTROL-^ (RS) turns on incremental plot mode. RS space means move pen up
  93. ;  RS P means move pen down, following letters:A, E, D, F, B, J, H, I mean
  94. ;  move right, right and up, up, left and up, left, left and down, down, and
  95. ;  right and down, respectively. Ex: RS <space> J J J  means move three Tek
  96. ;  positions left and down with the pen up (invisibly).
  97. ; CONTROL-UNDERLINE (US) turns off plot mode, as does CR (for all but 4025).
  98. ; CONTROL-X switches from TEKTRONIX sub mode to NORMAL alpha mode but is
  99. ;  ignored if we are emulating a full Tek terminal rather than a sub mode
  100. ;  of DEC or Heath.
  101. ; FF erases screen.
  102. ; ESC letter, where letter is accent grave (`), a-e sets the line drawing
  103. ;   pattern until reset to solid lines (same as escape accent) by command or
  104. ;   a terminal reset.
  105. ;    ENQ = Control E
  106. ;    ESC = Control [ (left square bracket)
  107. ;    FF = Control L
  108. ;    FS = Control \ (backslash)
  109. ;    GS = Control ] (right square bracket)
  110. ;    RS = Control ^ (caret)
  111. ;    US = Control _ (underscore)
  112. ;
  113. ; The plot commands are characters which specify the absolute position to move
  114. ; the beam.  All moves except the one immediately after the GS character
  115. ; (Control-]) are with a visible trace.
  116. ;
  117. ; For 4010-like devices - The positions are from 0 to 1023 for both X and Y,
  118. ; although only 0 to 780 are visible for Y due to screen geometry.  The screen
  119. ; is 10.23 by 7.80 inches, and coordinates are sent as 1 to 4 characters.
  120. ;
  121. ; For 4014-like devices - The positions are from 0 to 4096, but each movement
  122. ; is a multiple of 4 positions unless the high-resolution LSBXY are sent.  This
  123. ; makes it compatible with the 4010 in that a full sized plot fills the screen.
  124. ;
  125. ; HIX,HIY = High-order 5 bits of position
  126. ; LOX,LOY = Middle-order 5 bits of position
  127. ; LSBXY      = Low-order 2 bits of X + low-order 2 bits of Y (4014 mode)
  128. ;
  129. ; Hi Y      Lo Y      Hi X      LSBXY      Characters sent (Lo-X always sent)
  130. ; ----      ----      ----      -----      ----------------------------------
  131. ; Same      Same      Same      Same                 Lo-X
  132. ; Same      Same      Same      Diff        LSB, Lo-Y,     Lo-X    4014
  133. ; Same      Same      Diff      Same             Lo-Y, Hi-X, Lo-X
  134. ; Same      Same      Diff      Diff        LSB, Lo-Y, Hi-X, Lo-X    4014
  135. ; Same      Diff      Same      Same             Lo-Y,     Lo-X
  136. ; Same      Diff      Same      Diff        LSB, Lo-Y,     Lo-X    4014
  137. ; Same      Diff      Diff      Same             Lo-Y, Hi-X, Lo-X
  138. ; Same      Diff      Diff      Diff        LSB, Lo-Y, Hi-X, Lo-X    4014
  139. ; Diff      Same      Same      Same      Hi-Y,             Lo-X
  140. ; Diff      Same      Same      Diff      Hi-Y, LSB, Lo-Y,     Lo-X    4014
  141. ; Diff      Same      Diff      Same      Hi-Y,         Lo-Y, Hi-X, Lo-X
  142. ; Diff      Same      Diff      Diff      Hi-Y, LSB, Lo-Y, Hi-X, Lo-X    4014
  143. ; Diff      Diff      Same      Same      Hi-Y,         Lo-Y,     Lo-X
  144. ; Diff      Diff      Same      Diff      Hi-Y, LSB, Lo-Y,     Lo-X    4014
  145. ; Diff      Diff      Diff      Same      Hi-y,         Lo-Y, Hi-X, Lo-X
  146. ; Diff      Diff      Diff      Diff      Hi-y, LSB, Lo-Y, Hi-X, Lo-X    4014
  147. ; Offset for byte:          20h    60h  60h   20h     40h
  148. ;
  149. ; Note that LO-Y must be sent if HI-X has changed so that the TEKTRONIX knows
  150. ; the HI-X byte (in the range of 20h-3fh) is HI-X and not HI-Y.     LO-Y must
  151. ; also be sent if LSBXY has changed, so that the 4010 will ignore LSBXY and
  152. ; accept LO-Y.    The LSBXY byte is 60h + MARGIN*10h + LSBY*4 + LSBX. (MARGIN=0)
  153. ;
  154. ;
  155. ;
  156. ; External variable tekflg and calls to tekini, tekemu, tekesc, tekcls:
  157. ; Byte TEKFLG is non-zero when the Tek emulator is active; it is set by the
  158. ; startup code in tekini and is maintained in this file. Internal variable
  159. ; inited remembers if we have a graphics screen saved, etc.
  160. ; TEKINI must be called when entering the emulator to establish the graphics
  161. ; screen mode and to calculate the screen dimensions.
  162. ; TEKRINT reinitialize complete emulator.
  163. ; TEKESC is called from say mszibm.asm to invoke Tek emulation when the
  164. ; external procedures have detected an Escape Control-L sequence. An implicit
  165. ; initialization is done if necessary.
  166. ; TEKEMU is the normal entry point to pass a received character to the emulator.
  167. ; It too will do an implicit initialization, if required.
  168. ; TEKCLS clears the graphics screen, but only if the emulator is active.
  169. ; The emulator remains active during Connect mode Help, Status, and other
  170. ; interrupts which do not change the terminal type.
  171.  
  172.      
  173.     public    tekemu,tekini,tekrint,tekend,tekgraf ; Terminal emulation
  174.         public    tekflg, tekdmp, tekinq, tekpal    ;  used by mszibm file
  175.     public    chcontrol            ; used by msyibm file
  176.  
  177. ENQ    equ    05h            ; ^E ENQ for TEK enquiries
  178. CAN    equ    18h            ; ^X to return to ANSI mode
  179. ESCZ    equ    1Ah            ; SUB, ESC-^Z triggers crosshairs
  180. VT    equ    0bh            ; ^K go up one line
  181. FS    equ    1ch            ; ^\ for point plot mode
  182. GS    equ    1Dh            ; ^] draw line (1st move is invisible)
  183. RS    equ    1Eh                   ; ^^ for incremental line plot mode
  184. US    equ    1Fh            ; ^_ (underscore) returns to text mode
  185. accent    equ    60h            ; accent grave
  186.  
  187. txtmode    equ    4            ; text mode for TEKTRONIX status
  188. maxtekx equ    1024            ; horizontal and
  189. maxteky equ    780            ; vertical resolution of TEK 4010
  190.      
  191. screen    equ    10h            ; IBM Bios screen call
  192.      
  193. uparr    equ    72            ; DOS scan codes for arrow keys
  194. dnarr    equ    80
  195. lftarr    equ    75
  196. rgtarr    equ    77
  197. homscn    equ    71            ; DOS home screen scan code
  198. shuparr    equ    '8'            ; ascii codes for shifted arrows
  199. shdnarr    equ    '2'
  200. shlftarr equ    '4'
  201. shrgtarr equ    '6'
  202.      
  203.                     ; Graph_mode for different systems:
  204. cga    equ    6            ; highest resolution mode for CGA
  205. mono    equ    7            ; real monochrome display adapter
  206. colorega equ    14            ; Low-res mode, color EGA
  207. monoega equ    15            ; mono ega needs mode 15
  208. ega    equ    16            ; Hi-res mode - EGA
  209. olivetti equ    72            ; Olivetti's Hi-res - 50 lines text
  210. toshiba    equ    74h            ; Toshiba T3100, like Olivetti
  211. vaxmate    equ    0D0h            ; DEC VAXmate II, like Olivetti
  212. wyse700 equ    0D3h            ; Wyse-700 1280 * 400
  213. hercules equ    255            ; pseudo mode for Hercules graphics
  214. ; Note: IBM VGA modes 17 & 18, 640 by 480, can be used by setting "ega" above
  215. ; to 17 or 18 and modifying ybot to be 479 and ymult to be 48 at label tekin5.
  216. ; The code will scale everything appropriately for the new screen size, but
  217. ; there will be insufficient memory to retain the entire graphics image.
  218. ; Manual override SET TERMINAL GRAPHICS VGA accomplishes these two steps.
  219. ;
  220. ; Note: WYSE-700 mode 1024 * 780 and 1280 * 800 can be set only by
  221. ; manual override SET TERMINAL GRAPHICS WYSET or WYSEA, respectively.
  222. ; No automatic sensing for Wyse.
  223.  
  224. segega    equ    0a000h            ; segments of display memory, EGA,VGA
  225. segcga    equ    0b800h            ; CGA, AT&T/Olivetti and relatives
  226. seghga    equ    0b000h            ; HGA
  227. segmono    equ    0b000h            ; Monochrome
  228. segwyse equ    0a000h            ; wyse-700, both banks start from here
  229.                     ; Wyse equates:
  230. wystoff equ    03ddh            ; set bank start offset
  231. wystseg equ    03deh            ; set bank start base
  232. wymode    equ    03dfh            ; register to select mode & bank
  233. wybeven equ    0c8h            ; mask for R/W even bank
  234. wybodd    equ    0cbh            ; mask for R/W odd bank
  235.  
  236.                     ; Hercules equates:
  237. index    equ    03b4h            ; 6845 index register
  238. cntrl    equ    03b8h            ; Display mode control port
  239. hstatus    equ    03bah            ; status port
  240. scrn_on equ    8            ; bit to turn screen on
  241. grph    equ    2            ; graphics mode
  242. text    equ    20h            ; text mode
  243. config    equ    03bfh            ; configuration port
  244. genable equ    1+2            ; enable graphics (1) on two pages (2) 
  245. rgbbold    equ    80            ; nor/bold threshold for RGB intensity
  246. hiy    equ    1            ; codes for Tek graphics components
  247. loy    equ    2
  248. hix    equ    4
  249. lox    equ    3
  250. ; maxparam and maxinter must agree with the prime equ's in file mszibm.asm
  251. maxparam equ    10            ; number of ESC and DCS Parameters
  252. maxinter equ    10            ; number of ESC and DCS Intermediates
  253.  
  254.                     ; Pixel basic operation codes
  255. pixor    equ    1            ; write as foreground OR current dot
  256. pixbak    equ    2            ; write as absolute background color
  257. pixxor    equ    4            ; write as foreground XOR current dot 
  258. pixfor    equ    8            ; write absolute foreground color
  259.  
  260. data    segment public 'data'
  261.     extrn    flags:byte, portval:word, rxtable:byte, vtemu:byte     
  262.     extrn    tv_mode:byte, yflags:byte, low_rgt:byte
  263.     extrn    param:word, nparam:word, inter:byte, ninter:word, lparam:byte
  264.     extrn    parstate:word, pardone:word, parfail:word
  265.     extrn    dnparam:word, dparam:word, dlparam:byte, dninter:word
  266.     extrn    dinter:byte, dcsstrf:byte, emubufc:word, emubuf:byte
  267.     extrn    emubufl:word
  268.  
  269. ; required for Hercules screen handling
  270.      
  271. gtable    db    35h,2dh,2eh,7        ; bytes for 6845 controller
  272.     db    5bh,2,57h,57h        ; - graphics mode
  273.     db    2,3,0,0
  274.      
  275. ttable    db    61h,50h,52h,0fh        ; bytes for 6845 controller
  276.     db    19h,6,19h,19h        ; - text mode
  277.     db    2,0dh,0bh,0ch
  278.  
  279. attlogo    db    'OLIVETTI'        ; Olivetti M24/28, AT&T 6300 rom id
  280. attllen    equ    $-attlogo        ; length
  281. toshlogo db    '  TT33110000  TTOOSSHHIIBBAA' ; Toshiba T3100 logo
  282. toshlen    equ    $-toshlogo        ; length
  283. declogo    db    'Copyright Digital Equipment Corp' ; DEC VAXmate
  284. declen    equ    $-declogo
  285. dumpname db    'TEKPLT.TIF',0        ; dump name
  286. dumplen    equ    $-dumpname
  287. tempname db    84 dup (0)        ; temp work area
  288. dhandle    dw    -1            ; dump file handle
  289.  
  290. ttstate    dw    tektxt            ; state machine control pointer
  291. prestate dw    0            ; previous state, across interruptions
  292. visible db    0            ; 0 to move, 1 to draw a line
  293. tek_hiy dw    0            ; Y coordinate in Tektronix mode
  294. tek_loy db    0
  295. tek_hix dw    0            ; X coordinate in Tektronix mode
  296. tek_lox db    0
  297. tek_lsb db    0            ; Low-order 2 bits of X + low Y
  298.                     ;    (4014 mode)
  299. status    db    0
  300. lastc    db    0            ; last x/y coord fragment seen       
  301. bnkchan db    0            ; a flag so we can select which bank
  302.                     ; to write in Wyse 1280*800 mode
  303. colpal    db    0,9,0ch,0ah        ; VT340 color palette table, IRGB
  304.     db    0dh,0bh,0eh,7, 8,1,4,2, 5,3,6,0fh ; 16 bytes, active table
  305. coldef    db    0,9,0ch,0ah, 0dh,0bh,0eh,7, 8,1,4,2, 5,3,6,0fh ; color def
  306. mondef    db    0,7 dup (0fh), 8 dup (7) ; monochrome default "colors"
  307. masktab db    80h,40h,20h,10h,8,4,2,1 ; quicker than calculations!
  308.                     ; dashed line patterns
  309. linetab    dw    0ffffh            ; ESC accent    11111111 11111111
  310.     dw    0aaaah            ; ESC a        10101010 10101010
  311.     dw    0f0f0h            ; ESC b        11110000 11110000
  312.     dw    0fafah            ; ESC c        11111010 11111010
  313.     dw    0ffcch            ; ESC d        11111111 11001100
  314.     dw    0fc92h            ; ESC e        11111100 10010010
  315.     dw    0            ; ESC x    user defined
  316.     dw    0            ; ESC y user defined
  317.     dw    0            ; ESC z user defined
  318. linepat    dw    0ffffh            ; active line pattern, from above
  319.  
  320. tekid    db    escape,'[?63;1;2;4;8;9;15c',0; VT320, level 3, etc
  321. ;End of init data
  322.  
  323.     even
  324. xmult    dw    1            ; scaling factor for x is
  325. xdiv    dw    1            ;     xmult/xdiv
  326. ymult    dw    1            ; scaling factor for y is
  327. ydiv    dw    1            ;     ymult/ydiv
  328. xmax    dw    1            ;
  329. ybot    dw    1            ;
  330. x_coord dw    0            ; Tek text char X coordinate
  331. y_coord dw    0            ; Tek text char Y coordinate
  332. xcross    dw    0            ; cross hairs to start at centre
  333. ycross    dw    0
  334. oldx    dw    0            ; Tek coordinates of last point
  335. oldy    dw    767            ;  initially top left
  336. scalex    dw    0            ; PC coord for scaled x value
  337. scaley    dw    0            ;  for scaled y value
  338. rectx1    dw    0            ; Rectangle PC x lower left corner
  339. recty1    dw    0            ; Rectangle PC y lower left corner
  340. rectx2    dw    0            ; Rectangle PC x width
  341. recty2    dw    0            ; Rectangle PC y height
  342. numlines dw    0            ; number of lines to fill
  343.                     ; area fill material
  344. fill    db    0            ; current fill byte pattern
  345. fillptr    dw    filpat1            ; pointer to current fill pattern
  346. fillist    dw    filpat1,filpat2,filpat3,filpat4,filpat5,filpat6,filpat7
  347.     dw    filpat8,filpat9,filpat10,filpat11,filpat12,filpat13
  348.     dw    filpat14
  349. numfil    equ    ($-fillist)/2        ; number of fill patterns
  350.     ; fill patterns, 8 bits wide, first byte is at top of PC screen
  351.     ; 8 bytes per pattern for 8 scan line repetition
  352. filpat1    db    8 dup (0ffh)        ; solid fill
  353. filpat2    db    4 dup (0aah, 55h)    ; grey (alternating dots)
  354. filpat3    db    80h,01h,02h,04h, 08h,10h,20h,40h ; right to left slant up
  355. filpat4    db    80h,40h,20h,10h, 08h,04h,02h,01h ; left to right slant up
  356. filpat5 db    2 dup (0,0,0aah,0)    ; horizontal lines
  357. filpat6    db    8 dup (44h)        ; vertical lines
  358. filpat7    db    80h,41h,22h,14h, 08h,14h,22h,41h   ; slanted crosshatch
  359. filpat8    db    2 dup (0aah,80h,80h,80h)  ; vertical crosshatch
  360. filpat9    db    4 dup (0f0h), 4 dup (0fh) ; checkerboard
  361. filpat10 db    4 dup (44h, 11h)    ; dots
  362. filpat11 db    2 dup (10h,28h,44h,82h)    ; horizontal herringbone
  363. filpat12 db    80h,40h,20h,10h,08h,10h,20h,40h ; vertical herringbone
  364. filpat13 db    8 dup (0)        ; first user definable fill
  365. filpat14 db    8 dup (0)        ; second user definable fill
  366.                     ; end of area fill material
  367. curmode    db    0            ; screen mode before graphics
  368. tekgraf    db    0        ; Tek graphics board selection (def=auto)
  369.                 ; local variables for LINE plotting routine
  370. graph_mode db    0            ; graphics video mode, default is none
  371. cursor    dw    0            ; saved text cursor
  372. inited    db    0            ; non-zero if inited (retains page)
  373. tekflg    db    0            ; Tek mode active flag
  374.                     ;  1=Tek reads serial port
  375.                     ;  2=VT300 emulator reads serial port
  376. tekident db    0            ; Tek ident request flag
  377. flow    dw    0            ; flow control word
  378. gpage    db    0            ; display adapter graphics page
  379. gfcol    db    15            ; graphics foreground colour
  380. gbcol    db    0            ; graphics background color
  381. tfcol    db    0            ; temp foreground color
  382. tbcol    db    0            ; temp background color
  383. colortb    db    0,4,2,6,1,5,3,7        ; color reversed-bit setting bytes
  384. ccode    db    pixfor            ; temp for holding plot color code
  385. bypass    db    0            ; GIN mode bypass condition (0=off)
  386. esctype    db    0
  387. bscontrol db    0            ; non-zero for destructive BS
  388. spcontrol db    0            ; non-zero for destructive SPACE
  389. chcontrol db    0            ; char-writing, 1=opaque,0=transparent
  390.     even
  391. putc    dw    mputc            ; ptr to plot a character routine
  392. psetup    dw    psetupm            ; ptr to plot setup routine
  393. pincy    dw    pincym            ; ptr to inc y routine
  394. plotptr    dw    pltmon            ; ptr to dot plot routine
  395. gcplot    dw    gcgen            ; ptr to char plot routine
  396. gfplot    dw    bpltmon            ; ptr to area-fill plot routine
  397. segscn    dw    0b800h            ; actual screen segment to use
  398. doneptr    dw    offset xpardone,seg xpardone ; far pointer for tpardone use
  399. dumpptr    dw    offset dump,seg dump    ; far pointer for dump use
  400. initptr    dw    offset tekini,seg tekini
  401. rptptr    dw    offset tekrpt,seg tekrpt
  402. endptr    dw    offset tekend,seg tekend
  403. linelen    dw    0            ; offset increment between scan lines
  404. ten    dw    10            ; word 10 for multiplying
  405. temp    dw    0
  406.  
  407. ; 8*8 font for Hercules and such, CGA, and EGA
  408. ; - allows 43 lines, and 80 (90 for Hercules) chars per line.
  409. ; all printing (?) characters from <space> to <del> - two characters per line
  410. ; 8 bits per scan line, top line given first, 8 scan lines.    
  411. font    db    0,0,0,0,0,0,0,0,           18h,18h,18h,18h,18h,0,18h,0
  412.     db    6ch,6ch,6ch,0,0,0,0,0,           36h,36h,7fh,36h,7fh,36h,36h,0
  413.     db    0ch,3fh,68h,3eh,0bh,7eh,18h,0, 60h,66h,0ch,18h,30h,66h,06h,0
  414.     db    38h,6ch,6ch,38h,6dh,66h,3bh,0, 0ch,18h,30h,0,0,0,0,0
  415.     db    0ch,18h,30h,30h,30h,18h,0ch,0, 30h,18h,0ch,0ch,0ch,18h,30h,0
  416.     db    0,18h,7eh,3ch,7eh,18h,0,0,     0,18h,18h,7eh,18h,18h,0,0
  417.     db    0,0,0,0,0,18h,18h,30h,           0,0,0,7eh,0,0,0,0
  418.     db    0,0,0,0,0,18h,18h,0,           0,06h,0ch,18h,30h,60h,0,0
  419.     db    3ch,66h,6eh,7eh,76h,66h,3ch,0, 18h,38h,18h,18h,18h,18h,7eh,0
  420.     db    3ch,66h,06h,0ch,18h,30h,7eh,0, 3ch,66h,06h,1ch,06h,66h,3ch,0
  421.     db    0ch,1ch,3ch,6ch,7eh,0ch,0ch,0, 7eh,60h,7ch,06h,06h,66h,3ch,0
  422.     db    1ch,30h,60h,7ch,66h,66h,3ch,0, 7eh,06h,0ch,18h,30h,30h,30h,0
  423.     db    3ch,66h,66h,3ch,66h,66h,3ch,0, 3ch,66h,66h,3eh,06h,0ch,38h,0
  424.     db    0,0,18h,18h,0,18h,18h,0,       0,0,18h,18h,0,18h,18h,30h
  425.     db    0ch,18h,30h,60h,30h,18h,0ch,   0,0,0,7eh,0,7eh,0,0,0
  426.     db    30h,18h,0ch,06h,0ch,18h,30h,   0,3ch,66h,0ch,18h,18h,0,18h,0
  427.     db    3ch,66h,6eh,6ah,6eh,60h,3ch,   0,3ch,66h,66h,7eh,66h,66h,66h,0
  428.     db    7ch,66h,66h,7ch,66h,66h,7ch,   0,3ch,66h,60h,60h,60h,66h,3ch,0
  429.     db    78h,6ch,66h,66h,66h,6ch,78h,   0,7eh,60h,60h,7ch,60h,60h,7eh,0
  430.     db    7eh,60h,60h,7ch,60h,60h,60h,   0,3ch,66h,60h,6eh,66h,66h,3ch,0
  431.     db    66h,66h,66h,7eh,66h,66h,66h,   0,7eh,18h,18h,18h,18h,18h,7eh,0
  432.     db    3eh,0ch,0ch,0ch,0ch,6ch,38h,   0,66h,6ch,78h,70h,78h,6ch,66h,0
  433.     db    60h,60h,60h,60h,60h,60h,7eh,   0,63h,77h,7fh,6bh,6bh,63h,63h,0
  434.     db    66h,66h,76h,7eh,6eh,66h,66h,   0,3ch,66h,66h,66h,66h,66h,3ch,0
  435.     db    7ch,66h,66h,7ch,60h,60h,60h,   0,3ch,66h,66h,66h,6ah,6ch,36h,0
  436.     db    7ch,66h,66h,7ch,6ch,66h,66h,   0,3ch,66h,60h,3ch,06h,66h,3ch,0
  437.     db    7eh,18h,18h,18h,18h,18h,18h,   0,66h,66h,66h,66h,66h,66h,3ch,0
  438.     db    66h,66h,66h,66h,66h,3ch,18h,   0,63h,63h,6bh,6bh,7fh,77h,63h,0
  439.     db    66h,66h,3ch,18h,3ch,66h,66h,   0,66h,66h,66h,3ch,18h,18h,18h,0
  440.     db    7eh,06h,0ch,18h,30h,60h,7eh,   0,7ch,60h,60h,60h,60h,60h,7ch,0
  441.     db    0,60h,30h,18h,0ch,06h,0,0,     3eh,06h,06h,06h,06h,06h,3eh,0
  442.     db    18h,3ch,66h,42h,0,0,0,0,       0,0,0,0,0,0,0,0ffh
  443.     db    30h,18h,0ch,0,0,0,0,0,           0,0,3ch,06h,3eh,66h,3eh,0
  444.     db    60h,60h,7ch,66h,66h,66h,7ch,0, 0,0,3ch,66h,60h,66h,3ch,0
  445.     db    06h,06h,3eh,66h,66h,66h,3eh,0, 0,0,3ch,66h,7eh,60h,3ch,0
  446.     db    0eh,18h,18h,3ch,18h,18h,18h,0, 0,0,3eh,66h,66h,3eh,06h,3ch
  447.     db    60h,60h,7ch,66h,66h,66h,66h,0, 18h,0,38h,18h,18h,18h,3ch,0
  448.     db    18h,0,38h,18h,18h,18h,18h,70h, 60h,60h,66h,6ch,78h,6ch,66h,0
  449.     db    38h,18h,18h,18h,18h,18h,3ch,0, 0,0,76h,7fh,6bh,6bh,63h,0
  450.     db    0,0,7ch,66h,66h,66h,66h,0,     0,0,3ch,66h,66h,66h,3ch,0
  451.     db    0,0,7ch,66h,66h,7ch,60h,60h,0, 0,3eh,66h,66h,3eh,06h,07h
  452.     db    0,0,6ch,76h,60h,60h,60h,0,     0,0,3eh,60h,3ch,06h,7ch,0
  453.     db    30h,30h,7ch,30h,30h,30h,1ch,0, 0,0,66h,66h,66h,66h,3eh,0
  454.     db    0,0,66h,66h,66h,3ch,18h,0,     0,0,63h,6bh,6bh,7fh,36h,0
  455.     db    0,0,66h,3ch,18h,3ch,66h,0,     0,0,66h,66h,66h,3eh,06h,3ch
  456.     db    0,0,7eh,0ch,18h,30h,7eh,0,     0ch,18h,18h,70h,18h,18h,0ch,0
  457.     db    18h,18h,18h,0,18h,18h,18h,0,   30h,18h,18h,0eh,18h,18h,30h,0
  458.     db    31h,6bh,46h,0,0,0,0,0,           8 dup (0ffh)
  459.  
  460. ; TIFF version 5.0 data fields
  461. ; Reference: Aldus/Microsoft Technical Memorandum dated 8/8/88
  462.                     ; TIFF data item size indicators
  463. uchar    equ    1            ; unsigned byte
  464. ascii    equ    2            ; asciiz string byte
  465. integer    equ    3            ; 16 bit unsigned integer
  466. long    equ    4            ; 32 bit unsigned integer
  467. rational equ    5            ; 32 bit numerator, 32 bit denominator
  468.  
  469. entry    struc                ; 12 byte image file directory entries
  470.     dw    ?            ; tag
  471.     dw    integer            ; type, of data item
  472. entcnt    dd    1            ; length, count of data items
  473. entval    dw    0            ; long value or long offset to value
  474.     dw    0
  475. entry    ends
  476.     
  477.     even                ; TIFF 5.0,  8 byte header
  478. header    dw    4949h            ; 'll', low byte stored first
  479.     dw    42            ; TIFF identification, 42 decimal
  480.     dw    nentry-header,0        ; long offset to image file directory
  481.                     ; Image File Directory
  482. nentry    dw    entrycnt        ; number of entries to follow
  483.                     ; 12-byte directory entries
  484. newsub    entry    <0feh,long>        ; new subfield type
  485. iwidth    entry    <100h,integer>        ; image width,  integer for WP 5
  486. ilength entry    <101h,integer>        ; image length, integer for WP 5
  487. bps    entry    <102h,,,4>         ; bits per sample, 4=iRGB, 1=B/W
  488. comp    entry    <103h,,,1>        ; compression, none
  489. photo     entry    <106h,,,3>        ; photometric interpret, palette 
  490. strip     entry    <111h,long,25,stripoff-header> ; offset to long strip offsets
  491. spp    entry    <115h,,,1>        ; samples/pixel, 1
  492. rps    entry    <116h,long,1,25>    ; long rows per strip
  493. sbc    entry    <117h,integer,25,stripbc-header> ; offset to strip byte counts
  494. xres    entry    <11ah,rational,1,xresval-header> ; x axis resolution
  495. yres    entry    <11bh,rational,1,yresval-header> ; y axis resolution
  496. resunit entry    <128h,integer,1,1>    ; resolution unit, no absolute units
  497. soft    entry    <131h,ascii,proglen,prog-header> ; software ident
  498. stamp    entry    <132h,ascii,dtlen,dandt-header>  ; date and time stamp
  499. cmap    entry    <140h,integer,3*16,colmap-header> ; palette color map
  500. entrycnt equ    ($-nentry-2+11)/12    ; compute number of entries for nentry
  501.     dd    0            ; long offset of next directory (none)
  502.                     ; supporting data pointed at above
  503. prog    db    'MS Kermit 300',0    ; originating program, asciiz
  504. proglen equ    $-prog
  505. dandt    db    '1989:12:25 00:00:01',0    ; date and time format
  506. dtlen    equ    $-dandt
  507. xresval dw    0,0,1,0            ; two double words (top / bottom)
  508. yresval dw    0,0,1,0            ; two double words (top / bottom)
  509. stripoff dd    25 dup (0)        ; long file offset for each strip
  510. stripbc dw    25 dup (0)        ; integer byte count for each strip
  511.     ; color map for red, green, blue; index by IRGB bits from ega sample
  512. colmap    dw    4 dup (0), 4 dup (007ffh), 4 dup (0), 4 dup (0ffffh) ; red
  513.     dw    2 dup (0,0,007ffh,007ffh), 2 dup (0,0,0ffffh,0ffffh) ; green
  514.     dw    2 dup (0,007ffh,0,007ffh), 2 dup (0,0ffffh,0,0ffffh) ; blue
  515. tifflen equ    $-header         ; length of header + directory + info
  516. pixdata equ    $              ; pixel data start here on disk
  517.                     ; end of TIFF information
  518.  
  519. esctab    db    33            ; table of ESC <char> dispatches
  520.     dw    escjmp            ; address of table for action routines
  521.     db    ENQ,FF,CAN,CTLZ,'/'            ; ^E,^L,^X,^Z,/
  522.     db    '@ABCD','EFGHI','JKLM'
  523.     db    3fh,'PZ[\'                ; '?PZ[\'
  524.     db    60h,'abcde','xyz'            ; accent, a..e,x,y,z
  525.  
  526. ; Dispatch for esctab table
  527.     even
  528. escjmp    dw    tekenq, tekcls,tekcan, tekgin,tekeseq    ; ^E,^L,^X,^Z,/
  529.     dw    14 dup (tekfill)            ; '@ABCDEFGHIJKLM'
  530.     dw    tekqury,tekeseq,sendid,tekeseq,tekgotst ; '?PZ[\'
  531.     dw    9 dup (teklpat)                ; accent, a..e,x,y,z
  532.  
  533. ; Final char table for ANSI escape sequences
  534. anstab    db    21            ; number of entries
  535.     dw    ansjmp            ; address of action routines
  536.     db    '@ABCD','EFGHJ','KXade','fhlmn','u'
  537.  
  538. ; Dispatch for anstab table
  539.     even
  540. ansjmp    dw    ansich, atcuu,   atcud,   atcuf,  atcub        ; '@ABCD'
  541.     dw    atcnl,  atcpl,   atcha,   atcup,  ated        ; 'EFGHJ'
  542.     dw    atel,   atech,   atcuf,   atcva,  atcud        ; 'KXade'
  543.     dw    atcup,  escexit, escexit, tekcol, tekrid    ; 'fhlmn'
  544.     dw    tekprpt                        ; 'u'
  545. data    ends
  546.  
  547. code    segment public 'code'        ; main body code segment
  548.     extrn    outchr:near, beep:near, scrseg:near, cmblnk:near
  549.     extrn    savescr:near, restscr:near, cptchr:near, clrbuf:near
  550.     extrn    iseof:near, atparse:near, unique:near
  551.     extrn    chgdsp:near, pcwait:near, vtrmac:near, vtsmac:near
  552.  
  553.     assume    cs:code, ds:data, es:nothing
  554.  
  555. ; These far routines are called by the Tek emulator; they are here to provide
  556. ; a bridge to the main code segment near procedures.
  557.      
  558. ; Procedures for calling to the main body of MS Kermit. Most are FAR and
  559. ; must be in in code segment named code, not in code2.
  560.  
  561. outmodem proc    far            ; send Tek char out serial port
  562.     push    ax
  563.     mov    ah,al
  564.     call    outchr            ; outchr reads from ah
  565.     pop    ax
  566.     ret
  567. outmodem ENDP
  568.  
  569. tekbeep    proc    far            ; sound a beep from Tek mode
  570.     call    beep
  571.     ret
  572. tekbeep    endp
  573.  
  574. tcmblnk    proc    far            ; blank the screen from Tek mode
  575.     call    cmblnk
  576.     ret
  577. tcmblnk    endp
  578.  
  579. tsavescr proc    far            ; save text screen while in Tek mode
  580.     call    savescr
  581.     ret
  582. tsavescr endp
  583.  
  584. trestscr proc    far            ;restore text screen while in Tek mode
  585.     cmp    low_rgt,80        ; were we in 80 column mode?
  586.     jbe    trestsc1        ; be = yes
  587.     mov    al,1            ; set to 132 columns
  588.     call    chgdsp            ; msyibm routine to change screen
  589. trestsc1:
  590.     call    restscr
  591.     ret
  592. trestscr endp
  593.  
  594. tscrseg    proc    far            ; get video segment while in Tek mode
  595.     call    scrseg
  596.     ret
  597. tscrseg    endp
  598.  
  599. tclrbuf    proc    far            ; clear serial port buf while in Tek
  600.     call    clrbuf            ;  mode
  601.     ret
  602. tclrbuf    endp
  603.  
  604. tcptchr    proc    far            ; call session logger while in Tek
  605.     call    cptchr            ;  mode
  606.     ret
  607. tcptchr    endp
  608.  
  609. tiseof    proc    far            ; call iseof while in Tek mode
  610.     call    iseof
  611.     ret
  612. tiseof    endp
  613.  
  614. tparstart proc    far            ; start escape sequence parser
  615.     mov    parstate,0        ; set to initialize automatically
  616.     mov    pardone,offset tpardone    ; jmp to this when completed
  617.     mov    parfail,0        ; no failure case jump
  618.     ret
  619. tparstart endp
  620.  
  621. tparser    proc    far
  622.     call    atparse            ; reach to real parser
  623.     ret
  624. tparser    endp
  625.  
  626. tpardone proc    near            ; called by real parser
  627.     call    dword ptr doneptr    ; far call xpardone, old MASM way
  628.     ret
  629. tpardone endp
  630.  
  631. tunique    proc    far            ; reach to real unique name procedure
  632.     call    unique            ;  while in Tek mode
  633.     ret
  634. tunique    endp
  635.  
  636. tekwait    proc    far            ; call pcwait while in Tek mode
  637.     call    pcwait
  638.     ret
  639. tekwait    endp
  640.  
  641.  
  642. ; Return screen info for Tek screen report: ax=screen height, bx=width,
  643. ; cx=number of colors (0=none for pure text, 1=b/w, 16=ega)
  644. tekinq    proc    near
  645.     mov    tekident,1        ; say this is an ident request
  646.     call    dword ptr initptr    ; do init steps to get screen sizes
  647.     mov    ax,ybot            ; lowest screen line
  648.     inc    ax            ; screen height, in lines
  649.     mov    bx,xmax
  650.     add    bx,8            ; screen width, in dots
  651.     cmp    graph_mode,mono        ; pure text mono (no graphics at all)?
  652.     jne    tekinq1            ; ne = no
  653.     mov    ax,24            ; bottom screen line
  654.     mov    bx,80            ; screen width
  655.     xor    cx,cx            ; pure mono, say 0 colors
  656.     jmp    short tekinq2
  657. tekinq1:mov    cx,1            ; say b/w screen
  658.     cmp    plotptr,offset pltcga    ; using CGA style graphics?
  659.     je    tekinq2            ; e = yes
  660.     cmp    graph_mode,monoega    ; monochrome monitor on ega?
  661.     je    tekinq2            ; e = yes
  662.     mov    cx,16            ; say 16 colors
  663. tekinq2:mov    tekident,0
  664.     ret
  665. tekinq    endp
  666.  
  667. ; These routines can be called by either the main body or from within Tek
  668. ; mode.
  669. tekdmp    proc    near            ; Tek screen dump routine
  670.     call    dword ptr dumpptr    ; callable from main body
  671.     clc
  672.     ret
  673. tekdmp    endp
  674.  
  675. tekmac    proc    far            ; invoke vtrmac or vtsmac
  676.     or    ax,ax            ; which macro?
  677.     jz    tekmacr            ; z = the R flavor
  678.     call    vtsmac            ; do TerminalS, in msyibm
  679.     ret
  680. tekmacr:call    vtrmac            ; do TerminalR, in msyibm
  681.     ret                ; only if they fail
  682. tekmac    endp
  683.  
  684. tekpal    proc    near            ; do palette report tekrpt
  685.     call    dword ptr rptptr    ; callable from main body
  686.     ret
  687. tekpal    endp
  688. code    ends                ; main body code segment
  689.  
  690. ; Code segment code2 is allocated to Tektronix emulation
  691. code2    segment public 'code2'        ; supplementary code segment
  692.  
  693.     assume    cs:code2, ds:data, es:nothing
  694.  
  695. ; Initialise TEK mode by setting high resolution screen, etc
  696. tekini    proc    far
  697.     push    ax            ; do presence tests
  698.     push    bx
  699.     push    cx
  700.     push    dx
  701.     push    si
  702.     push    di
  703.     push    es
  704.     mov    bx,portval        ; get port flow control chars:
  705.     mov    bx,[bx].flowc        ; bh=xon, bl=xoff or both are nulls
  706.     mov    flow,bx            ; save here
  707.     mov    ax,bx            ; get flow control word
  708.     cmp    al,0            ; able to do xoff?
  709.     je    tekin0            ; e = no
  710.     call    outmodem        ; tell host xoff while we change modes
  711. tekin0:    mov    bx,vtemu.att_ptr    ; emulator screen color ptr
  712.     mov    al,[bx]
  713.     mov    gfcol,al        ; save foreground color
  714.     and    gfcol,0fh        ; save just foreground bits
  715.     and    al,70h            ; select background color, no bold
  716.     mov    cl,4
  717.     shr    al,cl            ; get background colors
  718.     mov    gbcol,al        ; set graphics background color    
  719.     mov    ah,15            ; get current screen mode
  720.     int    screen
  721.     cmp    al,mono            ; mono text mode (7)?
  722.     je    tekin1            ; e = yes
  723.     cmp    tekident,0        ; doing an ident request?
  724.     jne    tekin2            ; ne = yes, don't mess with screen
  725.     test    tekflg,1        ; are we active as Tek device now?
  726.     jz    tekin1            ; z = no
  727.     jmp    tekin13            ; yes, don't redo graphics setup
  728. tekin1:    mov    curmode,al        ; save mode here
  729.     mov    ah,3            ; get cursor position
  730.     xor    bh,bh            ; page 0
  731.     int    screen
  732.     mov    cursor,dx        ; save position
  733.     call    tsavescr        ; save text screen
  734.                     ; Presence tests.
  735. tekin2:    mov    graph_mode,cga        ; Color. Assume CGA
  736.     mov    segscn,segcga        ; assume cga screen segment
  737.     mov    gpage,0            ; graphics page 0 but no page 1
  738.     mov    putc,offset gputc    ; CGA character display routine
  739.     mov    gcplot,offset gcgen    ; General character plot routine
  740.     mov    gfplot,offset bpltcga    ; CGA area fill routine
  741.     mov    psetup,offset psetupc    ; CGA plot setup routine
  742.     mov    plotptr,offset pltcga    ; CGA dot plot routine
  743.     mov    pincy,offset pincyc    ; CGA inc y routine
  744.     mov    xmult,5            ; CGA. Scale TEK to PC by 640/1024
  745.     mov    xdiv,8            ;  so that 0-1023 converts to 0-639
  746.     mov    xmax,640-8        ; x-coord of rightmost character
  747.     mov    ymult,10        ; vertical scale for IBM is 200/780
  748.     mov    ydiv,39            ;
  749.     mov    ybot,199        ; Bottom of screen is Y=199
  750.     mov    al,tekgraf        ; user video board specification
  751.     cmp    al,0            ; auto-sensing?
  752.     jne    tekin2d            ; ne = no
  753.     jmp    tekin2c            ; yes (default)
  754. tekin2d:cmp    al,1            ; user wants CGA?
  755.     jne    tekin2a            ; ne = no
  756.     call    crossini        ; preset crosshairs for new screen
  757.     jmp    tekin13            ; do CGA
  758. tekin2a:cmp    al,4            ; user wants Hercules?
  759.     jne    tekin2b            ; ne = no
  760.     jmp    tekin8            ; do Hercules
  761. tekin2b:cmp    al,5            ; user wants AT&T style?
  762.     jne    tekinwy            ; ne = no
  763.     jmp    tekin7            ; do AT&T kind
  764.                     ; Wyse-700
  765. tekinwy:cmp    al,8            ; user wants Wyse-700 1024*780 ?
  766.     jne    tekinw0            ; ne = no
  767.     call    chkwyse            ; presence test
  768.     jc    tekinwf            ; c = failed
  769.     mov    xmax,1024-8        ; x-coord of rightmost character
  770.     mov    ybot,779        ; Bottom of screen is Y=780
  771.     mov    xmult,1            ; Wyse. Scale TEK to PC by 1024/1024
  772.     mov    xdiv,1            ;  so that 0-1023 converts to 0-1023
  773.     mov    ymult,1            ; vertical scale is 780/780
  774.     mov    ydiv,1            ;
  775.     jmp    short tekinw2        ;
  776. tekinw0:cmp    al,7            ; user wants Wyse-700 1280*780 ?
  777.     jne    tekinw1            ; ne = no
  778.     call    chkwyse            ; presence test
  779.     jc    tekinwf            ; c = failed
  780.     mov    xmax,1280-8        ; x-coord of rightmost character
  781.     mov    ybot,779        ; Bottom of screen is Y=800
  782.     mov    xmult,10        ; Wyse. Scale TEK to PC by 1280/1024
  783.     mov    xdiv,8            ;  so that 0-1023 converts to 0-1279
  784.     mov    ymult,1            ; vertical scale is 780/780
  785.     mov    ydiv,1            ;
  786.     jmp    short tekinw2        ;
  787. tekinwf:jmp    tekin2c            ; failure jump point
  788. tekinw1:cmp    al,6            ; user wants Wyse-700 1280*800 ?
  789.     jne    tekin2c            ; no = no
  790.     call    chkwyse            ; presence test
  791.     jc    tekinwf            ; c = failed
  792.     mov    xmax,1280-8        ; x-coord of rightmost character
  793.     mov    ybot,799        ; Bottom of screen is Y=800
  794.     mov    xmult,10        ; Wyse. Scale TEK to PC by 1280/1024
  795.     mov    xdiv,8            ;  so that 0-1023 converts to 0-1279
  796.     mov    ymult,40        ; vertical scale for IBM is 800/780
  797.     mov    ydiv,39            ;  so scale those 20 pixels more
  798. tekinw2:mov    graph_mode,wyse700    ; Assume Wyse Graphics
  799.     mov    segscn,segwyse        ; assume wyse screen segment
  800.     mov    gpage,0            ; only one graphics page 0
  801.     mov    putc,offset gputc    ; CGA character display routine
  802.     mov    gcplot,offset gcgen    ; CGA character plot routine
  803.     mov    psetup,offset psetupw    ; Wyse plot setup routine
  804.     mov    plotptr,offset pltcga    ; CGA dot plot routine
  805.     mov    pincy,offset pincyw    ; Wyse inc y routine
  806.     jmp    tekin13            ; do Wyse
  807.                     ; do auto-sensing of display board
  808.                     ; test for EGA
  809. tekin2c:mov    ax,1200H        ; EGA: Bios alternate select
  810.     mov    bl,10H                  ; Ask for EGA info
  811.     mov    bh,0ffH            ; Bad info, for testing
  812.     mov    cl,0fH            ; Reserved switch settings
  813.     int    screen            ; EGA, are you there?
  814.     and    cl,0fh            ; four lower switches
  815.     cmp    cl,0cH            ; Test reserved switch settings
  816.     jb    tekin3            ; b = ega present
  817.     jmp    tekin7            ; else no EGA, check other adapters
  818.  
  819. tekin3:    mov    ax,40h            ; check Bios 40:87h for ega being
  820.     mov    es,ax            ;  the active display adapter
  821.     test    byte ptr es:[87h],8    ; is ega active?
  822.     jz    tekin3a            ; z = yes
  823.     jmp    tekin7            ; ega is inactive, check others
  824. tekin3a:cmp    bl,1            ; is there 128KB on ega board?
  825.     jb    tekin4            ; b = less, so no screen saves
  826.     mov    gpage,1            ; >=128 KB, use two graphics pages
  827. tekin4:    mov    graph_mode,ega        ; assume high resolution color
  828.     cmp    cl,3            ; high resolution color?
  829.     je    tekin5            ; e = yes
  830.     cmp    cl,9            ; high resolution color?
  831.     je    tekin5            ; e = yes
  832.     mov    graph_mode,monoega    ; assume mono monitor on ega board
  833.     test    bh,1            ; ega mono mode in effect?
  834.      jnz    tekin5            ; nz = yes
  835.     mov    graph_mode,colorega    ; say ordinary cga on ega board, 64KB
  836.     mov    gpage,1            ; is enough memory with 200 scan lines
  837.     jmp    short tekin5a        ; use current cga parameters
  838. tekin5:    mov    ybot,349        ; text screen bottom is 349 on EGA
  839.     mov    ymult,35        ;
  840.     mov    ydiv,78            ; scale y by 350/780
  841. tekin5a:mov    segscn,segega        ; use ega screen segment
  842.     mov    psetup,offset psetupe    ; plot setup routine
  843.     mov    plotptr,offset pltega    ; ega dot plot routine
  844.     mov    gfplot,offset bpltega    ; ega area fill routine
  845.     mov    pincy,offset pincye    ; inc y routine
  846.     mov    putc,offset gputc    ; character display routine
  847.     mov    gcplot,offset gcega    ; EGA character plot routine
  848.     call    crossini        ; preset crosshairs for new screen
  849.     jmp    tekin13            ; end of EGA part, do VGA tests below
  850.  
  851. tekin7:    mov    ax,0fc00h        ; Olivetti/AT&T 6300, check rom id
  852.     mov    es,ax
  853.     mov    di,0            ; start here
  854.     mov    graph_mode,olivetti    ; Olivetti
  855.     mov    cx,attllen        ; length of logo
  856.     mov    si,offset ATTLOGO    ; master string
  857.     repe    cmpsb            ; do a match
  858.     je    tekin7c            ; e = a match
  859.     mov    di,0050h        ; look here too
  860.     mov    si,offset ATTLOGO
  861.     mov    cx,attllen
  862.     repe    cmpsb
  863.     je    tekin7c            ; e = a match
  864.     mov    di,2014h        ; and look here
  865.     mov    si,offset ATTLOGO
  866.     mov    cx,attllen
  867.     repe    cmpsb            ; do a match
  868.     je    tekin7c            ; e = a match, else try other types
  869. tekin7a:mov    graph_mode,toshiba
  870.     mov    ax,0f000h        ; Check for Toshiba T3100, rom scan
  871.     mov    es,ax
  872.     mov    di,0014h        ; start here
  873.     mov    si,offset TOSHLOGO    ; master string
  874.     mov    cx,toshlen        ; length
  875.     repe    cmpsb            ; do a match
  876.     je    tekin7c            ; e = a match, else try other types
  877. tekin7b:mov    graph_mode,vaxmate    ; DEC VAXmate II
  878.     mov    ax,0f000h        ; Check for VAXmate II rom signature
  879.     mov    es,ax
  880.     mov    di,0e000h        ; start here
  881.     mov    si,offset DECLOGO    ; master string
  882.     mov    cx,declen        ; length
  883.     repe    cmpsb            ; do a match
  884.     jne    tekin7d            ; ne = mismatch, try other types
  885.  
  886.                     ; Olivetti/AT&T, Toshiba, VAXmate
  887. tekin7c:mov    gpage,0            ; only page 0 with 640 by 400 mode
  888.     mov    segscn,segcga        ; use cga screen segment (0b800h)
  889.     mov    psetup,offset psetupo    ; plot setup routine
  890.     mov    plotptr,offset pltcga    ; cga dot plot routine
  891.     mov    gfplot,offset bpltcga    ; area fill plot routine
  892.     mov    pincy,offset pincyh    ; inc y routine (Herc style addresses)
  893.     mov    putc,offset gputc    ; character display routine
  894.     mov    gcplot,offset gcgen    ; General character plot routine
  895.     mov    ybot,399        ; bottom of screen is y = 399
  896.     mov    ymult,20        ; vertical scale = 400/780
  897.     mov    ydiv,39            ; same as cga setup
  898.     call    crossini        ; preset crosshairs for new screen
  899.     jmp    tekin13
  900.  
  901. tekin7d:cmp    curmode,mono        ; mono text mode?
  902.     je    tekin8            ; e = yes
  903.     jmp    tekin11            ; ne = no, try cga
  904.                     ; test for Hercules
  905. tekin8:    call    tscrseg            ; get screen segment, test Environment
  906.     cmp    tv_mode,0        ; Environment active?
  907.     je    tekin8a            ; e = no, ok to test for Hercules
  908.     jmp    tekin10            ; don't do Herc mode, do Mono
  909. tekin8a:mov    dx,hstatus        ; Herc status port
  910.     in    al,dx            ; read it
  911.     mov    bl,al            ; save here
  912.     and    bl,80h            ; remember retrace bit
  913.     mov    cx,0ffffh        ; do many times (for fast machines)
  914. tekin8b:mov    dx,hstatus        ; check status port
  915.     in    al,dx
  916.     and    al,80h            ; select bit
  917.     jmp    $+2            ; use a little time
  918.     cmp    bl,al            ; did it change?
  919.     loope    tekin8b            ; test again if not
  920.     je    tekin10            ; e = no change in bit, not Herc
  921.     mov    graph_mode,hercules    ; say have Herc board
  922.     mov    segscn,seghga        ; assume hga screen segment
  923.     mov    putc,offset gputc    ; character display routine
  924.     mov    gcplot,offset gcgen    ; general character plot routine
  925.     mov    gfplot,offset bpltcga    ; area fill plot routine
  926.     mov    psetup,offset psetuph    ; plot setup routine to use
  927.     mov    plotptr,offset pltcga    ; use cga dot plot routine for Herc
  928.     mov    pincy,offset pincyh    ; inc y routine
  929.     mov    xmult,45        ; Scale TEK to Hercules by 720/1024
  930.     mov    xdiv,64            ;  so that 0-1023 converts to 0-719
  931.     mov    xmax,720-8        ; x-coord of rightmost character
  932.     mov    ymult,87        ; vertical scale for Hercules is
  933.     mov    ydiv,195        ;  348/780
  934.     mov    ybot,347        ; bottom of screen is y = 347
  935.     mov    ax,seghga        ; segment of Herc video display
  936.     mov    es,ax
  937.     mov    al,es:[8000h]        ; read original contents, page 1
  938.     not    byte ptr es:[8000h]    ; write new pattern
  939.     mov    ah,es:[8000h]        ; read back
  940.     not    byte ptr es:[8000h]    ; restore original contents
  941.     not    ah            ; invert this too
  942.     cmp    ah,al            ; same (memory present?)
  943.     jne    tekin9            ; ne = not same, no memory there
  944.     mov    gpage,1            ; say two pages of display memory
  945. tekin9:    call    crossini        ; preset crosshairs
  946.     jmp    tekin13
  947.                     ; set to MONO
  948. tekin10:mov    graph_mode,mono        ; force monochrome adapter text
  949.     mov    segscn,segmono        ; assume mono screen segment
  950.     call    tscrseg            ; Environments: get virtual screen
  951.     mov    segscn,ax        ;  seg returned in ax and es:di
  952.     mov    gpage,0
  953.     mov    putc,offset mputc    ; character display routine
  954.     mov    psetup,offset psetupm    ; plot setup routine to use
  955.     mov    gfplot,offset bpltmon    ; area fill plot routine
  956.     mov    plotptr,offset pltmon    ; use hga dot plot routine
  957.     mov    pincy,offset pincym    ; inc y routine
  958.     mov    xmult,5            ; Scale TEK to mono by 640/1024
  959.     mov    xdiv,8            ;  so that 0-1023 converts to 0-639
  960.     mov    xmax,640-8        ; x-coord of rightmost character
  961.     mov    ymult,10        ; vertical scale for mono is 200/780
  962.     mov    ydiv,39
  963.     mov    ybot,200        ; bottom of screen is y = 200 for Bios
  964.     call    crossini        ; preset crosshairs for new screen
  965.     jmp    tekin13            ; Uses TEXT mode, for safety
  966.  
  967.                     ; test for CGA
  968. tekin11:mov    graph_mode,cga        ; set CGA high resolution graphics
  969.     mov    segscn,segcga        ; CGA screen segment
  970.     call    crossini        ; preset crosshairs for new screen
  971.     jmp    tekin13
  972.  
  973.                     ; Set Graphics mode
  974. tekin13:cmp    graph_mode,wyse700    ; Wyse ?
  975.     jne    tekin13a        ; ne = no
  976.     call    wygraf            ; set Wyse graphics mode, clear regen
  977.     jmp    short tekin16        ; restore screen
  978. tekin13a:cmp    graph_mode,hercules    ; Hercules?
  979.     jne    tekin14            ; ne = no
  980.     cmp    tekident,0        ; just identifying?
  981.     jne    tekin16            ; ne = yes
  982.     call    hgraf            ; set Herc graphics mode, clear regen
  983.     or    tekflg,1        ; say doing Tekmode
  984.     jmp    short tekin16        ; restore screen
  985. tekin14:mov    ah,0            ; set screen mode
  986.     mov    al,graph_mode        ;  to this screen mode
  987.     cmp    tekgraf,3        ; user wants "VGA" modes (640x480)?
  988.     jne    tekin14a        ; ne = no
  989.     cmp    al,monoega        ; yes, allow high resolution stuff?
  990.     jb    tekin14a        ; b = no
  991.     cmp    al,ega            ; ditto
  992.     ja    tekin14a        ; a = no
  993.     add    al,2            ; use modes 17(b/w) and 18(10)(color)
  994.     mov    ybot,479        ; text screen bottom is 479 on VGA
  995.     mov    ymult,48
  996. tekin14a:cmp    tekident,0        ; just identifying screen size etc?
  997.     jne    tekin16            ; ne = yes, do not invoke graphics
  998.     cmp    gpage,0            ; only page 0 available?
  999.     je    tekin15            ; e = yes, and watch for Bios errors
  1000.     cmp    inited,0        ; first time through?
  1001.     je    tekin15            ; e = yes, clear the page of old junk
  1002.     or    al,80h            ; save regen buffer (save area too)
  1003. tekin15:int    screen            ; Bios Set Mode.
  1004.     or    tekflg,1        ; say doing Tekmode
  1005.  
  1006. tekin16:cmp    tekident,0        ; just identifying?
  1007.     jne    tekin16a        ; ne = yes
  1008.     cmp    inited,0        ; inited yet?
  1009.     jne    tekin19            ; ne = yes, restore screen
  1010.     mov    ttstate,offset tektxt    ; do displayable text
  1011.     mov    prestate,offset tektxt    ; set a previous state of text
  1012.     mov    inited,1        ; say we have initialized
  1013. tekin16a:mov    si,offset mondef    ; default monochrome colors
  1014.     cmp    plotptr,offset pltcga    ; using CGA style graphics?
  1015.     je    tekin17            ; e = yes
  1016.     cmp    graph_mode,mono        ; pure mono text system?
  1017.     je    tekin17            ; e = yes
  1018.     cmp    graph_mode,monoega    ; ega, but monochrome?
  1019.     je    tekin17            ; e = no
  1020.     mov    si,offset coldef    ; use color palette
  1021. tekin17:mov    al,[si+7]        ; foreground color = palette 7
  1022.     mov    gfcol,al
  1023.     mov    al,[si]            ; background color = palette 0
  1024.     mov    gbcol,al
  1025.     mov    cx,16
  1026.     mov    di,offset colpal    ; VT340 active color palette
  1027.     push    es
  1028.     push    ds
  1029.     pop    es
  1030.     cld
  1031.     rep    movsb            ; reinit palette entries
  1032.     pop    es
  1033.     call    fixcolor        ; correct color mapping for some bds
  1034.     mov    al,gfcol
  1035.     mov    tfcol,al        ; remember current coloring
  1036.     mov    al,gbcol
  1037.     mov    tbcol,al
  1038.     cmp    tekident,0        ; just identifying?
  1039.     jne    tekin20            ; ne = yes
  1040.     call    tekcls            ; clear screen, for ega coloring
  1041.     jmp    short tekin20
  1042. tekin19:call    tekrest            ; restore old graphics screen
  1043.     mov    al,tfcol        ; and coloring
  1044.     mov    gfcol,al
  1045.     mov    al,tbcol
  1046.     mov    gbcol,al
  1047. tekin20:mov    ax,250
  1048.     call    tekwait            ; 250 ms wait for display adapter
  1049.     mov    ax,flow            ; get flow control word
  1050.     xchg    ah,al            ; get xon into al
  1051.     cmp    al,0            ; able to send xon?
  1052.     je    tekin21            ; e = no
  1053.     call    outmodem        ; tell host xon
  1054. tekin21:mov    al,chcontrol        ; opaque/transparent char writing
  1055.     mov    bscontrol,al        ; set destructive BS control
  1056.     mov    spcontrol,al        ; set destructive SPACE control
  1057.     mov    tekident,0
  1058.     clc                ; clear carry for success
  1059.     pop    es
  1060.     pop    di
  1061.     pop    si
  1062.     pop    dx
  1063.     pop    cx
  1064.     pop    bx
  1065.     pop    ax
  1066.     ret
  1067. tekini    endp
  1068.  
  1069. TEKRINT proc    far            ; Tek reinitialization entry point
  1070.     call    dword ptr endptr    ; exit cleanly if alread in Tek mode
  1071.     mov    inited,0        ; do complete reinitialization
  1072.     mov    tekflg,0
  1073.     call    tekini
  1074.     ret
  1075. TEKRINT    endp
  1076.  
  1077. ; End TEK emulation, recover previous screen
  1078. TEKEND    proc    far
  1079.     mov    ttstate,offset tektxt    ; set an initial state
  1080.     mov    prestate,offset tektxt    ; and a previous state
  1081.     test    tekflg,1        ; running as a Tek terminal now?
  1082.     jnz    teknd1            ; nz = yes
  1083.     mov    tekflg,0        ; returning to text emulator
  1084.     ret                ; else return as is
  1085. teknd1:    call    teksave            ; save graphics screen to page 1
  1086.     cmp    graph_mode,hercules    ; Hercules?
  1087.     jne    teknd2            ; ne = no
  1088.     call    htext            ; yes then set up Hercules text mode
  1089. teknd2:    mov    ah,0            ; set video mode
  1090.     mov    al,curmode        ; restore previous screen mode
  1091.     int    screen            ; revert to text screen
  1092.     call    trestscr        ; restore text screen
  1093.     mov    dx,cursor        ; saved cursor position
  1094.     mov    bh,0            ; page 0
  1095.     mov    ah,2            ; set cursor
  1096.     int    screen
  1097.     mov    tekflg,0        ; returning to text emulator
  1098.     mov    lastc,0
  1099.     mov    bypass,0        ; reset bypass condition
  1100.     mov    visible,0        ; next move is invisible
  1101.     clc
  1102.     ret
  1103. TEKEND    ENDP
  1104.  
  1105.  
  1106. ;Terminal emulation. Enter with received character in AL.
  1107. TEKEMU    proc    far            ; main emulator
  1108.     call    tektt            ; local emulator routine
  1109.     ret
  1110. TEKEMU    endp
  1111.  
  1112. tektt    proc    near
  1113.     test    tekflg,1        ; running as a Tek device?
  1114.     jnz    tektt1            ; nz = yes
  1115.     push    ax
  1116.     call    tekini            ; init now
  1117.     pop    ax
  1118.     mov    ttstate,offset tektxt    ; initial state
  1119.     mov    prestate,offset tektxt    ; set a previous state of text
  1120.     jnc    tektt1            ; nc = succeeded
  1121.     ret                ; else failed to init, just return
  1122. tektt1:    test    al,80h            ; high bit set?
  1123.     jz    tektt1a            ; z = no
  1124.     cmp    al,9fh            ; in range for C1 controls?
  1125.     ja    tektt1a            ; a = no
  1126.     push    ax            ; save the char
  1127.     mov    al,escape        ; make 7-bit control version
  1128.     call    tektt2            ; act on escape
  1129.     pop    ax
  1130.     sub    al,40h            ; get second char of 7-bit control
  1131.  
  1132. tektt1a:and    al,7fh            ; force Tek chars to be 7 bits
  1133.     or    al,al            ; NUL char?
  1134.     jnz    tektt2            ; nz = no
  1135.     ret                ; yes, ignore it (before logging)
  1136. tektt2:    test    yflags,capt        ; capturing output?
  1137.     jz    tektt4            ; z = no, forget this part
  1138.     push    ax            ; save char
  1139.     call    tcptchr            ; give it captured character
  1140.     pop    ax            ; restore character and keep going
  1141. tektt4:    test    yflags,trnctl        ; debug? if so use tty mode
  1142.     jz    tektt5            ; z = no
  1143.     cmp    al,DEL            ; DEL char?
  1144.     jne    tektt4a            ; ne = no
  1145.     mov    al,5eh            ; make DEL a caret query mark
  1146.     call    outscrn
  1147.     mov    al,3fh            ; the query mark
  1148.     call    outscrn
  1149.     ret
  1150. tektt4a:cmp    al,' '            ; control char?
  1151.     jae    tektt4b            ; ne = no
  1152.     push    ax
  1153.     mov    al,5eh            ; caret
  1154.     call    outscrn
  1155.     pop    ax
  1156.     add    al,'A'-1        ; make char printable
  1157. tektt4b:call    outscrn
  1158.     ret
  1159.  
  1160. tektt5:    call    ttstate            ; do current state
  1161.     ret
  1162. tektt    endp
  1163.      
  1164. TEKTXT    proc    near            ; Dispatch on text characters
  1165.     mov    ttstate,offset tektxt    ; this is our state
  1166.     cmp    al,DEL            ; RUBOUT?
  1167.     jne    tektx1            ; ne = no
  1168.     mov    al,bs            ; make BS
  1169.     jmp    short tektx7
  1170. tektx1:    cmp    al,CR            ; carriage return (^M)?
  1171.     je    tektx9            ; e = yes
  1172.     cmp    al,LF            ; line feed (^J)?
  1173.     je    tektx9            ; e = yes
  1174.     cmp    al,FF            ; form feed (^L)?
  1175.     jne    tektx4            ; ne = no
  1176.     call    tekcls            ; clear the screen
  1177.     ret
  1178. tektx4:    cmp    al,VT            ; vertical tab (^K)?
  1179.     je    tektx7
  1180.     cmp    al,bell            ; bell (^G)?
  1181.     jne    tektx5            ; ne = no
  1182.     call    tekbeep
  1183.     mov    bypass,0        ; clear GIN mode bypass condition
  1184.     ret
  1185. tektx5:    cmp    al,tab            ; horizontal tab (^I)?
  1186.     je    tektx7            ; e = yes
  1187.     cmp    al,BS            ; backspace (^H)?
  1188.     je    tektx7            ; e = yes
  1189.     cmp    al,' '            ; control char?
  1190.     jae    tektx7            ; ae = no
  1191.     jmp    tekctl            ; process control char
  1192. tektx7:    cmp    bypass,0        ; bypass mode off?
  1193.     jne    tektx8            ; ne = no, it's on so skip display
  1194.     call    outscrn            ; output character to the screen
  1195. tektx8:    ret
  1196. tektx9:    mov    bypass,0        ; clear GIN mode bypass condition
  1197.     jmp    short tektx7
  1198. TEKTXT    endp
  1199.  
  1200.  
  1201. tekctl    proc    near            ; Control characters:
  1202.     cmp    al,GS            ; Line plot command?
  1203.     jne    tekctl1            ; ne = no
  1204.     mov    visible,0        ; next move is invisible
  1205.     and    status,not txtmode    ; set status report byte
  1206.     mov    ttstate,offset tekline    ; expect coordinates next
  1207.     jmp    tekctl7
  1208. tekctl1:cmp    al,RS            ; Incremental dot command?
  1209.     jne    tekctl2            ; ne = no
  1210.     and    status,not txtmode    ; set status report
  1211.     mov    ttstate,offset tekrlin    ; expect pen command next
  1212.     jmp    tekctl7
  1213. tekctl2:cmp    al,FS            ; Point plot command?
  1214.     jne    tekctl3            ; ne = no
  1215.     mov    visible,0        ; next move is invisible
  1216.     and    status,not txtmode    ; set status report byte
  1217.     mov    ttstate,offset tekpnt
  1218.     jmp    tekctl7
  1219. tekctl3:cmp    al,US            ; assert text mode? [bjh]
  1220.     jne    tekctl4            ; ne = no
  1221.     or    status,txtmode        ; set status report byte
  1222.     mov    ttstate,offset tektxt    ; go to TEKTXT next time
  1223.     mov    bypass,0        ; reset bypass condition
  1224.     mov    visible,0        ; next move is invisible
  1225.     jmp    tekctl7
  1226. tekctl4:cmp    al,ESCAPE        ; Escape?
  1227.     jne    tekctl5            ; ne = no
  1228.     or    status,txtmode        ; set status report byte
  1229.     cmp    ttstate,offset tekesc    ; already in escape state?
  1230.     je    tekctl7            ; e = yes, nest no further
  1231.     push    ttstate            ; current state
  1232.     pop    prestate        ; save here as previous state
  1233.     mov    ttstate,offset tekesc    ; next state parses escapes
  1234.     ret
  1235.  
  1236. tekctl5:cmp    al,CAN            ; Control X? (exits Tek sub mode)
  1237.     jne    tekctl7            ; ne = no, stay in current state
  1238.     mov    ttstate,offset tektxt    ; back to text mode
  1239.     cmp    flags.vtflg,tttek    ; main Tek emulator?
  1240.     je    tekctl6            ; e = yes, ignore the ^X
  1241.     call    tekend            ; else exit sub mode
  1242.     mov    visible,0        ; next move is invisible
  1243. tekctl6:mov    prestate,offset tektxt    ; make previous state text
  1244. tekctl7:ret
  1245. tekctl    endp
  1246.  
  1247. TEKESC    proc    near            ; Process ESC <following text>
  1248.     mov    bypass,0        ; clear GIN mode bypass condition
  1249.     mov    ttstate,offset tekesc    ; in case get here from msz file
  1250.     cmp    inited,0        ; inited yet? (msz call)
  1251.     jne    tekesc1            ; ne = yes
  1252.     call    tekini            ; init now
  1253.     mov    prestate,offset tektxt    ; set a previous state of text
  1254.     jnc    tekesc1            ; nc = succeeded
  1255.     ret                ; else failed to init, just return
  1256.     
  1257. tekesc1:cmp    al,20h            ; in intermediates, column 2?
  1258.     jb    tekesc3            ; b = no
  1259.     cmp    al,2fh
  1260.     ja    tekesc3            ; a = no
  1261.     mov    ttstate,offset tekesc1    ; stay in this state while intermeds
  1262.     mov    bx,ninter        ; number of intermediates
  1263.     cmp    bx,maxinter        ; done enough already?
  1264.     jae    tekesc2            ; ae = yes, ignore the excess
  1265.     mov    inter[bx],al        ; store this one
  1266.     inc    ninter            ; one more
  1267.     cmp    inter,'/'        ; HDS2000/3000 Final char?
  1268.     je    tekesc3            ; e = yes, process specially like '['
  1269. tekesc2:ret                ; get more input
  1270.     
  1271.                     ; Final char is in AL, dispatch on it
  1272. tekesc3:mov    ttstate,offset tektxt    ; set new state
  1273.     mov    esctype,al        ; save kind of escape sequence
  1274.     mov    bx,offset esctab    ; ESC dispatch table
  1275.     call    atdispat        ; dispatch on AL
  1276.     ret
  1277. TEKESC    endp    
  1278.  
  1279. tekeseq    proc    near            ; process Escape and Device Contrl seq
  1280.     call    tparstart        ; init escape sequence parser
  1281.     mov    ttstate,offset escparse    ; do parsing next
  1282.     ret
  1283. tekeseq    endp
  1284.  
  1285. ; State for gathering text to feed escape sequence parser
  1286. escparse proc    near
  1287.     cmp    al,' '            ; embedded control code?
  1288.     jb    escpar2            ; b = yes, process now
  1289.     call    tparser            ; far call, to call real parser
  1290.     jnc    escpar1            ; nc = success
  1291.     push    prestate        ; recover previous state
  1292.     pop    ttstate
  1293.     stc
  1294. escpar1:ret
  1295. escpar2:call    tekctl            ; process embedded control code
  1296.     push    prestate        ; get previous state
  1297.     pop    ttstate            ; restore it
  1298.     ret
  1299. escparse endp
  1300.  
  1301. ; Escape sequence parser completion routine
  1302. ; AL has Final character of escape sequence
  1303. XPARDONE PROC    FAR            ; called by tpardone when done
  1304.     cmp    esctype,'['        ; ansi escape sequence (ESC [)?
  1305.     jne    xpardo3            ; ne = no
  1306.     mov    bx,offset anstab    ; ANSI ESC [ table
  1307.     call    atdispat        ; dispatch on Final char in AL
  1308.     jmp    short xpardo5
  1309.  
  1310. xpardo3:cmp    esctype,'/'        ; HDS escape sequence (ESC /)?
  1311.     jne    xpardo4            ; ne = no
  1312.     call    hdsesc            ; analyze
  1313.     jmp    short xpardo5
  1314.  
  1315. xpardo4:cmp    esctype,'P'        ; DCS introducer?
  1316.     jne    xpardo5            ; ne = no
  1317.     call    tekdcs            ; grab parameters etc, prep strings
  1318.     ret
  1319.  
  1320. xpardo5:push    prestate        ; recover previous state
  1321.     pop    ttstate
  1322.     ret
  1323. XPARDONE ENDP
  1324.                 ; ESC <char> action routines
  1325.                 ; exit each by putting prestate into ttstate
  1326.  
  1327. tekenq    proc    near            ; ESC-^E Enquiry for cursor position
  1328.     mov    bypass,1        ; set bypass mode
  1329.     call    sendstat        ; send status
  1330.     push    prestate        ; get previous state
  1331.     pop    ttstate            ; restore it
  1332.     ret
  1333. tekenq    endp
  1334.  
  1335. tekcan    proc    near            ; ESC ^X
  1336.     push    prestate        ; get previous state
  1337.     pop    ttstate            ; restore it
  1338.     jmp    tekctl            ; process in controls section
  1339. tekcan    endp
  1340.  
  1341. tekgin    proc    near            ; ESC-^Z Enter GIN mode
  1342.     cmp    graph_mode,mono        ; Monochrome text mode?
  1343.     je    tekgin1            ; e = yes, no crosshairs in text mode
  1344.     mov    bypass,1        ; turn on GIN mode bypass conditon
  1345.     call    croshair        ; activate the cross-hairs
  1346.     jmp    short tekgin2
  1347. tekgin1:call    tekbeep            ; tell the user we are unhappy
  1348. tekgin2:push    prestate        ; get previous state
  1349.     pop    ttstate            ; restore it
  1350.     ret
  1351. tekgin    endp
  1352.  
  1353. tekqury    proc    near            ; query mark (ESC ? means DEL)
  1354.     mov    al,DEL            ; replace with DEL code
  1355.     push    prestate        ; get previous state
  1356.     pop    ttstate            ; restore it
  1357.     ret
  1358. tekqury    endp
  1359.  
  1360. tekfill    proc    near            ; Fill series ESC @ .. ESC M
  1361.     sub    al,'@'            ; remove bias
  1362.     mov    bl,al
  1363.     xor    bh,bh
  1364.     shl    bx,1            ; make a word index
  1365.     mov    bx,fillist[bx]        ; get pointer to the pattern from list
  1366.     mov    fillptr,bx        ; assign this pattern pointer
  1367.     push    prestate        ; get previous state
  1368.     pop    ttstate            ; restore it
  1369.     ret
  1370. tekfill    endp
  1371.  
  1372. teklpat    proc    near            ; ESC accent grave line pattern series
  1373.     cmp    al,'e'            ; accent ... lowercase e?
  1374.     jbe    teklpa1            ; be = yes
  1375.     sub    al,'x'-'f'        ; user sets,map x to f, y to g, z to h
  1376. teklpa1:push    bx
  1377.     mov    bl,al
  1378.     sub    bl,accent        ; remove bias
  1379.     cmp    bl,8            ; nine patterns, ignore others
  1380.     ja    teklpa2            ; a = illegal
  1381.     xor    bh,bh
  1382.     shl    bx,1            ; make this a word index
  1383.     mov    bx,linetab[bx]        ; get line pattern word
  1384.     mov    linepat,bx        ; save in active word
  1385. teklpa2:pop    bx            ; return to previous mode
  1386.     push    prestate        ; get previous state
  1387.     pop    ttstate            ; restore it
  1388.     ret
  1389. teklpat    endp
  1390.  
  1391. ; Detect exit Tek submode command ESC [ ? 38 l  from VT340's
  1392. escexit    proc    near
  1393.     cmp    lparam,'?'        ; possible "ESC [ ? 38 l"?
  1394.     jne    escex2            ; ne = no
  1395.     cmp    nparam,1        ; just one numeric parameter?
  1396.     jne    escex2            ; ne = no
  1397.     cmp    al,'l'            ; ESC [ ? Pn l?
  1398.     jne    escex4            ; ne = no, try 'h'
  1399.     cmp    param,38        ; correct value?
  1400.     jne    escex3            ; ne = no
  1401.     cmp    flags.vtflg,tttek    ; are we a full Tek terminal now?
  1402.     je    escex1            ; e = yes, stay that way
  1403.     call    dword ptr endptr    ; call far tekend
  1404.     ret
  1405. escex1:    mov    ttstate,offset tektxt
  1406.     mov    al,CAN            ; simulate arrival of Control-X
  1407.     jmp    tektxt            ; process char as text
  1408. escex2:    ret
  1409. escex3:    cmp    param,34        ; ESC [ ? 34 l?
  1410.     jne    escex2            ; ne = no
  1411.     call    tekend            ; play save and restore text mode
  1412.     xor    ax,ax            ; tell tekmac it's a Reset flavor
  1413.     call    tekmac            ; returns only if successful
  1414.     ret
  1415. escex4:    cmp    al,'h'            ; ESC ... l?
  1416.     jne    escex3            ; ne = no
  1417.     cmp    param,34        ; ESC [ ? 34 h?
  1418.     jne    escex2            ; ne = no
  1419.     call    tekend            ; play save and restore text mode
  1420.     mov    ax,1            ; tell tekmac it's a Set flavor
  1421.     call    tekmac            ; returns only if successful
  1422.     ret
  1423. escexit    endp
  1424.  
  1425. ; Human Data Systems 2000 style escape sequences (ESC / params Final)
  1426. hdsesc    proc    near
  1427.     cmp    al,'x'            ; draw an empty rectangle?
  1428.     jne    hdsesc0            ; ne = no
  1429.     call    rectdraw
  1430.     jmp    short hdsesc2a
  1431. hdsesc0:cmp    al,'y'            ; draw a filled rectangle?
  1432.     jne    hdsesc1            ; ne = no
  1433.     call    rectfil            ;do xhome,yhome,xwidth,yheight,pattern
  1434.     jmp    short hdsesc2a
  1435. hdsesc1:cmp    al,'z'            ; draw and fill rectangle?
  1436.     jne    hdsesc2            ; ne = no
  1437.     call    rectfil            ; do fill before border
  1438.     call    rectdraw        ; do border
  1439.     jmp    short hdsesc2a
  1440. hdsesc2:cmp    ninter,0        ; any intermediates?
  1441.     jne    hdsesc2a        ; ne = yes, failure
  1442.     cmp    lparam,0        ; letter parameter?
  1443.     jne    hdsesc2a        ; ne = yes, failure
  1444.     cmp    nparam,1        ; just zero or one numeric parameter?
  1445.     ja    hdsesc9            ; a = no
  1446.     cmp    al,'a'            ; user defined pattern?
  1447.     jb    hdsesc3            ; b = no
  1448.     cmp    al,'c'
  1449.     ja    hdsesc3            ; a = no
  1450.     sub    al,'a'            ; 'a' is first of three user patterns
  1451.     xor    ah,ah            ;  store as 'f,g,h' in the series
  1452.     mov    bx,ax
  1453.     shl    bx,1            ; make a word index
  1454.     mov    ax,param[0]        ; get the 16-bit pattern
  1455.     mov    linetab[bx+12],ax    ; store in user defined pattern
  1456. hdsesc2a:push    prestate        ; get previous state
  1457.     pop    ttstate            ; restore it
  1458.     ret
  1459.  
  1460. hdsesc3:cmp    al,'d'            ; "Data Level" (pixel ops)?
  1461.     jne    hdsesc4            ; ne = no
  1462.     mov    cx,param        ; get the parameter value
  1463.     mov    al,pixfor        ; assume foreground only ESC / 0 d
  1464.     cmp    cl,1            ; something else?
  1465.     jb    hdsesc3a        ; b = no
  1466.     mov    al,pixbak        ; assume background only ESC / 1 d
  1467.     cmp    cl,2            ; something else?
  1468.     jb    hdsesc3a        ; b = no
  1469.     mov    al,pixxor        ; assume XOR  ESC / 2 d
  1470.     cmp    cl,3            ; something else?
  1471.     jb    hdsesc3a        ; b = no
  1472.     ja    hdsesc3b        ; a = unknown, ignore
  1473.     mov    al,pixfor+pixbak    ; write both absolute  ESC / 3 d
  1474. hdsesc3a:mov    ccode,al        ; use as pixel op coding
  1475. hdsesc3b:push    prestate        ; get previous state
  1476.     pop    ttstate            ; restore it
  1477.     ret
  1478.  
  1479. hdsesc4:cmp    al,'h'            ; set space, backspace control?
  1480.     je    hdsesc4a        ; e = yes
  1481.     cmp    al,'l'            ; reset space, backspace control?
  1482.     jne    hdsesc9            ; ne = no
  1483.     xor    ah,ah            ; say resetting
  1484.     jmp    short hdsesc5
  1485. hdsesc4a:mov    ah,1            ; say setting
  1486. hdsesc5:cmp    param,2            ; space control?
  1487.     jne    hdsesc5a        ; ne = no
  1488.     mov    spcontrol,ah        ; reset (0) or set destructive SPACE
  1489.     push    prestate        ; get previous state
  1490.     pop    ttstate            ; restore it
  1491.     ret
  1492. hdsesc5a:cmp    param,9            ; destructive backspace?
  1493.     jne    hdsesc13        ; ne = no
  1494.     mov    bscontrol,ah        ; reset (0) or set destructive BS
  1495.  
  1496. hdsesc9:cmp    al,'C'            ; user defined fill pattern #1?
  1497.     jne    hdsesc10        ; ne = no
  1498.     mov    di,offset filpat13    ; storage area for user pattern #1
  1499.     jmp    short hdsesc11
  1500. hdsesc10:cmp    al,'D'            ; user defined fill pattern #2?
  1501.     jne    hdsesc11        ; ne = no
  1502.     mov    di,offset filpat14    ; storage area for user pattern #2
  1503. hdsesc11:mov    cx,8            ; do 8 paramters
  1504.     xor    bx,bx
  1505. hdsesc12:mov    ax,param[bx]        ; copy 8 bit fill pattern
  1506.     mov    [di],al            ; to array
  1507.     add    bx,2
  1508.     inc    di
  1509.     loop    hdsesc12
  1510. hdsesc13:push    prestate        ; get previous state
  1511.     pop    ttstate            ; restore it
  1512.     ret
  1513. hdsesc    endp
  1514.  
  1515. ; Analyze ESC [ Pn ; Pn m  color command    
  1516. ; where Pn = 30-37 foreground color, 40-47 background color, ANSI standard
  1517. ; Enter with escape sequence already parsed.
  1518. TEKCOL    proc    near
  1519.     push    si
  1520.     cld
  1521.     mov    si,offset param        ; parameters from parser
  1522.     mov    cx,nparam        ; number of parameters
  1523. tekco1:    jcxz    tekco5            ; z = none left
  1524.     lodsw                ; parameter to ax
  1525.     dec    cx
  1526.     or    ax,ax            ; 0, remove intensity, set b/w?
  1527.     jnz    tekco2            ; nz = no
  1528.     mov    tfcol,7            ; regular white
  1529.     mov    tbcol,0            ;  on black
  1530.     jmp    short tekco1
  1531.  
  1532. tekco2:    cmp    ax,1            ; intensity bit?
  1533.     jne    tekco3            ; ne = no
  1534.     or    tfcol,8            ; set foreground intensity
  1535.     jmp    short tekco1
  1536.     
  1537. tekco3:    cmp    ax,30            ; foreground series?
  1538.     jb    tekco1            ; b = no
  1539.     cmp    ax,37
  1540.     ja    tekco4            ; a = no
  1541.     sub    ax,30            ; remove bias
  1542.     push    bx
  1543.     mov    bl,al
  1544.     xor    bh,bh
  1545.     mov    al,byte ptr colortb[bx]    ; reverse coloring
  1546.     pop    bx
  1547.     and    tfcol,not (7)        ; retain intensity bit
  1548.     or    tfcol,al        ; remember foreground color
  1549.     jmp    short tekco1
  1550.  
  1551. tekco4:    cmp    ax,40
  1552.     jb    tekco1
  1553.     cmp    ax,47            ; legal value?
  1554.     ja    tekco1            ; a = no
  1555.     sub    al,40
  1556.     push    bx
  1557.     mov    bl,al
  1558.     xor    bh,bh
  1559.     mov    al,byte ptr colortb[bx]    ; reverse coloring
  1560.     pop    bx
  1561.     mov    tbcol,al        ; remember background color
  1562.     jmp    short tekco1
  1563.  
  1564. tekco5:    cmp    ninter,0        ; intermediates?
  1565.     jne    tekco7            ; ne = yes, no go
  1566.     cmp    lparam,0        ; letter parameter?
  1567.     jne    tekco7            ; ne = yes, no go
  1568.     cmp    nparam,0        ; number of ansi arguments, zero?
  1569.     ja    tekco6            ; a = no, got some
  1570.     mov    tbcol,0            ; none is same as 0, set b/w
  1571.     mov    tfcol,7
  1572. tekco6:    mov    al,tbcol        ; success, store coloring
  1573.     mov    gbcol,al        ; set background color
  1574.     mov    al,tfcol
  1575.     mov    gfcol,al        ; set foreground color
  1576.     call    fixcolor        ; do special ega corrections
  1577.     mov    al,gfcol        ; update these in case error
  1578.     mov    tfcol,al
  1579.     mov    colpal[7],al        ; foreground goes here
  1580.     mov    al,gbcol
  1581.     mov    tbcol,al
  1582.     mov    colpal[0],al        ; background goes here
  1583. tekco7:    pop    si
  1584.     clc
  1585.     ret
  1586. TEKCOL    endp
  1587.  
  1588. ; Revise screen color codes for ega boards with mono displays and limited
  1589. ; memory.
  1590. fixcolor proc    near
  1591.     cmp    graph_mode,ega        ; one of these ega modes?
  1592.     je    fixcol6            ; e = yes
  1593.     cmp    graph_mode,colorega
  1594.     je    fixcol6
  1595.     cmp    graph_mode,monoega
  1596.     je    fixcol6
  1597.     cmp    plotptr,offset pltcga    ; using CGA style graphics?
  1598.     jne    fixcol5            ; ne = no
  1599.     and    gfcol,7            ; strip intensity
  1600.     jmp    short fixcol6        ; keep colors different
  1601. fixcol5:ret                ; else ignore color corrections
  1602. fixcol6:mov    ah,gfcol
  1603.     mov    al,gbcol
  1604.     cmp    graph_mode,monoega    ; monochrome ega display?
  1605.     jne    fixcol3            ; ne = no
  1606.     test    al,7            ; bright backgound?
  1607.     jnz    fixcol1            ; nz = yes
  1608.     mov    ah,1            ; normal foreground
  1609.     test    gfcol,8            ; intensity on?
  1610.     jz    fixcol1            ; z = no
  1611.     mov    ah,5            ; say bright foreground
  1612. fixcol1:test    al,7            ; black backgound?
  1613.     jz    fixcol2            ; z = yes
  1614.     mov    al,1            ; regular video
  1615. fixcol2:cmp    ah,al            ; same color in both?
  1616.     jne    fixcol3            ; ne = no
  1617.     mov    ah,1            ; make foreground regular
  1618.     xor    al,al            ;  and background black
  1619. fixcol3:mov    gfcol,ah
  1620.     mov    gbcol,al
  1621.     cmp    gpage,0            ; minimal memory (64KB mono and ega)?
  1622.     ja    fixcol4            ; a = no, enough, else strange mapping
  1623.     mov    al,gfcol        ; fix coloring to map planes C0 to C1
  1624.     and    al,5            ; and C2 to C3 (as 0, 3, 0Ch, or 0Fh)
  1625.     mov    ah,al            ; make a copy
  1626.     shl    ah,1            ; duplicate planes C0, C2 in C1, C3
  1627.     or    al,ah            ; merge the bits
  1628.     mov    gfcol,al        ; store proper foreground color
  1629.     mov    al,gbcol        ; repeat for background color
  1630.     and    al,5
  1631.     mov    ah,al
  1632.     shl    ah,1
  1633.     or    al,ah
  1634.     mov    gbcol,al
  1635. fixcol4:ret
  1636. fixcolor endp
  1637.  
  1638. tekrid    proc    near            ; report Tek screen parameters
  1639.     cmp    lparam,'?'        ; possible "ESC [ ? 38 l"?
  1640.     jne    tekridx            ; ne = no
  1641.     cmp    nparam,1        ; just one numeric parameter?
  1642.     jne    tekridx            ; ne = no
  1643.     cmp    param,256        ; correct value?
  1644.     je    tekrid            ; e = yes
  1645. tekridx:ret
  1646. tekrid1:push    es            ; as ESC [ ? 256; height; len; #col n
  1647.     push    ds
  1648.     pop    es
  1649.     cld
  1650.     mov    di,offset tempname    ; a temp buffer
  1651.     mov    al,escape        ; report
  1652.     stosb
  1653.     mov    al,'['
  1654.     stosb
  1655.     mov    al,'?'
  1656.     stosb
  1657.     mov    ax,256
  1658.     call    dec2di            ; write ascii digits
  1659.     mov    al,';'
  1660.     stosb
  1661.     mov    ax,ybot            ; do height
  1662.     inc    ax
  1663.     cmp    graph_mode,mono        ; pure mono text system?
  1664.     jne    tekrid7a        ; ne = no
  1665.     mov    ax,24
  1666. tekrid7a:call    dec2di
  1667.     mov    al,';'            ; separator
  1668.     stosb
  1669.     mov    ax,xmax            ; width
  1670.     add    ax,8            ; in dots
  1671.     cmp    graph_mode,mono        ; pure mono text system?
  1672.     jne    tekrid7b        ; ne = no
  1673.     mov    ax,80
  1674. tekrid7b:call    dec2di
  1675.     mov    al,';'            ; separator
  1676.     stosb
  1677.     mov    al,'1'            ; screen colors, assume 1
  1678.     stosb
  1679.     cmp    plotptr,offset pltcga    ; using CGA style graphics?
  1680.     je    tekrid4            ; e = yes
  1681.     cmp    graph_mode,monoega    ; monochrome monitor on ega?
  1682.     je    tekrid4            ; e = yes
  1683.     cmp    graph_mode,mono        ; pure mono text system?
  1684.     jne    tekrid3
  1685.     mov    byte ptr [di-1],'0'    ; say zero colors
  1686.     jmp    short tekrid4
  1687. tekrid3:mov    al,'6'
  1688.     stosb                ; say 16
  1689. tekrid4:mov    al,'n'            ; end of string
  1690.     stosb
  1691.     call    outstrng        ; send the string
  1692.     pop    es
  1693.     ret
  1694. tekrid    endp
  1695.  
  1696. tekprpt    proc    near
  1697.     cmp    nparam,1        ; one or more numeric parameters?
  1698.     jb    tekrprx            ; b = no
  1699.     cmp    param,2            ; "CSI 2 $ u"?
  1700.     jne    tekrprx            ; ne = no
  1701.     cmp    inter,'$'        ; correct Intermediate?
  1702.     jne    tekrprx            ; ne = no
  1703.     call    dword ptr rptptr    ; invoke the palette report generator
  1704. tekrprx:ret
  1705. tekprpt    endp
  1706.  
  1707. tekrpt    proc    FAR            ; report VT340 color palette
  1708.     push    es            ; DECRQTSR(request), DECCTR(response)
  1709.     push    ds
  1710.     pop    es
  1711.     push    di
  1712.     push    bx
  1713.     cld
  1714.     mov    di,offset tempname    ; a temp buffer
  1715.     mov    al,escape        ; report
  1716.     stosb
  1717.     cmp    plotptr,offset pltcga    ; using CGA style graphics?
  1718.     je    tekrpt9            ; e = yes
  1719.     cmp    graph_mode,mono        ; pure mono text system?
  1720.     je    tekrpt9            ; e = yes
  1721.     cmp    graph_mode,monoega    ; monochrome monitor on ega?
  1722.     jne    tekrpt10        ; ne = no
  1723. tekrpt9:mov    ax,'0P'            ; b/w systems report DCS 0 $ s ST
  1724.     stosw
  1725.     mov    ax,'s$'
  1726.     stosw
  1727.     call    outstrng
  1728.     jmp    tekrpt8
  1729.  
  1730. tekrpt10:mov    ax,'2P'            ; color systems report DCS 2 $ s...ST
  1731.     stosw
  1732.     mov    ax,'s$'
  1733.     stosw                ; "ESC [ 2 $ s"
  1734.     call    outstrng        ; output this string
  1735.     mov    cx,16            ; number of palette registers to do
  1736.     xor    bx,bx            ; begin with color palette 0
  1737. tekrpt1:push    bx            ; save palette index
  1738.     push    cx            ; save loop counter
  1739.     mov    di,offset tempname    ; buffer
  1740.     mov    ax,bx            ; palette number
  1741.     call    dec2di            ; palette register, to buffer
  1742.     mov    ax,'2;'            ; ";2;" means sending RGB values
  1743.     stosw
  1744.     mov    al,';'
  1745.     stosb
  1746.     mov    ah,colpal[bx]        ; get palette iRGB
  1747.     mov    al,rgbbold/4        ; assume dark red for bold black
  1748.     cmp    ah,8            ; bold black?
  1749.     je    tekrpt2            ; e = yes
  1750.     xor    al,al
  1751.     test    ah,4            ; red?
  1752.     jz    tekrpt2            ; z = no
  1753.     mov    al,rgbbold/2        ; say red, 40%
  1754.     test    ah,8            ; bold?
  1755.     jz    tekrpt2            ; z = no
  1756.     mov    al,rgbbold        ; more if bold
  1757. tekrpt2:push    ax
  1758.     xor    ah,ah            ; clear high byte
  1759.     call    dec2di            ; store red
  1760.     pop    ax
  1761.     mov    al,';'            ; separator
  1762.     stosb
  1763.     mov    al,rgbbold/4        ; assume dark green for bold black
  1764.     cmp    ah,8            ; bold black?
  1765.     je    tekrpt4            ; e = yes
  1766.     xor    al,al
  1767.     test    ah,2            ; green?
  1768.     jz    tekrpt4            ; z = no
  1769.     mov    al,rgbbold/2        ; say green, 40%
  1770.     test    ah,8            ; bold?
  1771.     jz    tekrpt4            ; z = no
  1772.     mov    al,rgbbold        ; more if bold
  1773. tekrpt4:push    ax
  1774.     xor    ah,ah            ; clear high byte
  1775.     call    dec2di            ; store green
  1776.     pop    ax
  1777.     mov    al,';'            ; separator
  1778.     stosb
  1779.     mov    al,rgbbold/4        ; assume dark blue for bold black
  1780.     cmp    ah,8            ; bold black?
  1781.     je    tekrpt6            ; e = yes
  1782.     xor    al,al
  1783.     test    ah,1            ; blue?
  1784.     jz    tekrpt6            ; z = no
  1785.     mov    al,rgbbold/2        ; say blue, 40%
  1786.     test    ah,8            ; bold?
  1787.     jz    tekrpt6            ; z = no
  1788.     mov    al,rgbbold        ; more if bold
  1789. tekrpt6:xor    ah,ah            ; clear high byte
  1790.     call    dec2di            ; store blue
  1791.     pop    cx            ; recover loop counter
  1792.     cmp    cx,1            ; doing last item?
  1793.     je    tekrpt7            ; e = yes, do not send another "/"
  1794.     mov    al,'/'            ; separator
  1795.     stosb
  1796. tekrpt7:push    cx
  1797.     call    outstrng        ; output this string
  1798.     pop    cx
  1799.     pop    bx            ; recover palette index
  1800.     inc    bx            ; ready for next palette
  1801.     dec    cx
  1802.     jz    tekrpt8            ; z = done
  1803.     jmp    tekrpt1            ; do all palettes
  1804. tekrpt8:mov    al,escape        ; DCS terminator ST
  1805.     call    outmodem
  1806.     mov    al,'\'
  1807.     call    outmodem
  1808.     pop    bx
  1809.     pop    di
  1810.     pop    es
  1811.     ret
  1812. tekrpt    endp
  1813.  
  1814. ; Output string in tempname. Enter with di pointing at last byte+1. Return
  1815. ; with di at the same place.
  1816. outstrng proc    near
  1817.     push    cx
  1818.     mov    cx,di            ; compute length
  1819.     mov    di,offset tempname    ; start of buffer
  1820.     sub    cx,di            ; start of buffer
  1821. outstn1:mov    al,[di]
  1822.     inc    di
  1823.     call    outmodem        ; send the byte
  1824.     loop    outstn1            ; do the string
  1825.     pop    cx
  1826.     ret
  1827. outstrng endp
  1828.  
  1829. ; Process Device Control Strings (DCS or ESC P lead-in chars, parameters,
  1830. ; and Final character already read). Prepare to gather strings.
  1831. tekdcs    proc    near
  1832.     mov    dcsstrf,al        ; record Final char
  1833.     mov    emubufc,0        ; clear string count
  1834.     mov    cx,maxparam        ; number of DCS parameters
  1835.     push    si            ; copy these to the DCS area so that
  1836.     push    di            ;  they are not lost when an ST is
  1837.     push    es            ;  parsed (parser clears ESC items)
  1838.     push    ds
  1839.     pop    es
  1840.     mov    si,offset param        ; ESC paramater storage area, numeric
  1841.     mov    di,offset dparam    ; DCS parameter storage area, numeric
  1842.     cld
  1843.     rep    movsw            ; copy set to DCS storage area
  1844.     mov    cl,lparam         ; copy letter Paramter
  1845.     mov    dlparam,cl
  1846.     mov    cx,maxinter        ; number of intermediate characters
  1847.     mov    si,offset inter        ; source
  1848.     mov    di,offset dinter    ; destination
  1849.     rep    movsb
  1850.     mov    si,nparam        ; number of parameters
  1851.     mov    dnparam,si
  1852.     mov    si,ninter
  1853.     mov    dninter,si        ; number of intermediates
  1854.     pop    es
  1855.     pop    di
  1856.     pop    si
  1857.     cmp    dcsstrf,'q'        ; Sixel Graphics?
  1858.     jne    tekdcs1            ; ne = no
  1859.     mov    ttstate,offset tekgets    ; get string as next state
  1860.     ret
  1861.  
  1862. tekdcs1:mov    ttstate,offset tekdcsnul ; consume unknown DCS
  1863.     ret
  1864. tekdcs    endp
  1865.  
  1866. ; Read and discard OSC (ESC ]), PM (ESC ^), APC (ESC _) control sequences
  1867. ; through final ST (ESC \) terminator.
  1868. tekdcsnul proc    near
  1869.     mov    dcsstrf,0        ; simulate a null (dummy) Final char
  1870.     cmp    al,20h            ; control char?
  1871.     jae    tekdcsnu1        ; ae = no, skip
  1872.     jmp    tekctl            ; do control char
  1873. tekdcsnu1:ret
  1874. tekdcsnul endp
  1875.  
  1876. ; State machine to process DCS strings of type "q" (Sixel Command and Data)
  1877. ; Enter with new char in AL.
  1878. tekgets    proc    near
  1879.     mov    ttstate,offset tekgets    ; set state to ourselves
  1880.     mov    nparam,0        ; say no pending control sequences
  1881.     cmp    al,20h            ; control character?
  1882.     jae    tekgsch            ; ae = no, analyze
  1883.     jmp    tekctl            ; do control char
  1884.                     ; single sixel char state
  1885. tekgsch:cmp    al,3fh            ; legal sixel data char?
  1886.     jb    tekgrpt            ; b = no, try repeated char
  1887.     mov    cx,1            ; repeat count of 1
  1888.     jmp    sixplt            ; plot the six dots
  1889.  
  1890. tekgrpt:cmp    al,'!'            ; repeated char?
  1891.     jne    tekgera            ; ne = no
  1892.     mov    ttstate,offset tekgrpt0    ; next state is get repeat parameter
  1893.     mov    param,0
  1894.     mov    nparam,0
  1895.     ret
  1896.  
  1897. tekgrpt0:cmp    al,' '            ; control char?
  1898.     jae    tekgrpt1        ; ae = no
  1899.     jmp    tekctl            ; process control char
  1900. tekgrpt1:mov    cx,param        ; first param is used here
  1901.     call    getdec            ; accumulate repeat count to cx
  1902.     mov    param,cx        ; retain current count
  1903.     jc    tekgrpt2        ; c = ended on non-numeric
  1904.     ret                ; get more characters
  1905. tekgrpt2:cmp    al,3fh            ; break char, is it a sixel datum?
  1906.     jb    tekgrpt3        ; b = no, it is illegal, quit
  1907.     call    sixplt            ; plot cx versions of the six bits
  1908.     mov    ttstate,offset tekgets    ; return to sixel idle state
  1909.     ret
  1910. tekgrpt3:jmp    short tekgets        ; reprocess break character
  1911.  
  1912. tekgera:cmp    al,22h            ; double quote raster attribute?
  1913.     jne    tekgco            ; ne = no, try color
  1914.     mov    param,0            ; clear parameters, Pan
  1915.     mov    param[2],0        ; Pad
  1916.     mov    param[4],0        ; Ph
  1917.     mov    param[6],0        ; Pv
  1918.     mov    nparam,0        ; work on initial parameter first
  1919.     mov    ttstate,offset tekgra1    ; next state is get parameter
  1920.     ret
  1921. tekgra1:cmp    al,' '            ; control char?
  1922.     jb    tekgra2            ; b = yes, finish this work first
  1923.     push    bx
  1924.     mov    bx,nparam        ; parameter number
  1925.     shl    bx,1            ; make it a word index
  1926.     mov    cx,param[bx]        ; accumulated parameter
  1927.     call    getdec            ; accumulate decimal value into cx
  1928.     mov    param[bx],cx        ; remember accumulation
  1929.     pop    bx
  1930.     jc    tekgra2            ; c = failure to get a digit char
  1931.     ret
  1932. tekgra2:inc    nparam            ; say have another complete parameter
  1933.     cmp    nparam,4        ; got all four params Pan,Pad,Ph,Pv?
  1934.     je    tekgra4            ; e = yes
  1935.     cmp    al,';'            ; break char is separator?
  1936.     jne    tekgra3            ; ne = no, quit now
  1937.     ret                ; get more characters
  1938. tekgra3:jmp    tekgets            ; restart with the break char
  1939.  
  1940. tekgra4:;;; perform raster attributes work here
  1941.     mov    ttstate,offset tekgets
  1942.     ret
  1943.  
  1944. tekgco:    cmp    al,'#'            ; color introducer?
  1945.     je    tekgco0            ; e = yes
  1946.     jmp    tekgcr            ; ne = no
  1947. tekgco0:mov    ttstate,offset tekgco1    ; next state is get parameter
  1948.     mov    param,0            ; clear parameters, Pc
  1949.     mov    param[2],0        ; Pu
  1950.     mov    param[4],0        ; Px
  1951.     mov    param[6],0        ; Py
  1952.     mov    param[8],0        ; Pz
  1953.     mov    nparam,0        ; work on initial parameter first
  1954.     ret
  1955. tekgco1:cmp    al,' '            ; control char?
  1956.     jb    tekgco2            ; b = yes, finish this work first
  1957.     push    bx
  1958.     mov    bx,nparam        ; parameter number
  1959.     shl    bx,1            ; make it a word index
  1960.     mov    cx,param[bx]        ; accumulated parameter
  1961.     call    getdec            ; accumulate decimal value
  1962.     mov    param[bx],cx        ; remember accumulation
  1963.     pop    bx
  1964.     jc    tekgco2            ; c = failure to get a digit char
  1965.     ret
  1966. tekgco2:inc    nparam            ; say have another complete parameter
  1967.     cmp    al,';'            ; break char is separator?
  1968.     jne    tekgco3            ; ne = no, decode current sequence
  1969.     cmp    nparam,5        ; have 5 params already?
  1970.     jae    tekgco3            ; ae = yes, process them now
  1971.     ret                ;  else get more parameters
  1972. tekgco3:cmp    nparam,1        ; just one parameter?
  1973.     je    tekgco3a        ; e = yes, select from palette
  1974.     jb    tekgco3b        ; b = none, reprocess as sixel
  1975.     call    tekgco4            ; process parameters
  1976.     mov    nparam,0        ; clear parameters
  1977.     jmp    tekgets            ; reprocess char as sixel
  1978.  
  1979. tekgco3a:push    bx            ; select color from palette
  1980.     mov    bx,param[0]        ; get color number
  1981.     and    bx,000fh        ; get 0-15
  1982.     mov    bl,colpal[bx]        ; get color from palette
  1983.     mov    gfcol,bl        ; set active foreground color
  1984.     pop    bx
  1985.     push    ax            ; save char in al
  1986.     call    fixcolor        ; fix color too, if req'd
  1987.     pop    ax
  1988. tekgco3b:mov    nparam,0        ; clear parameters
  1989.     jmp    tekgets            ; reprocess char as sixel
  1990.  
  1991.                     ; set IRGB/HLS color to color palette
  1992. tekgco4:cmp    param[2],2        ; Pu (1-2), wanted RBG?
  1993.     je    tekgco4b        ; e = yes
  1994.     cmp    param[2],1        ; Pu, wanted HLS?
  1995.     jne    tekgco4a        ; ne = no
  1996.     jmp    tekgco9            ; do HLS scheme
  1997. tekgco4a:mov    nparam,0        ; clear parameters
  1998.     ret                ; return without doing work
  1999. tekgco4b:push    ax            ; iRGB, save break char in al
  2000.     mov    ax,param[4]        ; red
  2001.     mov    bx,param[6]        ; green
  2002.     mov    dx,param[8]        ; blue
  2003.     xor    cx,cx            ; cl has final color index, 0-15
  2004.     or    ch,al
  2005.     or    ch,bl
  2006.     or    ch,dl            ; any color?
  2007.     jcxz    tekgco7            ; z = no, use cl = 0 black
  2008.     cmp    ax,rgbbold        ; setting red bold?
  2009.     jae    tekgco4c        ; ae = yes
  2010.     cmp    bx,rgbbold        ; setting green bold?
  2011.     jae    tekgco4c        ; ae = yes
  2012.     cmp    dx,rgbbold        ; setting blue bold?
  2013.     jb    tekgco4d        ; b = no
  2014. tekgco4c:mov    cl,8            ; set the bold bit
  2015.     jmp    tekgco4e        ; do hues
  2016. tekgco4d:cmp    ax,rgbbold/2        ; all in dim intensities?
  2017.     jae    tekgco4e        ; ae = no
  2018.     cmp    bx,rgbbold/2        ; green?
  2019.     jae    tekgco4e        ; ae = no
  2020.     cmp    dx,rgbbold/2        ; blue
  2021.     jae    tekgco4e        ; ae = no
  2022.     mov    cl,8            ; use bold black (dark grey)
  2023.     jmp    tekgco7
  2024. tekgco4e:or    ax,ax            ; Hues, any red?
  2025.     jz    tekgco5            ; z = no
  2026.     or    cl,4            ; set red bit
  2027.     cmp    ax,rgbbold/2        ; dim?
  2028.     jae    tekgco5            ; ae = no
  2029.     test    cl,8            ; doing bold?
  2030.     jz    tekgco5            ; z = no
  2031.     xor    cl,4            ; clear dim red
  2032. tekgco5:or    bx,bx            ; any green?
  2033.     jz    tekgco6            ; z = no
  2034.     or    cl,2            ; set green bit
  2035.     cmp    bx,rgbbold/2        ; dim?
  2036.     jae    tekgco6            ; ae = no
  2037.     test    cl,8            ; doing bold?
  2038.     jz    tekgco6            ; z = no
  2039.     xor    cl,2            ; clear dim green
  2040. tekgco6:or    dx,dx            ; any blue?
  2041.     jz    tekgco7            ; z = no
  2042.     or    cl,1            ; set blue bit
  2043.     cmp    dx,rgbbold/2        ; dim?
  2044.     jae    tekgco7            ; ae = no
  2045.     test    cl,8            ; doing bold?
  2046.     jz    tekgco7            ; z = no
  2047.     xor    cl,1            ; clear dim blue
  2048. tekgco7:push    bx
  2049.     mov    bx,param[0]        ; Pc, color palette being defined
  2050.     and    bx,000fh        ; get 0-15
  2051.     mov    colpal[bx],cl        ; store color code in palette
  2052.     pop    bx
  2053.     mov    nparam,0        ; say done with this sequence
  2054.     pop    ax            ; recover break char in al
  2055.     ret
  2056.  
  2057.                     ; Hue, Lightness, Saturation
  2058. tekgco9:push    ax            ; save break char
  2059.     xor    cl,cl            ; assummed color of black
  2060.     mov    ax,param[4]        ; Px, Hue, 60 degree slices
  2061.     push    cx
  2062.     mov    cx,360            ; do modulo 360
  2063.     xor    dx,dx            ; clear high order numerator
  2064.     div    cx            ; dx has remainder
  2065.     pop    cx
  2066.     mov    ax,dx            ; put remainder in ax
  2067.     cmp    ax,30            ; blue?
  2068.     jae    tekgco10        ; ae = no
  2069.     or    cl,1            ; blue
  2070.     jmp    short tekgco15
  2071. tekgco10:cmp    ax,90            ; magenta?
  2072.     jae    tekgco11        ; ae = no
  2073.     or    cl,1+4            ; magenta = blue + red
  2074.     jmp    short tekgco15
  2075. tekgco11:cmp    ax,150            ; red?
  2076.     jae    tekgco12        ; ae = no
  2077.     or    cl,4            ; red
  2078.     jmp    short tekgco15
  2079. tekgco12:cmp    ax,210            ; yellow?
  2080.     jae    tekgco13        ; ae = no
  2081.     or    cl,4+2            ; yellow = reg + green
  2082.     jmp    short tekgco15
  2083. tekgco13:cmp    ax,270            ; cyan?
  2084.     jae    tekgco14        ; ae = no
  2085.     or    cl,2+1            ; cyan = green+blue
  2086.     jmp    short tekgco15
  2087. tekgco14:or    cl,1            ; blue
  2088.  
  2089. tekgco15:mov    ax,param[6]        ; Py, Lightness
  2090.     mov    dx,param[8]        ; Pz, Saturation
  2091.     cmp    ax,86            ; lightness is max?
  2092.     jb    tekgco16        ; b = no
  2093.     mov    cl,0fh            ; greater than 85% means bold white
  2094.     jmp    short tekgco22
  2095. tekgco16:cmp    ax,71            ; high lightness?
  2096.     jb    tekgco17        ; b = not that light
  2097.     or    cl,8            ; turn on bold bit
  2098.     cmp    dx,51            ; saturated?
  2099.     jae    tekgco22        ; ae = yes
  2100.     mov    cl,0fh            ; low saturation yields bold white
  2101.     jmp    short tekgco22
  2102. tekgco17:cmp    ax,57            ; central coloring, upper?
  2103.     jb    tekgco18        ; b = no
  2104.     or    cl,8            ; turn on bold bit
  2105.     cmp    dx,51            ; saturated?
  2106.     jae    tekgco22        ; ae = yes, use bold colors
  2107.     mov    cl,7            ; s < 50 is dim white
  2108.     cmp    dx,11            ; saturated less than 11%
  2109.     jae    tekgco22        ; ae = no
  2110.     xor    cl,cl            ; s < 11 is black here
  2111.     jmp    short tekgco22
  2112. tekgco18:cmp    ax,43            ; dim colors, upper?
  2113.     jb    tekgco19        ; b = no
  2114.     or    cl,8            ; turn on bold bit
  2115.     cmp    dx,51            ; saturated?
  2116.     jae    tekgco22        ; ae = yes, use bold colors
  2117.     and    cl,not 8        ; use dim colors
  2118.     jmp    short tekgco22
  2119. tekgco19:cmp    ax,29            ; dim colors, lower?
  2120.     jb    tekgco20        ; b = no
  2121.     cmp    dx,51            ; saturated?
  2122.     jae    tekgco22        ; ae = yes
  2123.     mov    cl,7            ; use dim white
  2124.     jmp    short tekgco22
  2125. tekgco20:cmp    ax,14            ; dark colors?
  2126.     jb    tekgco21        ; b = no
  2127.     cmp    dx,51            ; saturated?
  2128.     jae    tekgco22        ; ae = yes
  2129. tekgco21:xor    cl,cl            ; use black
  2130. tekgco22:push    bx
  2131.     mov    bx,param[0]        ; Pc, color palette being defined
  2132.     and    bx,000fh        ; get palette 0-15
  2133.     mov    colpal[bx],cl        ; store color code in palette
  2134.     pop    bx
  2135.     mov    nparam,0        ; say done with this sequence
  2136.     pop    ax            ; recover break char
  2137.     ret
  2138.  
  2139. tekgcr:    cmp    al,'$'            ; graphics carriage return?
  2140.     jne    tekgnl            ; ne = no
  2141.     mov    x_coord,0        ; go to left margin, no line feed
  2142.     ret
  2143. tekgnl:    cmp    al,'-'            ; graphics new line?
  2144.     jne    tekgunk            ; ne = no
  2145.     mov    x_coord,0        ; go to left margin, no line feed
  2146.     mov    ax,y_coord        ; bottom of char cell
  2147.     add    ax,6            ; go down 6 dots
  2148.     cmp    ax,ybot            ; wrapping below bottom?
  2149.     jbe    tekgnl1            ; be = no
  2150.     mov    ax,ybot            ; stop at bottom (leaves 2 dots free!)
  2151. tekgnl1:mov    y_coord,ax
  2152.     ret
  2153. tekgunk:mov    ttstate,offset tekgets    ; unknown char
  2154.     cmp    al,' '            ; control char?
  2155.     jae    tekgun1            ; ae = no
  2156.     jmp    tektxt            ; process control char
  2157. tekgun1:ret                ; ignore the unknown char
  2158. tekgets    endp
  2159.  
  2160. ; Accumulate decimal value in CX using ascii char in al.
  2161. ; Return with value in CX. Return carry clear if ended on a digit,
  2162. ; return carry set and ascii char in al if ended on a non-digit.
  2163. getdec    proc    near
  2164.     cmp    al,'0'            ; a number?
  2165.     jb    getdecx            ; b = no, quit
  2166.     cmp    al,'9'
  2167.     ja    getdecx            ; a = not a number, quit
  2168.     sub    al,'0'            ; remove ascii bias
  2169.     xchg    cx,ax            ; put char in cx, decimal value in ax
  2170.     push    dx            ; save reg
  2171.     mul    ten            ; times ten for a new digit
  2172.     pop    dx            ; recover reg, ignore overflow
  2173.     add    al,cl            ; add current digit
  2174.     adc    ah,0            ; 16 bits worth
  2175.     xchg    ax,cx            ; rpt cnt back to cx
  2176.     clc                ; say found a digit
  2177.     ret
  2178. getdecx:stc                ; say non-digit (in al)
  2179.     ret
  2180. getdec    endp
  2181.  
  2182. ; Display lower six bits of AL in a column, a sixel datum. Do CX times.
  2183. ; Location is PC text cursor, x_coord, y_coord, with least significant bit
  2184. ; at the top (at y_coord+8). Increments x_coord by one for each interation
  2185. ; but stops at right margin and does not change y_coord. If dparam[2], P2,
  2186. ; is 1 then color pattern 0 bits in current background, else skip them.
  2187. sixplt    proc    near
  2188.     cmp    cx,0            ; repeat count present?
  2189.     jne    sixplt1            ; ne = yes
  2190.     ret
  2191. sixplt1:push    ax
  2192.     push    bx
  2193.     push    linepat            ; save line pattern
  2194.     sub    al,3fh            ; remove ascii bias from sixel char
  2195.     xor    ah,ah
  2196.     mov    linepat,ax        ; our dot pattern in lower 6 bits
  2197.     mov    di,y_coord        ; text bottom cell line
  2198.     sub    di,8            ; go to top of 8 high char cell
  2199.     jnc    sixplt2            ; nc = no wrap over top
  2200.     xor    di,di            ; limit to screen top
  2201. sixplt2:mov    bx,di            ; bx = ending y
  2202.     add    bx,5            ; plus our six dots (goes down screen)
  2203.     cmp    bx,ybot            ; wrapping below bottom?
  2204.     jbe    sixplt3            ; be = no
  2205.     mov    bx,ybot            ; stop at bottom
  2206. sixplt3:mov    ax,x_coord        ; left edge of text cell
  2207.     mov    si,ax            ; si=starting, ax=ending PC x coord
  2208.     add    xmax,7            ; refer to right edge, not right char
  2209.     push    es            ; set up for dot plotting, save regs
  2210.     push    si
  2211.     push    di
  2212.     push    dx
  2213.     push    bp
  2214.     mov    dl,ccode        ; existing pixel op code
  2215.     push    dx            ; save ccode around line drawing
  2216.     mov    ccode,pixor        ; set OR pixel op for use by plot()
  2217.     cmp    gfcol,0            ; all black dots?
  2218.     jne    sixplt3a        ; ne = no
  2219.     mov    ccode,pixfor        ; yes, force overwriting to nulls
  2220. sixplt3a:push    cx
  2221.     call    psetup            ; setup display and es:di and es:si
  2222.     pop    cx
  2223.                     ; start sixel repeat loop
  2224. sixplt4:push    cx            ; save sixel repeat count
  2225.     push    di            ; save y starting screen address
  2226.     mov    bp,linepat        ; store active line pattern word in BP
  2227.     mov    cx,6            ; six dots per sixel
  2228.                     ; start six dot loop
  2229. sixplt5:push    cx            ; save dot count
  2230.     mov    cl,pixFor        ; assume foreground coloring
  2231.     test    bp,1            ; bit to be plotted, is it a 1?
  2232.     jnz    sixplt6            ; nz = yes, plot in foreground color
  2233.     cmp    dparam[2],1        ; P2 = 1, skip over 0's?
  2234.     je    sixplt6            ; e = yes
  2235.     mov    cl,pixbak        ; use background write pixel op
  2236.     or    bp,1            ; set pattern bit so we see a pixel
  2237. sixplt6:mov    ccode,cl        ; desired pixel op
  2238.     call    plotptr            ; plot a dot if it is a 1
  2239.     call    pincy            ; next dot down the screen (di)
  2240.     pop    cx            ; recover dot counter
  2241.     loop    sixplt5            ; do each of 6 dots
  2242.                     ;
  2243.     pop    di            ; recover starting y screen coord
  2244.     pop    cx            ; recover repeat count
  2245.     cmp    ax,xmax            ; off right edge?
  2246.     jae    sixplt8            ; ae = yes
  2247.     inc    ax            ; move right one pixel
  2248.     inc    si            ; start and stop x's
  2249. sixplt8:loop    sixplt4            ; repeat sixel cx times
  2250.     pop    dx
  2251.     mov    ccode,dl        ; recover main color code
  2252.     pop    bp
  2253.     pop    dx
  2254.     pop    di
  2255.     pop    si
  2256.     pop    es
  2257.     mov    x_coord,ax        ; new text starting x coord
  2258.     sub    xmax,7            ; restore to right most char cell
  2259.     pop    linepat            ; restore normal line pattern
  2260.     pop    bx
  2261.     pop    ax
  2262.     ret
  2263. sixplt    endp
  2264.  
  2265. ; Process ST or ESC \  String Terminator.
  2266. tekgotst proc    near
  2267.     mov    dcsstrf,0        ; clear DCS Final char
  2268.     mov    nparam,0
  2269.     mov    ninter,0
  2270.     mov    al,colpal[7]        ; reset foreground to palette 7
  2271.     mov    gfcol,al
  2272.     mov    al,colpal[0]        ; and background to palette 0
  2273.     mov    gbcol,al
  2274.     call    fixcolor        ; and fix up coloring, if req'd
  2275.     mov    prestate,offset tektxt    ; reset state of emulator to normal
  2276.     mov    ttstate,offset tektxt
  2277.     ret
  2278. tekgotst endp
  2279.  
  2280. TEKLINE    proc    near            ; GS line drawing
  2281.     cmp    al,' '            ; control char?
  2282.     jae    teklin3            ; ae = no
  2283.     cmp    al,CR            ; exit drawing on CR,LF,RS,US,FS,CAN
  2284.     je    teklin2            ; e = yes, a cr
  2285.     cmp    al,LF            ; these terminate line drawing cmds
  2286.     je    teklin2
  2287.     cmp    al,FS            ; <FS>
  2288.     je    teklin2
  2289.     cmp    al,GS            ; <GS>
  2290.     je    teklin2
  2291.     cmp    al,RS            ; <RS>
  2292.     je    teklin2
  2293.     cmp    al,US            ; <US>
  2294.     je    teklin2
  2295.     cmp    al,CAN            ; and <CAN>
  2296.     je    teklin2            ; BUT ignore other control chars
  2297.     cmp    al,escape        ; escape?
  2298.     je    teklin1            ; e = yes, come back to this state
  2299.     ret                ; ignore stray control char
  2300. teklin1:jmp    tekctl            ; process control char
  2301. teklin2:mov    lastc,0            ; clear last drawing coordinate flag
  2302.     mov    visible,0        ; invisible again
  2303.     jmp    tektxt            ; process char under text mode
  2304.  
  2305. teklin3:call    tekxyc            ; parse coordinates from input bytes
  2306.     jc    teklin4            ; c = done, do the plotting
  2307.     ret                ; nc = not done yet
  2308. teklin4:mov    cl,visible        ; get moveto or drawto variable
  2309.     call    tekdraw            ; move that point
  2310.     mov    visible,1        ; say next time we draw
  2311.     ret
  2312. TEKLINE    endp
  2313.     
  2314. TEKPNT    proc    near            ; FS plot single point
  2315.     cmp    al,' '            ; control char?
  2316.     jae    tekpnt3            ; ae = no
  2317.     cmp    al,CR            ; exit drawing on CR,LF,RS,US,FS,CAN
  2318.     je    tekpnt2            ; e = yes, a cr
  2319.     cmp    al,LF             ; these terminate line drawing cmds
  2320.     je    tekpnt2
  2321.     cmp    al,FS            ; <FS>
  2322.     je    tekpnt2
  2323.     cmp    al,GS            ; <GS>
  2324.     je    tekpnt2
  2325.     cmp    al,RS            ; <RS>
  2326.     je    tekpnt2
  2327.     cmp    al,US            ; <US>
  2328.     je    tekpnt2
  2329.     cmp    al,CAN            ; and <CAN>
  2330.     je    tekpnt2            ; BUT ignore other control chars
  2331.     cmp    al,escape        ; escape?
  2332.     je    tekpnt1            ; e = yes
  2333.     clc
  2334.     ret                ; ignore stray control char
  2335. tekpnt1:jmp    tekctl            ; process control char
  2336. tekpnt2:mov    lastc,0            ; clear last drawing coordinate flag
  2337.     mov    visible,0        ; invisible again
  2338.     jmp    tektxt            ; process char under text mode
  2339.  
  2340. tekpnt3:call    tekxyc            ; parse coordinates
  2341.     jc    tekpnt4            ; c = done, do the plotting
  2342.     ret                ; nc = not done yet
  2343. tekpnt4:xor    cl,cl            ; do not draw
  2344.     call    tekdraw            ; move to the point
  2345.     mov    ax,si            ; copy starting point to end point
  2346.     mov    bx,di            ; ax,bx,si,di are in PC coordinates
  2347.     mov    cl,1            ; make plot visible
  2348.     call    line            ; draw the dot
  2349.     mov    visible,0        ; return to invisibility
  2350.     clc
  2351.     ret
  2352. TEKPNT    endp
  2353.  
  2354. ; Decode graphics x,y components. Returns carry set to say have all
  2355. ; components for a line, else carry clear. Understands 4014 lsb extensions.
  2356. ; Permits embedded escape sequences.
  2357. TEKXYC    proc    near
  2358.     cmp    al,40h
  2359.     jb    tekgh2            ; 20-3F are HIX or HIY
  2360.     cmp    al,60h            ; 40-5F are LOX (causes beam movement)
  2361.     jb    tekgh4            ; 60-7F are LOY
  2362.                     ; extract low-order 5 bits of Y coord
  2363.     mov    ah,tek_loy        ; copy previous LOY to MSB (4014)
  2364.     mov    tek_lsb,ah
  2365.     and    al,1Fh            ; LOY is 5 bits
  2366.     mov    tek_loy,al
  2367.     cmp    lastc,loy        ; 2nd LOY in a row?
  2368.     je    tekgh1            ; e = yes, then LSB is valid
  2369.     mov    tek_lsb,0        ; 1st one, clear LSB
  2370. tekgh1:    mov    lastc,loy        ; LOY seen, expect HIX (instead of HIY)
  2371. tekgh0:    clc                ; c clear = not completed yet
  2372.     ret
  2373. tekghx:    mov    ttstate,offset tektxt    ; go to TEKTXT next time
  2374.     mov    lastc,0            ; clear last drawing coordinate flag
  2375.     or    status,txtmode        ; set text mode in status byte
  2376.     clc                ; carry clear means done
  2377.     ret
  2378.  
  2379.             ; Extract high-order 5 bits (X or Y, depending on lastc)
  2380. tekgh2: and    ax,1Fh            ; just 5 bits
  2381.     mov    cl,5
  2382.     shl    ax,cl            ; shift over 5 bits
  2383.     cmp    lastc,loy        ; was last coordinate a low-y?
  2384.     je    tekgh3            ; e = yes, parse hix
  2385.     mov    tek_hiy,ax        ; this byte has HIY
  2386.     mov    lastc,hiy
  2387.     clc
  2388.     ret
  2389. tekgh3: mov    tek_hix,ax        ; this byte has HIX
  2390.     mov    lastc,hix
  2391.     clc
  2392.     ret
  2393. tekgh4: and    al,1Fh            ; just 5 bits
  2394.     mov    tek_lox,al
  2395.     mov    lastc,lox
  2396.     mov    ax,tek_hix        ; combine HIX*32
  2397.     or    al,tek_lox        ;  with LOX
  2398.     mov    bx,tek_hiy        ; same for Y
  2399.     or    bl,tek_loy
  2400.     stc                ; set c to say completed operation
  2401.     ret
  2402. TEKXYC    endp
  2403.  
  2404. TEKRLIN    proc    near            ; RS relative line drawing
  2405.     cmp    al,' '            ; control char?
  2406.     jae    tekrli1            ; ae = no
  2407.     jmp    tektxt            ; process control char
  2408. tekrli1:cmp    al,' '            ; pen up command?
  2409.     jne    tekrli2            ; ne = no, try pen down
  2410.     mov    visible,0        ; do invisible movements
  2411.     jmp    short tekrli3        ; do the command
  2412. tekrli2:cmp    al,'P'            ; pen down command?
  2413.     jne    tekrli4            ; ne = no, return to text mode
  2414.     mov    visible,1        ; set visible moves
  2415.  
  2416. tekrli3:mov    ax,x_coord        ; PC x coordinate of pen
  2417.     mov    bx,y_coord        ;    y coordinate
  2418.     call    pctotek            ; get current pen position in Tek coor
  2419.     xor    cl,cl            ; invisible, moveto
  2420.     call    tekdraw            ; move that point, set oldx and oldy
  2421.     mov    ttstate,offset tekinc    ; next get incremental movement cmds
  2422.     ret
  2423.  
  2424. tekrli4:mov    visible,0        ; bad char, reset visibility
  2425.     mov    ttstate,offset tektxt    ; assume text
  2426. tekrli5:jmp    ttstate            ; deal with bad char
  2427. TEKRLIN    endp
  2428.                     ; interpret RS inc plot command byte
  2429. TEKINC    proc    near            ; get movement character and do cmd
  2430.     cmp    al,' '            ; control char?
  2431.     jae    tekinc1            ; ae = no
  2432.     jmp    tektxt            ; process control char
  2433. tekinc1:mov    bx,oldx
  2434.     mov    cx,oldy
  2435.     test    al,1            ; 'A', 'E', 'I'?  Do by bit fields
  2436.     jz    tekinc2            ; z = no
  2437.     inc    bx            ; adjust beam position
  2438. tekinc2:test    al,2            ; 'B', 'F', 'J'?
  2439.     jz    tekinc4
  2440.     dec    bx
  2441. tekinc4:test    al,4            ; 'D', 'E', 'F'?
  2442.     jz    tekinc8            ; z = no
  2443.     inc    cx
  2444. tekinc8:test    al,8            ; 'H', 'I', 'J'?
  2445.     jz    tekinc9
  2446.     dec    cx
  2447. tekinc9:cmp    bx,0            ; too far left?
  2448.     jge    tekinc10        ; ge = no
  2449.     xor    bx,bx            ; else stop at the left margin
  2450. tekinc10:cmp    bx,maxtekx-1        ; too far left?
  2451.     jle    tekinc11        ; le = no
  2452.     mov    bx,maxtekx-1        ; else stop that the left margin
  2453. tekinc11:cmp    cx,maxteky-1        ; above the top?
  2454.     jle    tekinc12        ; le = not above the top
  2455.     mov    cx,maxteky-1        ; else stop at the top
  2456. tekinc12:cmp    cx,0            ; below bottom?
  2457.     jge    tekinc13        ; ge = not below bottom
  2458.     xor    cx,cx            ; else stop at the bottom
  2459. tekinc13:mov    ax,bx            ; ax is vector x end point
  2460.     mov    oldx,bx
  2461.     mov    bx,cx            ; bx is vector y end point
  2462.     mov    oldy,cx
  2463.     mov    cl,visible
  2464.     jmp    tekdraw            ; move/draw to that point
  2465. tekincb:mov    visible,0
  2466.     jmp    tektxt            ; reparse the bad char
  2467. TEKINC    endp
  2468.     
  2469.  
  2470. crossini proc    near            ; set crosshairs for initial screen
  2471.     mov    ax,xmax            ; right margin minus 7 dots
  2472.     add    ax,7            ; right most dot
  2473.     shr    ax,1            ; central position
  2474.     mov    xcross,ax        ; save PC coord for crosshair
  2475.     mov    ax,ybot            ; last scan line
  2476.     shr    ax,1
  2477.     mov    ycross,ax        ; this is the center of the screen
  2478.     ret
  2479. crossini endp
  2480.  
  2481. ; Routine to trigger the crosshairs, wait for a key to be struck, and send
  2482. ; the typed char (if printable ascii) plus four Tek encoded x,y position
  2483. ; coordinates and then a carriage return.
  2484. ; ax, cx, xcross, ycross operate in PC coordinates.
  2485.      
  2486. CROSHAIR PROC NEAR
  2487.     push    linepat            ; save line drawing pattern
  2488.     mov    linepat,0ffffh        ; reset line type to solid
  2489.  
  2490.     mov    ax,xmax            ; right margin minus 7 dots
  2491.     add    ax,7
  2492.     mov    temp,ax            ; right margin dot
  2493. crosha1:call    crosdraw        ; draw the cross-hairs
  2494.     call    tiseof            ; is stdin at EOF?
  2495.     jc    crosha2            ; c = yes, exit this mode now
  2496.     mov    ah,coninq        ; DOS, quiet read char
  2497.     int    dos
  2498.     push    ax            ; save char for later
  2499.     call    crosdraw        ; erase cross hairs
  2500.     pop    ax
  2501.     or    al,al            ; ascii or scan code returned
  2502.     jnz    arrow5            ; nz = ascii char returned
  2503.  
  2504.     call    tiseof            ; is stdin at EOF?
  2505.     jc    crosha2            ; c = yes, exit this mode now
  2506.     mov    ah,coninq        ; read scan code
  2507.     int    dos
  2508.     or    al,al            ; Control-Break?
  2509.     jnz    crosha3            ; nz = no, something else
  2510. crosha2:pop    linepat            ; restore line pattern
  2511.     ret                ; exit crosshairs mode
  2512.  
  2513. crosha3:cmp    al,homscn        ; is it 'home'?
  2514.     jne    arrow1            ; ne = no, try other keys
  2515.     mov    ax,temp            ; right margin
  2516.     shr    ax,1            ; central position
  2517.     mov    xcross,ax        ; save PC coord for crosshair
  2518.     mov    ax,ybot            ; last scan line
  2519.     shr    ax,1
  2520.     mov    ycross,ax        ; this is the center of the screen
  2521.     jmp    crosha1            ; home the crosshairs
  2522.  
  2523. arrow1:    cmp    al,lftarr        ; left arrow?
  2524.     jne    arrow2            ; ne = no
  2525.     mov    cx,-1            ; left shift
  2526.     jmp    short xkeys
  2527. arrow2:    cmp    al,rgtarr        ; right arrow?
  2528.     jne    arrow3            ; ne = no
  2529.     mov    cx,1            ; right shift
  2530.     jmp    short xkeys
  2531. arrow3:    cmp    al,uparr        ; up arrow?
  2532.     jne    arrow4            ; ne = no
  2533.     mov    cx,-1            ; up shift
  2534.     jmp    short vertkey
  2535. arrow4:    cmp    al,dnarr        ; down arrow?
  2536.     jne    badkey            ; ne = no, ignore it
  2537.     mov    cx,1                  ; down shift
  2538.     jmp    short vertkey
  2539.  
  2540. badkey:    call    tekbeep            ; tell user we don't understand
  2541.     jmp    crosha1            ; keep going
  2542.  
  2543.                     ; Shifted keys yield ascii keycodes
  2544. arrow5:    cmp    al,'C' and 1fh        ; Control-C?
  2545.     je    crosha2            ; e = yes, exit crosshairs mode now
  2546.     cmp    al,shlftarr        ; shifted left arrow?
  2547.     jne    arrow6            ; ne = no
  2548.     mov    cx,-10            ; big left shift
  2549.     jmp    short xkeys
  2550. arrow6:    cmp    al,shrgtarr        ; shifted right arrow?
  2551.     jne    arrow7            ; ne = no
  2552.     mov    cx,10            ; big right shift
  2553.     jmp    short xkeys
  2554. arrow7:    cmp    al,shuparr        ; shifted up arrow?
  2555.     jne    arrow8            ; ne = no
  2556.     mov    cx,-10            ; big up shift
  2557.     jmp    short vertkey
  2558. arrow8:    cmp    al,shdnarr        ; shifted down arrow?
  2559.     jne    charkey            ; ne = no, send this key as is
  2560.     mov    cx,10            ; big down shift
  2561.     jmp    short vertkey
  2562.  
  2563. xkeys:     add    cx,xcross        ; add increment
  2564.     jns    noxc            ; gone too far negative?
  2565.     mov    cx,0            ; s = yes, make it 0
  2566. noxc:    cmp    cx,temp            ; too far right?
  2567.     jb    xdraw9            ; b = no
  2568.     mov    cx,temp            ; yes, make it the right
  2569. xdraw9: mov    xcross,cx        ; new x value for cross hairs
  2570.     jmp    crosha1            ; and redraw
  2571.      
  2572. vertkey:add    cx,ycross        ; adjust cx
  2573.     jns    noyc            ; gone negative?
  2574.     mov    cx,0            ; s = yes then make 0
  2575. noyc:    cmp    cx,ybot            ; too high?
  2576.     jb    yok            ; b = no
  2577.     mov    cx,ybot            ; make it maximum
  2578. yok:    mov    ycross,cx        ; save new y crosshair
  2579.     jmp    crosha1            ; and redraw
  2580.      
  2581. charkey:push    ax            ; preserve char in al
  2582.     call    tclrbuf            ; purge received data to date
  2583.     pop    ax
  2584.     call    outmodem        ; send the break character
  2585.     mov    ax,xcross        ; set beam to xcross,ycross
  2586.     mov    bx,ycross        ; must convert to Tek coordinates
  2587.     call    pctotek            ; scale from PC screen coord to Tek
  2588.     push    ax            ; save around drawing
  2589.     push    bx
  2590.     xor    cx,cx            ; just a move
  2591.     call    tekdraw            ; moveto ax,bx in Tek coord
  2592.     pop    bx            ; recover Tek y
  2593.     pop    ax            ; recover Tek x
  2594.     call    sendpos            ; send position report to host
  2595.     pop    linepat            ; recover current line drawing pattern
  2596.     mov    ttstate,offset tektxt    ; go to TEKTXT next time
  2597.     mov    lastc,0            ; clear last drawing coordinate flag
  2598.     or    status,txtmode        ; set text mode in status byte
  2599.     ret
  2600. CROSHAIR ENDP
  2601.      
  2602. ; CROSDRAW draws cross-hairs by XORing cross with picture.
  2603. ; xcross and ycross are in PC coordinates.     
  2604. CROSDRAW PROC    NEAR
  2605.     mov    al,ccode        ; save current pixel op
  2606.     push    ax
  2607.     mov    si,xcross        ; move to (xcross, ycross-10)
  2608.     mov    di,ycross
  2609.     sub    di,10            ; half the size of the cross
  2610.     jns    crosd1            ; no sign bit means ok
  2611.     xor    di,di            ; else limit to start of screen
  2612. crosd1:    mov    ax,si            ; next, draw to (xcross, ycross+10)
  2613.     mov    bx,ycross        ; make bottom stroke
  2614.     add    bx,10
  2615.     cmp    bx,ybot            ; too large?
  2616.     jbe    crosd2            ; be = no
  2617.     mov    bx,ybot            ; vertical line to (xcross,ybot)
  2618. crosd2:    mov    cl,pixxor        ; xor pixels
  2619.     call    line            ; and draw vertical
  2620.     sub    si,12            ; move to (xcross-12, ycross)
  2621.     jns    crosd3            ; no sign means ok
  2622.     xor    si,si            ; else limit to start of line
  2623. crosd3:    mov    di,ycross
  2624.     mov    bx,di
  2625.     mov    ax,xcross        ; draw to (xcross+12, ycross)
  2626.     add    ax,12
  2627.     cmp    ax,temp            ; temp is right margin, too large?
  2628.     jbe    crosd4            ; be = no, ok
  2629.     mov    ax,temp            ; max x value
  2630. crosd4:    mov    cl,pixxor        ; set XOR code
  2631.     call    line            ; draw to (xcross+12, ycross)
  2632.     pop    ax            ; recover current pixel op
  2633.     mov    ccode,al        ; restore it
  2634.     ret
  2635. CROSDRAW ENDP
  2636.      
  2637. ; SENDPOS sends position of cross-hairs to the host.
  2638. ; ax has Tek X and bx has Tek Y coord of center of crosshair     
  2639. SENDPOS PROC NEAR
  2640.     push    bx            ; preserve register
  2641.     call    sendxy            ; send x coord
  2642.     pop    ax
  2643.     call    sendxy            ; send y coord
  2644.     mov    al,cr            ; follow up with cr
  2645.     call    outmodem
  2646.     ret
  2647. SENDPOS ENDP
  2648.  
  2649. ; Write binary number in AX as decimal asciiz to buffer pointer DI.
  2650. dec2di    proc    near        ; output number in ax using base in cx
  2651.                 ; corrupts ax, cx, and dx
  2652.     mov    cx,10
  2653. dec2di1:xor    dx,dx        ; clear high word of numerator
  2654.     div    cx        ; (ax / cx), remainder = dx, quotient = ax
  2655.     push    dx        ; save remainder for outputting later
  2656.     or    ax,ax        ; any quotient left?
  2657.     jz    dec2di2        ; z = no
  2658.     call    dec2di1        ; yes, recurse
  2659. dec2di2:pop    dx        ; get remainder
  2660.     add    dl,'0'        ; make digit printable
  2661.     mov    [di],dl        ; store char in buffer
  2662.     inc    di
  2663.     mov    byte ptr[di],0    ; add terminator
  2664.     ret
  2665. dec2di    endp
  2666.      
  2667. ; SENDXY sends value of ax as Tek encoded bytes
  2668. ; ax is in Tek coordinates     
  2669. SENDXY    PROC    NEAR
  2670.     shl    ax,1
  2671.     shl    ax,1            ; move all but lower 5 bits to ah
  2672.     shl    ax,1
  2673.     shr    al,1
  2674.     shr    al,1            ; move low five bits to low 5 bits
  2675.     shr    al,1
  2676.     or    ah,20h            ; make it a printing char as per TEK
  2677.     xchg    al,ah            ; send high 5 bits first
  2678.     call    outmodem
  2679.     xchg    al,ah            ; then low five bits
  2680.     or    al,20h
  2681.     call    outmodem
  2682.     xchg    ah,al            ; al is first sent byte
  2683.     ret
  2684. SENDXY    ENDP
  2685.      
  2686.      
  2687. SENDID    PROC NEAR            ; pretend VT340
  2688.     mov    bx,offset tekid        ; VT320 identification string
  2689. sndid1: mov    al,[bx]            ; get char from sequence
  2690.     or    al,al            ; end of sequence?
  2691.     jz    sndid0            ; z = yes, return
  2692.     call    outmodem        ; send it out the port
  2693.     inc    bx
  2694.     jmp    sndid1
  2695. sndid0:    ret
  2696. SENDID    ENDP
  2697.      
  2698. ; SENDSTAT - send status and cursor position to host
  2699.      
  2700. SENDSTAT PROC NEAR
  2701.     mov    al,STATUS        ; get tek status
  2702.     or    al,20h            ; make it printable
  2703.     call    OUTMODEM        ; and send it
  2704.     mov    ax,oldx            ; now send x coordinate (oldx is Tek)
  2705.     call    SENDXY
  2706.     mov    ax,oldy            ; and y coordinate (oldy is Tek coord)
  2707.     call    SENDXY
  2708.     mov    al,cr            ; end with a cr
  2709.     call    OUTMODEM
  2710.     ret
  2711. SENDSTAT ENDP
  2712.      
  2713.  
  2714. ; Convert X and Y from PC coordinates to Tek coordinates. AX = X, BX = Y
  2715. ; for both input and output.
  2716. pctotek    proc    near
  2717.     mul    xdiv            ; scale from PC screen coord to Tek
  2718.     div    xmult
  2719.     xchg    bx,ax            ; save Tek x coord in bx
  2720.     neg    ax            ; y axis. Turn upside down for Tek
  2721.     add    ax,ybot
  2722.     mul    ydiv            ; scale y from PC screen coord to Tek
  2723.     div    ymult
  2724.     xchg    ax,bx            ; ax has X, bx has Y in Tek coords
  2725.     ret
  2726. pctotek    endp
  2727.  
  2728. ; Routine to output character in AL to the screen.
  2729.  
  2730. OUTSCRN PROC NEAR            ; put one character to the screen
  2731.     cmp    bypass,0        ; GIN mode bypass off?
  2732.     je    outscr1            ; e = yes
  2733.     ret                ;  else ignore characters
  2734.                     ; Set Translation Input filter
  2735. outscr1:cmp    rxtable+256,0        ; translation turned off?
  2736.     je    outscr2            ; e = yes, no translation
  2737.     push    bx
  2738.     mov    bx,offset rxtable    ; address of translate table
  2739.     xlatb                ; new char is in al
  2740.     and    al,7fh            ; retain only lower seven bits
  2741.     pop    bx
  2742. outscr2:mov    ccode,pixor        ; assume transparent chars
  2743.     cmp    chcontrol,0        ; transparent chars?
  2744.     je    outscr3            ; e = yes
  2745.     mov    ccode,pixfor        ; write in foreground
  2746. outscr3:cmp    al,lf            ; this moves down the screen
  2747.     je    outscr4            ; e = yes, a lf
  2748.     cmp    al,' '            ; printable?
  2749.     jb    outscr5            ; b = no
  2750. outscr4:call    testfull        ; check for full screen
  2751. outscr5:call    putc            ; routine to draw characters
  2752.     ret
  2753. OUTSCRN ENDP
  2754.      
  2755. ; Test if screen is full. If full sound beep, wait for any keyboard input
  2756. ; (skip kbd reading if stdin is redirected).
  2757. testfull proc    near
  2758.     push    ax
  2759.     mov    ax,x_coord
  2760.     cmp    ax,xmax            ; at end of the line?
  2761.     jbe    testfu1            ; be = no
  2762.     mov    x_coord,0        ; wrap to next line
  2763.     add    y_coord,8        ; next row
  2764. testfu1:mov    ax,ybot            ; get last scan line
  2765.     inc    ax            ; number of scan lines
  2766.     cmp    ax,y_coord        ; minus where char bottom needs to go
  2767.     jae    testfu3            ; ae = enough space for char
  2768.     call    tekbeep            ; tell the user we are waiting
  2769.     call    tiseof            ; EOF on redirected stdin?
  2770.     jc    testfu2            ; c = yes, proceed anyway
  2771.     mov    ah,coninq        ; read keyboad via DOS
  2772.     int    dos            ; wait for keystroke
  2773.     or    al,al            ; scan code being returned?
  2774.     jne    testfu2            ; ne = no
  2775.     mov    ah,coninq        ; clear away scan code too
  2776.     int    dos
  2777. testfu2:call    tekcls            ; clear the screen
  2778.     mov    x_coord,0
  2779.     mov    y_coord,0
  2780. testfu3:pop    ax            ; recover current character
  2781.     ret
  2782. testfull endp
  2783.       
  2784. ; TEKCLS routine to clear the screen.
  2785. ; Entry point tekcls1 clears screen without resetting current point.     
  2786. TEKCLS    PROC    NEAR
  2787.     cmp    flags.vtflg,tttek    ; regular Tek terminal?
  2788.     je    tekcls0            ; e = yes
  2789.     test    tekflg,1        ; Tek mode active yet?
  2790.     jnz    tekcls0            ; nz = yes
  2791.     ret                ; else ignore this call
  2792. tekcls0:mov    x_coord,0        ; starting text coordinates
  2793.     mov    y_coord,0
  2794.     mov    oldx,0            ; assumed cursor starting location
  2795.     mov    oldy,maxteky        ;  top right corner (Tek coord)
  2796.     mov    scalex,0        ; clear last plotted point (PC coord)
  2797.     mov    scaley,0
  2798.     mov    lastc,0            ; last parsed x,y coordinate
  2799.     mov    visible,0        ; make lines invisible
  2800.     mov    bypass,0        ; clear bypass condition
  2801.     mov    ttstate,offset tektxt    ; do displayable text
  2802.     mov    prestate,offset tektxt
  2803.  
  2804. tekcls1:push    ax            ; save registers
  2805.     push    cx
  2806.     mov    bl,ccode        ; save pixel op code
  2807.     push    bx
  2808.     cmp    graph_mode,hercules    ; Hercules?
  2809.     jne    tekclsw            ; ne = no
  2810.     call    hgraf            ; set Hercules board to Graphics mode
  2811.     jmp    tekcls7
  2812.  
  2813. tekclsw:cmp    graph_mode,wyse700    ; Wyse 700?
  2814.     jne    tekcls2            ; ne = no
  2815.     call    wygraf            ; set board to Graphics mode & cls
  2816.     jmp    tekcls7
  2817.  
  2818. tekcls2:mov    di,0            ; point to start of screen, di=row
  2819.     mov    ccode,pixbak        ; write in background
  2820.     call    psetup            ; setup graphics routine and es:di
  2821.     mov    cx,4000h        ; CGA, 200 lines times 80 bytes worth
  2822.     cmp    graph_mode,cga        ; cga?
  2823.     je    tekcls3            ; e = yes
  2824.     mov    cx,8000h        ; Olivetti, 400 lines times 80 bytes
  2825.     cmp    graph_mode,olivetti    ; AT&T-Olivetti?
  2826.     je    tekcls3            ; e = yes
  2827.     cmp    graph_mode,toshiba    ; Toshiba?
  2828.     je    tekcls3            ; e = yes
  2829.     cmp    graph_mode,vaxmate    ; VAXmate?
  2830.     jne    tekcls4            ; ne = no
  2831. tekcls3:cld                ; clear screen directly of text stuff
  2832.     xor    ax,ax
  2833.     test    gbcol,7            ; background is dark?
  2834.     jz    tekcls3a        ; z = yes
  2835.     mov    ax,0ffffh        ; light, set all pixels
  2836. tekcls3a:shr    cx,1            ; do words
  2837.     rep    stosw            ; clear the words
  2838.     jmp    short tekcls7
  2839.  
  2840. tekcls4:cmp    graph_mode,ega        ; EGA?
  2841.     je    tekcls5            ; e = yes
  2842.     cmp    graph_mode,monoega    ; EGA with mono display?
  2843.     je    tekcls5            ; e = yes
  2844.     cmp    graph_mode,colorega    ; EGA with medium resolution monitor?
  2845.     je    tekcls5            ; e = yes
  2846.     jmp    short tekcls6        ; else use Bios
  2847.  
  2848. tekcls5:                ; EGA clear screen quickly
  2849.     mov    ax,0ff08h        ; set all 8 bits to be changed
  2850.     call    ega_gc            ; set bit mask register accordingly
  2851.     mov    ax,0003h        ; data rotate reg, write unmodified
  2852.     call    ega_gc            ; 
  2853.     mov    cx,ybot            ; last scan line
  2854.     inc    cx            ; number of scan lines
  2855.     mov    ax,80/2            ; words (2*bytes) per scan line
  2856.     mul    cx
  2857.     mov    cx,ax            ; cx = number of bytes to clear
  2858.     call    fixcolor        ; fix colors first, if req'd
  2859.     mov    al,gbcol        ; select background colour
  2860.     mov    ah,al            ; copy for word stores
  2861.     cld
  2862.     rep    stosw            ; write backgound color
  2863.     jmp    short tekcls7
  2864.  
  2865. tekcls6:push    es            ; clear screen by scrolling up
  2866.     call    tcmblnk            ; clear screen, for Environments
  2867.     pop    es
  2868.  
  2869. tekcls7:xor    si,si            ; starting x  (in case screen is
  2870.     xor    di,di            ; starting y    cleared by user)
  2871.     pop    bx
  2872.     mov    ccode,bl        ; restore pixel op code
  2873.     pop    cx
  2874.     pop    ax
  2875.     ret
  2876. TEKCLS    ENDP
  2877.      
  2878. ; Routine to draw a line on the screen, using TEKTRONIX coordinates.
  2879. ; X coordinate in AX, 0=left edge of screen, 1023=right edge of screen.
  2880. ; Y coordinate in BX, 0=bottom of screen, 779=top of screen.
  2881. ; CL=0 - invisible move, else draw in foreground colors
  2882.      
  2883. TEKDRAW PROC NEAR
  2884.     mov    si,scalex        ; get old x already scaled
  2885.     mov    di,scaley        ; get old y already scaled
  2886.     call    scale             ; scale new end point to PC coords
  2887.     cmp    cl,0            ; invisible drawing?
  2888.     je    moveto            ; z = just move, skip draw part
  2889.     mov    cl,pixfor        ; draw in foreground color
  2890.     call    LINE            ; draw the line
  2891. moveto:    mov    x_coord,ax        ; update text coordinates to match
  2892.     mov    y_coord,bx        ;  last drawn point
  2893.     ret
  2894. TEKDRAW ENDP
  2895.      
  2896. ; Scale TEKTRONIX coordinates to the currently defined screen coordinates
  2897. ; AX holds X axis, BX holds Y axis. Both are changed from Tektronix coord
  2898. ; to PC coordinates by this procedure.
  2899. SCALE    PROC    NEAR
  2900.     push    dx
  2901.     push    si
  2902.     cmp    ax,1023            ; limit x axis
  2903.     jbe    scale1            ; be = not out of bounds
  2904.     mov    ax,1023
  2905. scale1:    cmp    bx,779            ; limit y axix
  2906.     jbe    scale2            ; be = not out of bounds
  2907.     mov    bx,779
  2908. scale2:    mov    oldx,ax            ; save current Tek x for next draw
  2909.     mov    oldy,bx            ; save current Tek y for next draw
  2910.     mul    xmult            ; scale x-coord
  2911.     mov    si,xdiv            ; get the divisor
  2912.     shr    si,1            ; halve it
  2913.     add    ax,si            ; add in - to round to nearest integer
  2914.     adc    dx,0
  2915.     div    xdiv
  2916.     push    ax
  2917.     mov    ax,bx
  2918.     mul    ymult            ; scale y-coord
  2919.     mov    si,ydiv            ; get divisor
  2920.     shr    si,1            ; halve it
  2921.     add    ax,si            ; add in - to round to nearest integer
  2922.     adc    dx,0
  2923.     div    ydiv
  2924.     mov    bx,ybot
  2925.     sub    bx,ax            ; put new Y in right reg
  2926.     jns    scale3            ; ns = not too far
  2927.     xor    bx,bx
  2928. scale3:    pop    ax            ; put new X in right reg
  2929.     mov    scalex,ax        ; save scaled values
  2930.     mov    scaley,bx
  2931.     pop    si
  2932.     pop    dx
  2933.     ret
  2934. SCALE    ENDP
  2935.       
  2936. ; LINE    Subroutine to plot a line with endpoints in AX,BX and SI,DI.
  2937. ;    fast line drawing routine for the IBM PC
  2938. ;
  2939. ; Registers at CALL
  2940. ; -----------------
  2941. ; SI=Start X coord, all in PC coordinates
  2942. ; DI=Start Y coord
  2943. ; AX=End X coord
  2944. ; BX=End Y coord
  2945. ; CCODE=pixel operation code
  2946. ; BP= line drawing pattern (is changed here by rotation)
  2947. ; registers are all unchanged
  2948.      
  2949. LINE    PROC    NEAR
  2950.     push    ax
  2951.     push    bx
  2952.     push    cx
  2953.     push    dx
  2954.     push    si
  2955.     push    di
  2956.     push    es
  2957.     mov    bp,linepat        ; store active line pattern word in BP
  2958.     mov    dl,ccode        ; existing pixel op code
  2959.     push    dx            ; save around line drawing
  2960.     mov    ccode,cl    ; save color code in ccode for use by plot()
  2961.             ; first get coord to achieve increasing x; deltax >= 0
  2962.     sub    ax,si            ; deltax = x2 - x1
  2963.     jge    line1            ; ge = going to the right, as desired
  2964.     neg    ax            ; make deltax non-negative
  2965.     sub    si,ax            ; swap the x coordinates
  2966.     xchg    bx,di            ; swap the y coordinates too
  2967.                 ; second, compute deltay. ax = deltax, si = x1
  2968. line1:    sub    bx,di            ; deltay = y2 - y1
  2969.     call    psetup            ; setup display adapter for plotting
  2970.                     ;  and setup es:di to screen memory
  2971.   ; Choose algorithm based on |deltay| < |deltax| (use shallow) else steep.
  2972.   ; We arrange matters such that both deltas are non-negative.
  2973.     cmp    bx,0            ; deltay
  2974.     jge    line2            ; ge = non-negative
  2975.     neg    linelen
  2976.     neg    bx            ; make non-negative
  2977. line2:    cmp    bx,ax            ; |deltay| versus |deltax|
  2978.     jbe    shallow            ; be = do shallow algorithm
  2979.     jmp    steep            ; else do steep algorithm
  2980.  
  2981.     ; shallow algorithm, move along x, di=y1, bx=deltay, si=x1, ax=deltax
  2982. shallow:add    bx,bx            ; bx = 2*deltay
  2983.     mov    cx,ax            ; cx = number of steps (deltax here)
  2984.     inc    cx            ; loop dec's cx before testing
  2985.     mov    dx,bx            ; dx holds error
  2986.     sub    dx,ax            ; error = 2*deltay - deltax
  2987.     add    ax,ax            ; ax = 2*|deltax|
  2988. shal1:    call    plotptr            ; Plot(x,y)
  2989.     cmp    dx,0
  2990.     jle    shal2            ; le =     error <= 0
  2991.     call    pincy            ; increment y by one scan line
  2992.     sub    dx,ax            ; error = error - 2*deltax
  2993. shal2:    add    dx,bx            ; error = error + 2*deltay
  2994.     inc    si            ; x = next dot right
  2995.     loop    shal1
  2996.     jmp    short plotex
  2997.  
  2998.     ; steep algorithm, move along y, di=y1, bx=deltay, si=x1, ax=deltax
  2999. steep:    add    ax,ax            ; ax = 2*deltax
  3000.     mov    dx,ax            ; dx holds error
  3001.     sub    dx,bx            ; error = 2*deltax(bx) - deltay (bx)
  3002.     mov    cx,bx            ; cx = number of steps (deltay here)
  3003.     inc    cx            ; loop dec's cx before testing
  3004.     add    bx,bx            ; bx = 2*|deltay|
  3005. stee1:    call    plotptr            ; Plot(x,y) x = ax, y = di
  3006.     cmp    dx,0
  3007.     jle    stee2            ; le  error <= 0
  3008.     inc    si            ; x = next dot right
  3009.     sub    dx,bx            ; error = error - 2*deltay
  3010. stee2:    add    dx,ax            ; error = error + 2*deltax
  3011.     call    pincy            ; increment y
  3012.     loop    stee1
  3013. ;;;    jmp    plotex
  3014.  
  3015. plotex:    pop    dx            ; al has orginal pixel op
  3016.     mov    ccode,dl        ; restore it
  3017.     pop    es
  3018.     pop    di
  3019.     pop    si
  3020.     pop    dx            ; restore the world
  3021.     pop    cx
  3022.     pop    bx
  3023.     pop    ax
  3024.     ret
  3025. LINE    ENDP
  3026.  
  3027. ; Draw a rectangle.
  3028. ;  lower left corner: x = param[0], y = param[2], Tek coordinates
  3029. ;  distance: dx = param[4], dy = param[6], Tek coordinates, all positive
  3030. rectdraw proc    near
  3031.     push    x_coord
  3032.     push    y_coord
  3033.     mov    ax,param[0]        ; lower left corner is start, x part
  3034.     mov    bx,param[2]        ; y part
  3035.     push    ax            ; x0
  3036.     push    bx            ; y0
  3037.     mov    cl,0            ; moveto
  3038.     call    tekdraw
  3039.     pop    bx
  3040.     pop    ax
  3041.     add    bx,param[6]        ; y0 + dy
  3042.     mov    cl,1            ; draw x0,y0  to  x0,y0+dy
  3043.     push    ax
  3044.     push    bx
  3045.     call    tekdraw
  3046.     pop    bx
  3047.     pop    ax
  3048.     add    ax,param[4]        ; x0+dx
  3049.     mov    cl,1            ; draw x0,y0+dy  to  x0+dx,y0+dy
  3050.     push    ax
  3051.     call    tekdraw
  3052.     pop    ax
  3053.     mov    bx,param[2]        ; y0
  3054.     push    bx
  3055.     mov    cl,1
  3056.     call    tekdraw
  3057.     pop    bx
  3058.     mov    ax,param[0]        ; x0
  3059.     mov    cl,1
  3060.     call    tekdraw            ; complete the box
  3061.     pop    y_coord
  3062.     pop    x_coord
  3063.     ret
  3064. rectdraw endp
  3065.  
  3066. ; Fill a rectangle with a given pattern.
  3067. ;  lower left corner: x = param[0], y = param[2], Tek coordinates
  3068. ;  distance: dx = param[4], dy = param[6], Tek coordinates, all positive
  3069. ;  fill pattern = param[8]
  3070. rectfil    proc    near
  3071.     push    oldx
  3072.     push    oldy            ; save regular point/line old coords
  3073.     mov    ax,param        ; get Tek X coord of lower left corner
  3074.     mov    bx,param[2]        ; get Tek Y coord
  3075.     call    scale            ; convert to PC in ax,bx, scalex/y
  3076.     mov    rectx1,ax        ; lower left corner in PC coords
  3077.     mov    recty1,bx
  3078.     mov    ax,param        ; convert ending points, start Tek X
  3079.     add    ax,param[4]        ; Tek X + DX
  3080.     mov    bx,param[2]        ; start Tek Y
  3081.     add    bx,param[6]        ; Tek Y + DY
  3082.     call    scale
  3083.     pop    oldy
  3084.     pop    oldx
  3085.     mov    rectx2,ax        ; upper right corner PC X coord
  3086.     mov    recty2,bx        ; upper right corner PC Y coord
  3087.     mov    si,rectx1        ; starting x PC coord to si
  3088.     mov    di,recty2        ; starting y PC coord to di
  3089.     mov    cx,recty1        ; plotting from top down on screen
  3090.     sub    cx,bx            ; cx = # scan lines - 1
  3091.     mov    numlines,cx        ; remember here
  3092.     mov    bx,param[8]        ; fill pattern number
  3093.     or    bx,bx            ; zero?
  3094.     jz    rectfi1            ; z = yes, use current pointer
  3095.     cmp    bx,numfil        ; pattern number is too large?
  3096.     ja    rectfi1            ; a = yes, use current pointer
  3097.     dec    bx            ; count internally from 0
  3098.     shl    bx,1            ; make this a word pointer
  3099.     mov    bx,fillist[bx]        ; get pointer to pattern
  3100.     mov    fillptr,bx        ; remember it here
  3101. rectfi1:mov    cx,rectx2        ; ending x coord
  3102.     sub    cx,rectx1        ; number of horizontal pixels - 1
  3103.     inc    cx            ; number of horizontal pixels
  3104.     call    psetup            ; set up dsp and di to screen offset
  3105.             ; di points to whole byte, do bits in byte in gfplot
  3106. rectfi2:push    bx
  3107.      mov    bx,recty1        ; lower screen y (larger value)
  3108.     sub    bx,numlines        ; alignment: global screen sync
  3109.     and    bx,7            ; modulo 8
  3110.     add    bx,fillptr        ; offset of fill pattern start
  3111.     mov    bl,[bx]            ; pattern byte
  3112.     mov    fill,bl            ; save here for gfplot
  3113.     pop    bx
  3114.     call    gfplot            ; line fill routine
  3115.     call    pincy            ; next line
  3116.     dec    numlines
  3117.     jns    rectfi2            ; ns = more to do
  3118.     ret
  3119. rectfil    endp
  3120.  
  3121. ;;;;;;; EGA plot support routines
  3122. psetupe    proc    near            ; EGA setup for plotting
  3123.     push    ax
  3124.     mov    linelen,80        ; for y going down screen by pincy
  3125.     mov    ax,segscn        ; set es to screen memory segment
  3126.     mov    es,ax
  3127.     mov    ax,0205h        ; mode: write mode 2
  3128.     call    ega_gc
  3129.     mov    ax,0003h        ; assume writing bits directly
  3130.     test    ccode,pixfor+pixbak    ; direct foreground/background write?
  3131.     jnz    psete2            ; nz = yes
  3132.     mov    ax,1003h        ; assume OR
  3133.     test    ccode,pixor        ; OR?
  3134.     jnz    psete2            ; nz = yes
  3135.     mov    ax,1803h        ; assume XOR
  3136.     test    ccode,pixxor        ; inverting bits?
  3137.     jnz    psete2            ; nz = yes
  3138.     mov    ax,0803h        ; then use AND
  3139. psete2:    call    ega_gc            ; set controller
  3140.     mov    ax,80            ; compute starting point in regen buff
  3141.     mul    di
  3142.     mov    di,ax            ; di = di * 80
  3143.     pop    ax
  3144.     ret
  3145. psetupe    endp
  3146.  
  3147. pincye    proc    near            ; EGA inc y
  3148.     add    di,linelen        ; includes sign of deltay
  3149.     ret
  3150. pincye    endp
  3151.  
  3152. pltega    proc    near        ; EGA plot(x,y). x is in si, y is in di
  3153.     ror    bp,1            ; rotate line pattern
  3154.     jc    pltega1            ; c = a 1 bit to be plotted
  3155.     cmp    ccode,pixfor+pixbak    ; plot both 1's and 0's?
  3156.     je    pltega1            ; e = yes
  3157.     ret                ; else ignore the 0 bit
  3158. pltega1:push    bx
  3159.     push    si
  3160.     push    di
  3161.     mov    bx,si            ; want si/8 for bytes along line
  3162.     shr    si,1
  3163.     shr    si,1
  3164.     shr    si,1
  3165.     add    di,si            ; starting point in regen buffer
  3166.     and    bx,0007h        ; leave lower 3 bits for bit in byte
  3167.     mov    bh,masktab[bx]        ; 0-7 into bit mask in byte, x pos
  3168.     mov    bl,ccode        ; get line type code
  3169.     call    ega_plt
  3170.     pop    di
  3171.     pop    si
  3172.     pop    bx
  3173.     ret
  3174. pltega    endp
  3175.  
  3176. ; Plot bit pattern in "fill" as 8 horizontal pixels, starting at x,y (si,di)
  3177. ; and continuing across the line for cx pixels. psetupe has been called.
  3178. bpltega    proc    near        ; EGA plot(x,y). x is in si, y is in di
  3179.     push    bx
  3180.     push    cx
  3181.     push    si
  3182.     push    di
  3183.     mov    bx,si            ; want si/8 for bytes along line
  3184.     shr    si,1
  3185.     shr    si,1
  3186.     shr    si,1
  3187.     add    di,si            ; starting byte in regen buffer
  3188.                     ; di = offset in regen buffer
  3189.     and    bl,7            ; get bit in byte (di = byte aligned)
  3190.     jz    bplteg1            ; z = aligned already
  3191.     xchg    bl,cl            ; get shift to cl, low count to bl
  3192.     mov    bh,fill            ; 8-bit fill pattern
  3193.     mov    al,bh            ; get complement of pattern too
  3194.     not    al
  3195.     shl    bh,cl            ; trim cl bits from the left
  3196.     shr    bh,cl
  3197.     shl    al,cl            ; trim them from the right edge
  3198.     shr    al,cl            ; restore pattern
  3199.     xchg    cl,bl            ; put count back in cx
  3200.     add    cl,bl            ; add bits taken care of
  3201.     adc    ch,0
  3202.     jmp    short bplteg2        ; do this partial byte now
  3203.  
  3204. bplteg1:mov    bh,fill            ; fill pattern
  3205.     mov    al,bh            ; make inverted pattern
  3206.     not    al
  3207.     cmp    cx,8            ; do all 8 bits?
  3208.     jae    bplteg2            ; ae = yes
  3209.     push    cx            ; final byte fixup
  3210.     sub    cl,8            ; cl = - (number of bits to omit)
  3211.     neg    cl            ; cl = number of bits to omit
  3212.     mov    al,bh            ; get complement of pattern too
  3213.     not    al
  3214.     shr    bh,cl            ; trim them from the right edge
  3215.     shl    bh,cl            ; restore pattern
  3216.     shr    al,cl            ; trim them from the right edge
  3217.     shl    al,cl            ; restore pattern
  3218.     pop    cx
  3219. bplteg2:push    ax
  3220.     cmp    ccode,pixfor+pixbak    ; do both fore and background?
  3221.     jne    bplteg2a        ; ne = no
  3222.     push    bx
  3223.     mov    bh,al            ; get complemented pattern
  3224.     mov    bl,pixbak        ; write background
  3225.     call    ega_plt
  3226.     pop    bx
  3227. bplteg2a:mov    bl,ccode        ; get line type code
  3228.     call    ega_plt
  3229. bplteg3:pop    ax
  3230.     inc    di            ; next byte right
  3231.     sub    cx,8            ; did these
  3232.     cmp    cx,0            ; anything left to do?
  3233.     jg    bplteg1            ; a = yes, repeat
  3234.     pop    di
  3235.     pop    si
  3236.     pop    cx
  3237.     pop    bx
  3238.     ret
  3239. bpltega    endp
  3240.  
  3241. ;;;;;;;; CGA plot support routines
  3242. ; The CGA graphics memory mapping in mode 6 (640 by 200) is 8 dots per byte,
  3243. ; left most dot in the high bit, 80 bytes per scan line, scan line segments
  3244. ; alternating between 0b800h (even lines 0, 2, ...) and 0ba00h (odd lines).
  3245. psetupc    proc    near            ; CGA setup for plotting
  3246.     push    ax
  3247.     push    cx
  3248.     mov    linelen,80        ; 80 bytes per scan line
  3249.     mov    cx,segscn
  3250.     mov    es,cx
  3251.     mov    cx,di            ; save copy of di, start y line
  3252.                     ; compute starting point in regen buff
  3253.     shr    di,1            ; half the lines in each bank
  3254.     mov    ax,80            ; 80 bytes per line
  3255.     mul    di
  3256.     mov    di,ax            ; di = di * 80 / 2
  3257.     test    cx,1            ; even or odd line
  3258.     jz    psetc1            ; z = even
  3259.     add    di,2000h        ; offset to odd bank (seg 0ba00h)
  3260. psetc1:    and    di,3fffh
  3261.     pop    cx
  3262.     pop    ax
  3263.     ret
  3264. psetupc    endp
  3265.  
  3266. pincyc    proc    near            ; CGA inc y
  3267.     cmp    linelen,0        ; increasing or decreasing y?
  3268.     jl    pinyc2            ; l = decreasing
  3269.     cmp    di,2000h        ; in upper bank now?
  3270.     jb    pinyc1            ; b = no, in lower bank
  3271.     add    di,linelen        ; add a line
  3272. pinyc1:    add    di,2000h        ; switch banks
  3273.     and    di,3fffh        ; roll over address
  3274.     ret
  3275. pinyc2:    cmp    di,2000h        ; in upper bank now?
  3276.     jae    pinyc4            ; ae = yes
  3277.     add    di,linelen        ; subtract a line
  3278. pinyc4:    add    di,2000h        ; switch banks
  3279.     and    di,3fffh        ; roll over address
  3280.     ret
  3281. pincyc    endp
  3282.  
  3283. pltcga    proc    near        ; CGA plot(x,y). x is in si, y is in di
  3284.     push    bx        ; used for HGA and Wyse plots also.
  3285.     push    si
  3286.     push    di
  3287.     ror    bp,1            ; rotate line pattern
  3288.     jc    pltcg6            ; c = 1 bit to be plotted
  3289.     cmp    ccode,pixfor+pixbak    ; plot both 1's and 0's?
  3290.     jne    pltcg3            ; ne = no
  3291.  
  3292. pltcg6:    mov    bx,si            ; want si/8 for bytes along line
  3293.     shr    si,1
  3294.     shr    si,1
  3295.     shr    si,1
  3296.     add    di,si            ; starting point in regen buffer
  3297.     and    bx,0007h        ; leave lower 3 bits for bit in byte
  3298.                     ; di = offset in regen buffer
  3299.     mov    bh,masktab[bx]        ; 0-7 into bit mask in byte. x position
  3300.     mov    bl,ccode        ; get line type code
  3301.     test    bl,pixfor+pixor        ; draw in foreground color or OR?
  3302.     jz    pltcg1            ; z = no
  3303.     test    bl,pixor        ; OR?
  3304.     jnz    pltcg5            ; nz = yes
  3305.     test    gfcol,7            ; is foreground dark?
  3306.     jz    pltcg4            ; z = yes, punch a hole
  3307. pltcg5:    or    es:[di],bh        ; drawn
  3308.     jmp    short pltcg3
  3309. pltcg1:    test    bl,pixbak        ; draw in background (erase)?
  3310.     jz    pltcg2            ; z = no
  3311.     test    gbcol,7            ; is background light?
  3312.     jnz    pltcg5            ; nz = yes
  3313. pltcg4:    not    bh            ; invert the bit
  3314.     and    es:[di],bh        ; erase the dot
  3315.     jmp    short pltcg3
  3316. pltcg2:    xor    es:[di],bh        ; xor in this color
  3317. pltcg3:    pop    di
  3318.     pop    si
  3319.     pop    bx
  3320.     ret
  3321. pltcga    endp
  3322.  
  3323. ; Plot bit pattern in fill as 8 horizontal pixels, starting at x,y (si,di)
  3324. ; and continuing across the line for cx pixels. psetupc has been called.
  3325. bpltcga    proc    near        ; CGA plot(x,y). x is in si, y is in di
  3326.     push    bx        ; used for HGA and Wyse plots also.
  3327.     push    cx
  3328.     push    si
  3329.     push    di
  3330.     mov    bx,si            ; want si/8 for bytes along line
  3331.     shr    si,1
  3332.     shr    si,1
  3333.     shr    si,1
  3334.     add    di,si            ; starting byte in regen buffer
  3335.                     ; di = offset in regen buffer
  3336.     and    bl,7            ; get bit in byte (di = byte aligned)
  3337.     jz    bpltcg5            ; z = aligned already
  3338.     xchg    bl,cl            ; get shift to cl, low count to bl
  3339.     mov    bh,fill            ; 8-bit fill pattern
  3340.     mov    al,bh            ; get complement of pattern too
  3341.     not    al
  3342.     shl    bh,cl            ; trim cl bits from the left
  3343.     shr    bh,cl
  3344.     shl    al,cl            ; trim them from the right edge
  3345.     shr    al,cl            ; restore pattern
  3346.     xchg    cl,bl            ; put count back in cx
  3347.     add    cl,bl            ; add bits taken care of
  3348.     adc    ch,0
  3349.     jmp    short bpltcg4        ; do this partial byte now
  3350.  
  3351. bpltcg5:mov    bh,fill            ; fill pattern
  3352.     mov    al,bh            ; make inverted pattern
  3353.     not    al
  3354.     cmp    cx,8            ; do all 8 bits?
  3355.     jae    bpltcg4            ; ae = yes
  3356.     push    cx            ; final byte fixup
  3357.     sub    cl,8            ; cl = - (number of bits to omit)
  3358.     neg    cl            ; cl = number of bits to omit
  3359.     mov    al,bh            ; get complement of pattern too
  3360.     not    al
  3361.     shr    bh,cl            ; trim them from the right edge
  3362.     shl    bh,cl            ; restore pattern
  3363.     shr    al,cl            ; trim them from the right edge
  3364.     shl    al,cl            ; restore pattern
  3365.     pop    cx
  3366. bpltcg4:mov    bl,ccode        ; get line type code
  3367.     test    bl,pixfor+pixor        ; draw in foreground?
  3368.     jz    bpltcg1            ; z = no
  3369.     test    bl,pixor        ; OR?
  3370.     jnz    bpltcg7            ; nz = yes
  3371.     test    gfcol,7            ; is foreground dark?
  3372.     jz    bpltcg6            ; z = yes, punch a hole
  3373. bpltcg7:or    es:[di],bh        ; drawn
  3374.     jmp    short bpltcg3
  3375. bpltcg1:test    bl,pixbak        ; draw as background (erase)?
  3376.     jz    bpltcg2            ; z= do not draw as background (erase)
  3377.     test    gbcol,7            ; is background light?
  3378.     jnz    bpltcg7            ; nz = yes
  3379. bpltcg6:not    bh
  3380.     and    es:[di],bh        ; erase the dots
  3381.     jmp    short bpltcg3
  3382. bpltcg2:xor    es:[di],bh        ; xor in this color
  3383. bpltcg3:inc    di            ; next byte right
  3384.     sub    cx,8            ; did these
  3385.     cmp    cx,0            ; anything left to do?
  3386.     jg    bpltcg5            ; a = yes, repeat
  3387.     pop    di
  3388.     pop    si
  3389.     pop    cx
  3390.     pop    bx
  3391.     ret
  3392. bpltcga    endp
  3393.  
  3394. ;;;;;;; Wyse-700 plot support routines
  3395. ; The Wyse graphics memory map in mode 0D3h (1280 by 800) is 8 dots per byte,
  3396. ; left most dot in the high bit, 160 bytes per scan line, scan line segments
  3397. ; sequence as 0a000h even lines, and same for odd lines
  3398. psetupw proc    near            ; Wyse setup for plotting
  3399.     push    ax
  3400.     push    cx
  3401.     push    dx
  3402.     mov    linelen,160        ; for y going down screen by incy
  3403.     mov    ax,segscn        ; base segment of display memory
  3404.     mov    es,ax
  3405.     mov    cx,di            ; save copy of di, start y line
  3406.                     ; compute starting point in regen buff
  3407.     shr    di,1            ; half the lines in each bank
  3408.     mov    ax,160
  3409.     mul    di
  3410.     mov    di,ax            ; di = di * 160 / 2
  3411.     mov    dx,wymode
  3412.     shr    cx,1            ; compute bank from 1 lsb of line num
  3413.     jnc    psetw2            ; nc = it is in bank 0 (0b000h)
  3414.     mov    ax,wybodd        ; select odd bank
  3415.     out    dx,al
  3416.     jmp    short psetw3
  3417. psetw2: mov    ax,wybeven        ; select even bank
  3418.     out    dx,al
  3419. psetw3: mov    bnkchan, al        ; bank has changed
  3420.     pop    dx
  3421.     pop    cx
  3422.     pop    ax
  3423.     ret
  3424. psetupw endp
  3425.  
  3426. ;
  3427. ; Wyse-700 has two banks. Line 0, 2, 4 ... are in bank 0, and 1, 3, 5 ... are
  3428. ; in bank 1. Lines 0 and 1 have same addresses, lines 2 and 3 have same
  3429. ; addresses etc. We have to change bank every time Y changes but we
  3430. ; have to count new address only after two Y-value changes. Variable
  3431. ; bnkchan is a flag for us to know into which bank to write.
  3432. ;
  3433. pincyw    proc    near            ; Wyse inc y, step offset of line
  3434.     push    ax
  3435.     push    dx
  3436.     mov    dx,wymode        ; Wyse conrol register
  3437.     mov    al,wybeven        ;
  3438.     cmp    bnkchan,wybeven        ; was last write into even bank ?
  3439.     jne    pincywe            ; ne = no
  3440.     mov    al,wybodd        ; yes, set ready for odd bank
  3441.     out    dx,al            ;
  3442.     mov    bnkchan,al        ; set to odd
  3443.     jmp    short pincywo
  3444. pincywe:mov    al,wybeven        ; set ready foe even bank
  3445.     out    dx,al            ; select it
  3446.     mov    bnkchan,al        ; set to odd
  3447. pincywo:cmp    linelen,0        ; increasing y?
  3448.     jg    pinyw2            ; g = yes
  3449.     cmp    al,wybeven        ; from high (1) to low (0) bank ?
  3450.     je    pinyw4            ; e = yes
  3451.     add    di,linelen        ; no, add a line
  3452.     jmp    short pinyw4
  3453. pinyw2: cmp    al,wybodd        ; from low (0) to high (1) bank ?
  3454.     je    pinyw4            ; e = yes
  3455.     add    di,linelen        ; no, add a line
  3456. pinyw4: and    di,0ffffh        ; roll over address
  3457.     pop    dx
  3458.     pop    ax
  3459.     ret
  3460. pincyw    endp
  3461.  
  3462. ;;;;;;; HGA plot support routines
  3463. ; The HGA graphics memory mapping in mode 255 (720 by 348) is 8 dots per byte,
  3464. ; left most dot in the high bit, 90 bytes per scan line, scan line segments
  3465. ; sequence as 0b000h, 0b200h, 0b400h, 0b800h for lines 0-3 and repeat 90 bytes
  3466. ; higher for the rest.
  3467. psetuph    proc    near            ; HGA setup for plotting
  3468.     push    ax
  3469.     push    cx
  3470.     mov    linelen,90        ; for y going down screen by incy
  3471.     mov    ax,segscn        ; base segment of display memory
  3472.     mov    es,ax
  3473.     mov    cx,di            ; save copy of di, start y line
  3474.                     ; compute starting point in regen buff
  3475.     shr    di,1            ; quarter the lines in each bank
  3476.     shr    di,1
  3477.     mov    ax,90
  3478.     mul    di
  3479.     mov    di,ax            ; di = di * 90 / 4
  3480.     and    cx,3            ; compute bank from 2 lsb of line num
  3481.     jcxz    pseth2            ; z means it is in bank 0 (0b000h)
  3482. pseth1:    add    di,2000h        ; add offset for each bank
  3483.     loop    pseth1            ; do cx times
  3484. pseth2:    pop    cx
  3485.     pop    ax
  3486.     ret
  3487. psetuph    endp
  3488.  
  3489. pincyh    proc    near            ; HGA inc y, step offset of line
  3490.     cmp    linelen,0        ; increasing y?
  3491.     jg    pinyh2            ; g = yes
  3492.     cmp    di,2000h        ; in lowest for four banks?
  3493.     ja    pinyh1            ; a = no
  3494.     add    di,linelen        ; yes, add a line
  3495. pinyh1:    add    di,6000h        ; move back by adding a lot
  3496.     and    di,7fffh        ; roll over address
  3497.     ret
  3498. pinyh2:    cmp    di,6000h        ; in top most bank?
  3499.     jb    pinyh4            ; b = no
  3500.     add    di,linelen        ; yes, first add a line
  3501. pinyh4:    add    di,2000h        ; switch to next bank
  3502.     and    di,7fffh        ; roll over address
  3503.     ret
  3504. pincyh    endp
  3505.  
  3506. ;;;;;;; AT&T-Olivetti, Toshiba, VAXmate Graphics Adapter plot support routines
  3507. ; The graphics memory mapping in 640 by 400 mode is 8 dots per byte,
  3508. ; left most dot in the high bit, 80 bytes per scan line, scan line segments
  3509. ; sequence as 0b800h, 0ba00h, 0bc00h, 0be00h for lines 0-3 and repeat 80 bytes
  3510. ; higher for the rest. Use Hercules line incrementing (inc y) and CGA dot
  3511. ; writing. This is a monographic display.
  3512. psetupo    proc    near            ; setup for plotting
  3513.     push    ax
  3514.     push    cx
  3515.     mov    linelen,80        ; for y going down screen by incy
  3516.     mov    ax,segscn        ; base segment of display memory
  3517.     mov    es,ax
  3518.     mov    cx,di            ; save copy of di, start y line
  3519.                     ; compute starting point in regen buff
  3520.     shr    di,1            ; quarter the lines in each bank
  3521.     shr    di,1
  3522.     mov    ax,80
  3523.     mul    di
  3524.     mov    di,ax            ; di = di * 80 / 4
  3525.     and    cx,3            ; compute bank from 2 lsb of line num
  3526.     jcxz    pseto2            ; z means it is in bank 0 (0b800h)
  3527. pseto1:    add    di,2000h        ; add offset for each bank
  3528.     loop    pseto1            ; do cx times
  3529. pseto2:    pop    cx
  3530.     pop    ax
  3531.     ret
  3532. psetupo    endp
  3533.  
  3534. ;;;;;;;; Monochrome, simulate dots with text char
  3535. psetupm    proc    near
  3536.     mov    linelen,1        ; 80 characters but one line
  3537.     ret
  3538. psetupm    endp
  3539.  
  3540. pltmon    proc    near            ; Monochrome dot plot
  3541.     mov    x_coord,si        ; put dot at row=di, col=si, PC Coord
  3542.     mov    y_coord,di
  3543.     push    ax
  3544.     mov    al,'+'            ; our dot character
  3545.     call    mputc            ; display text char
  3546.     pop    ax
  3547.     ret
  3548. pltmon    endp
  3549.  
  3550. ; Plot bit pattern in fill as 8 horizontal pixels, starting at x,y (si,di)
  3551. ; and continuing across the line for cx pixels. Destroys CX.
  3552. bpltmon    proc    near        ; Mono plot(x,y). x is in si, y is in di
  3553.     jmp    pltmon        ; a dummy for the present
  3554. bpltmon    endp
  3555.  
  3556. pincym    proc    near            ; Monochrome inc y
  3557.     add    di,linelen        ; includes sign
  3558.     ret
  3559. pincym    endp
  3560.  
  3561. ; GPUTC - a routine to send text characters from font to true graphics boards
  3562. ; such as EGA, Hercules or CGA. Char is in al. Drawing routine ptr is gcplot.
  3563.      
  3564. gputc    proc    near
  3565.     cmp    al,' '            ; control character or space?
  3566.     ja    gputc1            ; a = no, display the char
  3567.     jmp    putctrl            ; else handle controls at putctrl
  3568. gputc1:    push    ax            ; first save some registers
  3569.     push    bx
  3570.     push    cx
  3571.     push    es
  3572.     push    di
  3573.      mov    bl,al            ; now BL has char to be displayed
  3574.     and    bl,7fh            ; no high bits allowed here
  3575.                     ; set board mode
  3576.     mov    di,y_coord        ; get current y coord (char bottom)
  3577.     sub    di,7            ; start 7 lines higher
  3578.     jnc    gputc2            ; nc = ok
  3579.     xor    di,di            ; move up to first line
  3580.     mov    y_coord,7        ; and reset scan line indicator
  3581. gputc2:    call    psetup    ; enter with di=line number, sets es:di to start of
  3582.             ; line in regen buffer and sets byte-wide plot mode
  3583.     mov    ax,x_coord        ; compute regen buffer byte
  3584.     shr    ax,1            ; want x_coord/8 for bytes along line
  3585.     shr    ax,1
  3586.     shr    ax,1
  3587.     add    di,ax            ; byte in regen buffer
  3588.     xor    bh,bh
  3589.     sub    bx,32            ; characters in font start at 32
  3590.     shl    bx,1
  3591.     shl    bx,1            ; 8 bytes per char, hence * 8
  3592.     shl    bx,1
  3593.     mov    cx,8            ; 8 bytes (scan lines) to transfer
  3594.     call    gcplot            ; call character plot routine
  3595.     call    incx            ; move to next char position
  3596.     pop    di
  3597.     pop    es
  3598.     pop    cx
  3599.     pop    bx
  3600.     pop    ax
  3601.     ret
  3602. gputc    endp
  3603.  
  3604. putctrl    proc    near            ; CONTROL CHARS = cursor movement     
  3605.     push    ax            ; save character
  3606.     cmp    al,FF            ; formfeed?
  3607.      jne    putct0            ; ne = no
  3608.     call    TEKCLS            ; FF clears the screen
  3609.     jmp    putctx
  3610. putct0:    cmp    al,BS            ; BS? sends (logical) cursor back one
  3611.     jne    putct2            ; ne = no, try next
  3612.     sub    x_coord,8        ; delete 8 dots (move left)
  3613.     jnc    putct1            ; nc = ok
  3614.     mov    x_coord,0        ; limit to left margin
  3615. putct1:    cmp    bscontrol,0        ; non-destructive backspace?
  3616.     je    putctx            ; e = yes
  3617.     push    x_coord
  3618.     mov    ah,ccode
  3619.     push    ax
  3620.     mov    ccode,pixbak        ; write in background
  3621.     mov    al,7fh            ; do all dots in background
  3622.     call    putc
  3623.     pop    ax
  3624.     mov    ccode,ah
  3625.     pop    x_coord            ; restore cursor
  3626.     jmp    short putctx
  3627. putct2:    cmp    al,TAB            ; tabs move forward one char position
  3628.     jne    putct4            ; ne = not a tab
  3629.     call    incx            ; let incx move cursor right one col
  3630.     jmp    putctx
  3631. putct4:    cmp    al,CR            ; <CR> means go to beginning of line
  3632.     jne    putct5
  3633.     mov    x_coord,0        ; zero the x coordinate
  3634.     jmp    putctx
  3635. putct5:    cmp    al,LF            ; <LF> means go down 8 pixels (1 line)
  3636.     jne    putct7            ; ne = not LF
  3637.     add    y_coord,8        ; border managed by outscrn and incx
  3638.     jmp    putctx
  3639. putct7:    cmp    al,VT            ; <VT> move up screen 1 line (8 pixels)
  3640.     jne    putct8
  3641.     sub    y_coord,8        ; subtract one line (8 pixels)
  3642.     jnc    putctx            ; nc = space left
  3643.     mov    y_coord,8        ; else set to top of screen
  3644.     jmp    short putctx
  3645.  
  3646. putct8:    cmp    al,' '            ; space?
  3647.     jne    putctx            ; ne = no
  3648.     cmp    spcontrol,0        ; non-destructive space?
  3649.     je    putct8a            ; e = yes
  3650.     mov    ah,ccode
  3651.     push    ax
  3652.     mov    ccode,pixbak        ; write in background
  3653.     mov    al,07fh            ; do all dots in background
  3654.     call    putc
  3655.     pop    ax
  3656.     mov    ccode,ah
  3657.     jmp    short putctx
  3658. putct8a:call    testfull        ; check on full screen
  3659.     call    incx
  3660. putctx:    pop    ax
  3661.     ret
  3662. putctrl    endp
  3663.  
  3664. mputc    proc    near            ; MONO put char in AL via Bios
  3665.     push    ax            ; updates x_coord,y_coord with
  3666.     push    bx            ; new cursor position
  3667.     push    cx
  3668.     push    dx
  3669.     xor    ah,ah            ; marker for cursor setting not needed
  3670.     cmp    al,' '            ; control code?
  3671.     jae    mputc1            ; ae = no, printable
  3672.     call    putctrl            ; do cursor arithmetic
  3673.     mov    ah,1            ; marker to set cursor but no display
  3674.  
  3675. mputc1:    push    ax            ; save char and marker
  3676.     mov    cl,3            ; char cell is 8 x 8 dots
  3677.     mov    ax,x_coord        ; get resulting cursor PC positions
  3678.     shr    ax,cl
  3679.     mov    dl,al            ; column
  3680.     mov    ax,y_coord
  3681.     sub    ax,7            ; minus 7 dots, like other modes
  3682.     jnc    mputc2            ; nc = non-negative
  3683.     mov    ax,7            ; else start at the top
  3684.     mov    y_coord,ax        ; here too
  3685. mputc2:    shr    ax,cl
  3686.     mov    dh,al            ; row
  3687.     mov    ah,2            ; set cursor to x_coord,y_coord
  3688.     xor    bh,bh            ; page 0
  3689.     int    screen
  3690.     pop    ax
  3691.     or    ah,ah            ; write a char in al?
  3692.     jnz    mputcx            ; nz = no
  3693.     mov    ah,09h            ; write char at cursor postion
  3694.     mov    cx,1            ; just one char
  3695.     xor    bh,bh            ; page 0
  3696.     mov    bl,gfcol        ; foreground coloring
  3697.     int    screen
  3698.     inc    dl            ; next column
  3699.     mov    ah,2            ; set real cursor ahead of last char
  3700.     int    screen
  3701.     call    incx            ; move logical cursor
  3702. mputcx:    pop    dx
  3703.     pop    cx
  3704.     pop    bx
  3705.     pop    ax
  3706.     ret
  3707. mputc    endp
  3708.  
  3709. incx    proc    near            ; move the logical cursor right
  3710.     mov    ax,xmax
  3711.     add    ax,8            ; last column+1
  3712.     cmp    ax,x_coord        ; beyond right most column?
  3713.     jae    incx1            ; ae = no
  3714.     mov    x_coord,ax        ; set up for wrap
  3715.     ret
  3716. incx1:    add    x_coord,8        ; shift the (logical) cursor right
  3717.     ret                ;  one character cell
  3718. incx    endp
  3719.  
  3720. ; EGA Character plot routine. Enter with bx pointing at font array for char
  3721. ; cx = number of bytes in char font, es:di = screen memory. Worker for gputc.
  3722. ; ccode: pixbak=plot in backgrd colors, pixfor=foregrd, pixxor=xor with screen
  3723. gcega    proc    near
  3724. gcega1:    mov    al,font[bx]        ; EGA byte plot: get bits from font
  3725.     push    bx
  3726.     cmp    chcontrol,0        ; transparent char writing?
  3727.     je    gcega2            ; e = yes
  3728.     mov    bh,0ffh            ; write these bits to clear field
  3729.     mov    bl,pixbak        ; in background coloring
  3730.     call    ega_plt            ; plot a byte
  3731. gcega2:    mov    bh,al            ; set bit pattern of character
  3732.     mov    bl,ccode        ; plot in back/fore/xor (ccode) colors
  3733.     call    ega_plt            ; byte plot routine for EGA systems
  3734.     pop    bx
  3735.     inc    bx            ; next byte of char pattern
  3736.     call    pincy            ; next scan line (linelen is preset)
  3737.     loop    gcega1
  3738.     ret
  3739. gcega    endp
  3740.  
  3741. ; General Character plot routine. Enter with bx pointing at font array for
  3742. ; char, cx = number of bytes in char font, es:di = screen memory.
  3743. ; Worker for gputc.
  3744.  
  3745. gcgen    proc    near
  3746. gcgen1:    mov    al,font[bx]        ; Non-EGA systems: get bits from font
  3747.     cmp    ccode,pixfor+pixbak    ; write both fore and back?
  3748.     jne    gcgen2            ; ne = no
  3749.     cmp    gfcol,0            ; is foreground dark?
  3750.     jne    gcgen1            ; ne = yes
  3751.     not    al            ; invert bits
  3752. gcgen1a:mov    es:[di],al        ; write bits directly
  3753.     jmp    short gcgen5
  3754. gcgen2:    test    ccode,pixfor+pixor    ; OR or write in foreground?
  3755.     jz    gcgen3            ; z = no
  3756.     not    al
  3757.     and    es:[di],al        ; clear bits to be written
  3758.     cmp    gfcol,0            ; is foreground dark?
  3759.     je    gcgen5            ; e = yes, done
  3760.     not    al
  3761.     or    es:[di],al        ; insert bits
  3762.     jmp    short gcgen5
  3763. gcgen3:    test    ccode,pixxor        ; XOR?
  3764.     jz    gcgen5            ; z = no
  3765.     xor    es:[di],al
  3766.     jmp    short gcgen5
  3767. gcgen4:    not    al            ; background write
  3768.     and    es:[di],al        ; clear bits
  3769.     cmp    gbcol,0            ; is background dark?
  3770.     je    gcgen5            ; e = yes
  3771.     not    al
  3772.     or    es:[di],al        ; write light bits
  3773. gcgen5:    inc    bx            ; point to next byte of char pattern
  3774.     call    pincy            ; next scan line (linelen is preset)
  3775.     loop    gcgen1            ; and repeat until complete
  3776.     ret
  3777. gcgen    endp
  3778.  
  3779. ; routines to manipulate ega graphics controller and mode register
  3780. ; command code in al, value in ah - destroys al and dx
  3781.      
  3782. ega_gc    proc    near            ; ega graphics controller
  3783.     mov    dx,3ceh
  3784.     out    dx,al            ; output command code
  3785.     inc    dx            ; dx is now data port
  3786.     mov    al,ah            ; get value to al
  3787.     out    dx,al            ; output value
  3788.     ret
  3789. ega_gc    endp
  3790. ega_md    proc    near            ; ega mode controller
  3791.     mov    dx,3c4h
  3792.     out    dx,al            ; output command code
  3793.     inc    dx            ; dx is now data port
  3794.     mov    al,ah            ; get value to al
  3795.     out    dx,al            ; output value
  3796.     ret
  3797. ega_md endp
  3798.      
  3799. ; Plot eight pixels using an EGA board
  3800. ; Enter with ES:[DI] pointing to screen address of byte,
  3801. ; bh has pattern of bits to be set, bl has attributes:
  3802. ;  pixbak = draw in background color, pixfor = draw in foreground color,
  3803. ;  pixor = OR with foreground color, pixxor = XOR with foreground color.
  3804. ; registers preserved
  3805. ; Note: this function operates on 8 pixels. One bits in bh select pixels to
  3806. ; be changed, bl determines which color planes will be affected for every
  3807. ; selected pixel.
  3808. ega_plt proc    near
  3809.     push    ax
  3810.     push    dx
  3811.     mov    dx,3ceh            ; (ega_gc) unprotect the bit positions
  3812.     mov    al,8            ; command to set bit mask register
  3813.     out    dx,al            ; output command code
  3814.     inc    dx            ; dx is now data port
  3815.     mov    al,bh            ; get pixels to be modified (1's)
  3816.     out    dx,al            ; output value (end of ega_gc)
  3817.     pop    dx
  3818.  
  3819.     mov    ah,gfcol        ; foreground color bit planes
  3820. ega1:    test    bl,pixfor+pixor        ; write foreground or OR?
  3821.     jnz    ega3            ; nz = yes
  3822.     mov    ah,gbcol        ; background color bit planes
  3823.     test    bl,pixbak        ; write in background coloring?
  3824.     jnz    ega3            ; nz = yes
  3825.     mov    ah,0fh            ; xor, touch each bit plane
  3826. ega3:    mov    al,es:[di]        ; latch byte
  3827.     mov    es:[di],ah        ; merge with untouched bits
  3828.     pop    ax
  3829.     ret
  3830. ega_plt endp
  3831.  
  3832. ; Presence test for Wyse-700: info in B000h and B800h are supposed to be equal
  3833. chkwyse    proc    near
  3834.     push    es
  3835.     push    ds
  3836.     mov    ax,0b800h        ; CGA segment
  3837.     mov    es,ax
  3838.     mov    ax,0b000h        ; Mono segment
  3839.     mov    ds,ax
  3840.     mov    ch,byte ptr es:[0]    ; CGA seg
  3841.     mov    cl,byte ptr ds:[0]    ; Mono seg
  3842.     push    cx            ; save original contents
  3843.     mov    byte ptr ds:[0],ch    ; copy CGA to Mono
  3844.     cmp    byte ptr ds:[0],ch    ; if different then not Wyse
  3845.     jne    chkwys1            ; ne = not Wyse
  3846.     not    byte ptr es:[0]        ; change CGA contents
  3847.     not    ch            ; and original pattern
  3848.     cmp    ch,byte ptr ds:[0]    ; if different then not Wyse
  3849.     jne    chkwys1            ; ne = not Wyse
  3850.     pop    cx
  3851.     mov    byte ptr es:[0],ch    ; restore CGA
  3852.     mov    byte ptr ds:[0],cl    ; restore Mono
  3853.     pop    ds
  3854.     pop    es
  3855.     clc
  3856.     ret
  3857.  
  3858. chkwys1:pop    cx
  3859.     mov    byte ptr es:[0],ch    ; restore CGA
  3860.     mov    byte ptr ds:[0],cl    ; restore Mono
  3861.     pop    ds
  3862.     pop    es
  3863.     stc
  3864.     ret
  3865. chkwyse    endp
  3866. ;
  3867. ; routine to set Wyse-700 board to graphics mode - 1280 * 800 & cls
  3868. ;
  3869. WYGRAF    PROC    NEAR
  3870.     push    ax
  3871.     push    bx            ; save used registers
  3872.     push    cx
  3873.     push    dx
  3874.     push    di
  3875.     xor    al,al
  3876.     mov    dx,wystoff        ; map video memory offset to zero
  3877.     out    dx,al            ;
  3878.     mov    dx,wystseg        ; map video memory segment to zero
  3879.     out    dx,al            ;
  3880.     mov    ax,segwyse        ; set es to Wyse start segment
  3881.     mov    es,ax            ;
  3882.     mov    al,wybeven        ; graph mode - even bank
  3883.     mov    dx,wymode        ; Wyse mode control register
  3884.     out    dx,al            ; select even bank
  3885.     cld
  3886.     xor    ax,ax            ; zero ax
  3887.     xor    di,di            ; start from zero
  3888.     mov    cx,0ffffh        ; clear 10000h bytes, whole even bank
  3889.     rep    stosb            ; store blanking char in whole screen
  3890.     mov    al,wybodd        ; graph mode - odd bank
  3891.     mov    dx,wymode        ; select it
  3892.     out    dx,al            ;
  3893.     xor    ax,ax            ; zero ax
  3894.     xor    di,di            ;
  3895.     mov    cx,0ffffh        ; clear 10000h bytes, whole odd bank
  3896.     rep    stosb            ; store blanking char in whole screen
  3897.     mov    bnkchan, 0        ; assume bank 0
  3898.     pop    di            ; restore regs
  3899.     pop    dx
  3900.     pop    cx
  3901.     pop    bx
  3902.     pop    ax
  3903.     ret
  3904. WYGRAF    ENDP
  3905.  
  3906. ; routine to set Hercules card to graphics mode - both pages are enabled
  3907.      
  3908. HGRAF    PROC    NEAR
  3909.     push    ax
  3910.     push    bx            ; save used registers
  3911.     push    cx
  3912.     push    si
  3913.     mov    al,grph            ; graph mode
  3914.     lea    si,gtable        ;  requires graphics table
  3915.     xor    bx,bx
  3916.     mov    cx,4000h        ; clear 4000h words
  3917.     call    setmd            ; and set the mode
  3918.     pop    si
  3919.     pop    cx
  3920.     pop    bx
  3921.     pop    ax
  3922.     ret
  3923. HGRAF    ENDP
  3924.      
  3925. ; set Hercules card to text mode
  3926.      
  3927. HTEXT    PROC    NEAR
  3928.     push    ax
  3929.     push    bx
  3930.     push    cx
  3931.     push    si
  3932.     mov    al,text            ; text mode
  3933.     lea    si,ttable        ; requires text table
  3934.     mov    bx,0720h        ; blank value (space, white on black)
  3935.     mov    cx,2000            ; whole screen to clear (80*25)
  3936.     call    setmd            ; set the mode
  3937.     pop    si
  3938.     pop    cx
  3939.     pop    bx
  3940.     pop    ax
  3941.     ret
  3942. HTEXT    ENDP
  3943.      
  3944. ; Hercules mode set - called from HTEXT and HGRAF
  3945.      
  3946. SETMD    PROC    NEAR
  3947.     push    dx
  3948.     push    ax
  3949.     mov    dx,config        ; configuration port
  3950.     mov    al,genable        ; allow graphics mode to be set
  3951.     out    dx,al
  3952.     pop    ax
  3953.     push    ax
  3954.     push    cx            ; save count
  3955.     mov    dx,cntrl        ; control port
  3956.     out    dx,al            ; set to text or graphics
  3957.     mov    dx,index        ; send 12 bytes from table to 6845
  3958.     mov    cx,12            ; number of registers to load
  3959.     xor    ah,ah            ; start with register 0 of 6845
  3960.     cld
  3961. setmd1:    jmp    $+2            ; small pause for hardware
  3962.     mov    al,ah            ; ah is counter
  3963.     out    dx,al            ; set register
  3964.     inc    dx            ; point to data port
  3965.     lodsb                ; get next byte in table
  3966.     jmp    $+2            ; small pause for hardware
  3967.     out    dx,al            ; and send to 6845
  3968.     inc    ah            ; next register
  3969.     dec    dx            ; point to register port
  3970.     loop    setmd1            ; and continue 'til cx=0
  3971.     pop    cx            ; recover count
  3972.     cld
  3973.     push    di
  3974.     push    es
  3975.     mov    ax,segscn        ; start of screen
  3976.     mov    es,ax
  3977.     xor    di,di
  3978.     mov    ax,bx            ; get blanking character
  3979.     rep    stosw            ; store blanking char in whole screen
  3980.     pop    es
  3981.     pop    di
  3982.     mov    dx,cntrl        ; now to re-enable screen
  3983.     pop    ax            ; get mode
  3984.     or    al,scrn_on        ; enable screen
  3985.     out    dx,al
  3986.     pop    dx
  3987.     ret
  3988. SETMD    ENDP
  3989.      
  3990. teksave    proc    near        ; saves graphics screen from page 0 to page 1
  3991.     push    si
  3992.     push    di
  3993.     cmp    gpage,0        ; only graphics page 0 on display board?
  3994.     je    teksavx        ; e = yes, no saving possible here
  3995.     mov    si,segscn    ; segment (!) of current screen
  3996.     cmp    graph_mode,ega
  3997.     je    teksav1
  3998.     cmp    graph_mode,monoega
  3999.     je    teksav1
  4000.     cmp    graph_mode,colorega
  4001.     je    teksav1
  4002.     cmp    graph_mode,hercules
  4003.     je    teksav2
  4004.     jmp    short teksavx    ; else nothing
  4005. teksav1:mov    di,segega+800h    ; EGA page 1 screen segment
  4006.     call    egasr        ; call common save/restore code
  4007.     jmp    short teksavx
  4008. teksav2:mov    di,seghga+800h    ; Hercules page 1 screen segment
  4009.     call    hgasr        ; call common save/restore code
  4010. teksavx:pop    di
  4011.     pop    si
  4012.     ret
  4013. teksave    endp
  4014.  
  4015. tekrest    proc    near        ; saves graphics screen of page 0 in page 1
  4016.     push    si
  4017.     push    di
  4018.     cmp    gpage,0        ; only graphics page 0 on display board?
  4019.      jne    tekres0        ; ne = no, more so work to do here
  4020.     call    tekcls1        ;  else clear the screen to color it
  4021.     jmp    short tekresx    ;  and exit
  4022. tekres0:mov    di,segscn    ; segment (!) of new graphics screen
  4023.     cmp    graph_mode,ega
  4024.     je    tekres1
  4025.     cmp    graph_mode,monoega
  4026.     je    tekres1
  4027.     cmp    graph_mode,colorega
  4028.     je    tekres1
  4029.     cmp    graph_mode,hercules
  4030.     je    tekres2
  4031.     jmp    short tekresx    ; else nothing
  4032. tekres1:mov    si,segega+800h    ; segment of EGA page 1
  4033.     call    egasr        ; call common save/restore code
  4034.     jmp    short tekresx
  4035. tekres2:mov    si,seghga+800h    ; segment of Hercules page 1
  4036.     call    hgasr        ; call common save/restore code
  4037. tekresx:pop    di
  4038.     pop    si
  4039.     ret
  4040. tekrest    endp
  4041.  
  4042. egasr    proc    near        ; common code for Tek ega save/restore ops
  4043.     push    ax
  4044.     push    cx
  4045.     push    dx
  4046.     mov    ax,0f00h    ; enable 4 plane set/resets
  4047.     call    ega_gc        ; set controller
  4048.     mov    ax,0f01h    ; enable Set/Reset register
  4049.     call    ega_gc
  4050.     mov    ax,0f02h    ; set color compare register for 4 planes
  4051.     call    ega_gc
  4052.     mov    ax,0905h    ; set mode reg: write latches, read mode
  4053.     call    ega_gc
  4054.     mov    ax,0ff02h    ; enable all planes
  4055.     call    ega_md
  4056.     mov    cx,ybot        ; last scan line
  4057.     inc    cx        ; number of scan lines
  4058.     mov    ax,80        ; bytes per scan line
  4059.     mul    cx
  4060.     mov    cx,ax
  4061.     push    es        ; save es
  4062.     push    ds        ; save ds
  4063.     mov    es,di        ; destination, set es to video memory
  4064.     mov    ds,si        ; source, set ds to video memory
  4065.     xor    si,si        ; clear offset fields
  4066.     xor    di,di
  4067.     cld            ; byte moves for ega adaptor
  4068.     rep    movsb        ; copy from page (ds:si) to page (es:di)
  4069.     pop    ds        ; recover ds
  4070.     pop    es        ; and other registers
  4071.     mov    ax,0000h    ; disable 4 plane set/resets
  4072.     call    ega_gc        ; set controller
  4073.     mov    ax,0001h    ; disable Set/Reset register
  4074.     call    ega_gc        ; set controller
  4075.     mov    ax,0002h    ; disable color compare register
  4076.     call    ega_gc
  4077.     mov    ax,1005h    ; set mode reg: write latches, odd/even
  4078.     call    ega_gc
  4079.     pop    dx
  4080.     pop    cx
  4081.     pop    ax
  4082.     ret
  4083. egasr    endp
  4084.  
  4085. hgasr    proc    near        ; Hercules save restore screen
  4086.     push    cx
  4087.     mov    cx,4000h    ; number of words to move
  4088.     push    es        ; save es
  4089.     push    ds        ; save ds
  4090.     mov    es,di        ; destination, set es to video memory
  4091.     mov    ds,si        ; source, set ds to video memory
  4092.     xor    si,si        ; clear offset fields
  4093.     xor    di,di
  4094.     cld
  4095.     rep    movsw        ; copy from page [si] to page [di]
  4096.     pop    ds        ; recover ds
  4097.     pop    es        ; and other registers
  4098.     pop    cx
  4099.     ret
  4100. hgasr    endp
  4101.  
  4102. dump    proc    far            ; Write screen as TIFF v5.0 file
  4103.     push    ax
  4104.     push    bx
  4105.     push    cx
  4106.     push    dx
  4107.     push    si
  4108.     push    di
  4109.     mov    si,offset dumpname    ; name of dump file
  4110.     mov    di,offset tempname    ; destination
  4111.     push    es
  4112.     push    ds
  4113.     pop    es
  4114.     mov    cx,dumplen        ; length of dump name
  4115.     cld
  4116.     repnz    movsb            ; copy it, asciiz
  4117.     pop    es
  4118.     mov    ax,offset tempname    ; address to ax for unique
  4119.     call    tunique            ; get unique name into ax
  4120.     mov    dx,ax            ; ds:dx is asciiz filename
  4121.     xor    cx,cx            ; normal attributes
  4122.     mov    ah,creat2        ; create the file
  4123.     int    dos
  4124.     jc    dmp2            ; c = failure
  4125. dmp1:    mov    dhandle,ax        ; file handle
  4126.     call    dmpdate            ; do time stamp
  4127.     cmp    plotptr,offset pltcga    ; using CGA style graphics?
  4128.     jne    dmp2            ; ne = no
  4129.     call    cgadmp            ; do CGA style dump routine
  4130.     jmp    short dmp3
  4131. dmp2:    call    egadmp
  4132. dmp3:    pop    di
  4133.     pop    si
  4134.     pop    dx
  4135.     pop    cx
  4136.     pop    bx
  4137.     pop    ax
  4138.     ret
  4139. dump    endp
  4140.  
  4141. ; CGA TIFF 5.0 screen-to-file dump routine
  4142. cgadmp    proc    near
  4143.     push    es            ; do the bookkeeping math first
  4144.     mov    bps.entval,1        ; bits/sample, mono
  4145.     mov    photo.entval,1        ; mono, one bit after the other
  4146.     mov    word ptr cmap.entcnt,0    ; no palette color map entries
  4147.     mov    ax,xmax            ; image width - 8 pixels
  4148.     add    ax,8            ; plus 8, for pixels per line
  4149.     mov    iwidth.entval,ax    ; store in directory
  4150.     mov    xresval,ax        ; x resolution
  4151.     mov    xresval+2,0        ; high order part
  4152.     mov    ax,ybot            ; lines per screen - 1
  4153.     inc    ax            ; lines per screen
  4154.     mov    ilength.entval,ax    ; image length, scan lines
  4155.     mov    yresval,ax        ; y resolution
  4156.     mov    yresval+2,0        ; high order part
  4157.     mov    cx,25            ; try dividing into this many strips
  4158. cgadmp5:xor    dx,dx            ; image pixels
  4159.     mov    ax,yresval        ; number of scan lines
  4160.     div    cx            ; try dividing into 25 strips,ax=quo
  4161.     or    dx,dx            ; did we get null remainder?
  4162.     loopnz    cgadmp5            ; nz = no, try again with fewer strips
  4163.     inc    cx            ; inc for dec by loop, cx = # strips
  4164.     mov    word ptr strip.entcnt,cx ; store number of strips
  4165.     mov    word ptr sbc.entcnt,cx    ; store number of strip byte counts
  4166.     mov    rps.entval,ax        ; rows per strip
  4167.     mul    linelen            ; rows/strip * bytes/row = bytes/strip
  4168.     push    cx            ; save strip count for loop below
  4169.     push    ds            ; ax = bytes per strip
  4170.     pop    es            ; es:di to our data segment
  4171.     mov    di,offset stripbc    ; where to write strip byte counts
  4172.     cld
  4173.     rep    stosw            ; write ax as bytes/strip, cx times
  4174.     pop    cx            
  4175.     mov    dx,ax            ; bytes/strip = increment, put here
  4176.     mov    di,offset stripoff    ; where we write
  4177.     mov    ax,offset pixdata-offset header ; where first strip starts
  4178. cgadmp4:stosw                ; write strip file offset
  4179.     mov    word ptr [di],0        ; high order part
  4180.     add    di,2            ; next double word
  4181.     add    ax,dx            ; next file strip offset
  4182.     loop    cgadmp4            ; do all strip offsets
  4183.                     ; file i/o starts here
  4184.     mov    bx,dhandle        ; dump's file handle
  4185.     mov    dx,offset header    ; write TIFF header and directory
  4186.     mov    cx,tifflen        ; length of header plus directory
  4187.     mov    ah,write2
  4188.     int    dos
  4189.     jc    cgadmp2            ; c = failure
  4190.     xor    di,di            ; start at y = top
  4191.     call    psetup            ; setup cga and di
  4192.     mov    cx,ybot            ; number of scan lines-1
  4193.     inc    cx            ; number of scan lines
  4194. cgadmp1:push    cx
  4195.     mov    cx,linelen        ; line length, bytes
  4196.     mov    dx,di            ; offset in screen buffer
  4197.     mov    bx,dhandle        ; file handle
  4198.     push    ds
  4199.     mov    ax,segscn        ; screen seg
  4200.     mov    ds,ax
  4201.     mov    ah,write2        ; write directly from screen memory
  4202.     int    dos
  4203.     pop    ds
  4204.     jc    cgadmp2            ; c = failure
  4205.     call    pincy            ; next line down, y = y + 1
  4206.     pop    cx
  4207.     loop    cgadmp1            ; do all scan lines
  4208. cgadmp2:mov    ah,close2        ; close the file
  4209.     int    dos
  4210.     mov    dhandle,-1        ; set handle to unused
  4211.     pop    es
  4212.     ret
  4213. cgadmp    endp
  4214.  
  4215. ; EGA TIFF 5.0 screen-to-file dump routine
  4216. egadmp    proc    near
  4217.     push    es            ; do the bookkeeping math first
  4218.     mov    bps.entval,4        ; bits/sample, iRGB
  4219.     mov    photo.entval,3        ; photo interp, palette
  4220.     mov    word ptr cmap.entcnt,3*16 ; palette color map entries
  4221.     mov    ax,xmax            ; image width - 8 pixels
  4222.     add    ax,8            ; plus 8, for pixels per line
  4223.     mov    iwidth.entval,ax    ; store in directory
  4224.     mov    xresval,ax        ; x resolution
  4225.     mov    xresval+2,0        ; high order part
  4226.     mov    ax,ybot            ; lines per screen - 1
  4227.     inc    ax            ; lines per screen
  4228.     mov    ilength.entval,ax    ; image length, scan lines
  4229.     mov    yresval,ax        ; y resolution
  4230.     mov    yresval+2,0        ; high order part
  4231.     mov    cx,25            ; try dividing into this many strips
  4232. egadmp10:xor    dx,dx            ; image pixels
  4233.     mov    ax,yresval        ; number of scan lines
  4234.     div    cx            ; try dividing into 25 strips, ax=quo
  4235.     or    dx,dx            ; did we get null remainder?
  4236.     loopnz    egadmp10        ; nz = no, try again with fewer strips
  4237.     inc    cx            ; inc for dec by loop, cx = # strips
  4238.     mov    word ptr strip.entcnt,cx ; store number of strips
  4239.     mov    word ptr sbc.entcnt,cx    ; store number of strip byte counts
  4240.     mov    rps.entval,ax        ; rows per strip
  4241.     shl    ax,1
  4242.     shl    ax,1            ; times 4 bits / pixel
  4243.     mul    linelen            ; rows/strip * bytes/row = bytes/strip
  4244.     push    cx            ; save strip count for loop below
  4245.     push    ds            ; ax = bytes per strip
  4246.     pop    es            ; es:di to our data segment
  4247.     mov    di,offset stripbc    ; where to write strip byte counts
  4248.     cld
  4249.     rep    stosw            ; write ax as bytes/strip, cx times
  4250.     pop    cx            
  4251.     mov    dx,ax            ; bytes/strip = increment, put here
  4252.     mov    di,offset stripoff    ; where we write
  4253.     mov    ax,offset pixdata-offset header ; where first strip starts
  4254.     xor    bx,bx
  4255. egadmp11:stosw                ; write strip file offset
  4256.     mov    es:[di],bx        ; high order part
  4257.     add    di,2            ; next double word
  4258.     add    ax,dx            ; next file strip offset
  4259.     adc    bx,0
  4260.     loop    egadmp11        ; do all strip offsets
  4261.                     ; screen to file i/o starts here
  4262.     mov    bx,dhandle        ; dump's file handle
  4263.     mov    dx,offset header    ; write TIFF header and directory
  4264.     mov    cx,tifflen        ; length of header plus directory
  4265.     mov    ah,write2
  4266.     int    dos
  4267.     jnc    egadmp12
  4268.     jmp    egadmp9            ; c = failure
  4269. egadmp12:
  4270.     xor    di,di            ; start at y = top
  4271.     call    psetup            ; setup adapter and es:di
  4272.     xor    di,di
  4273.     mov    bx,offset tempname    ; set buffer address
  4274.     mov    cx,ybot            ; number of scan lines-1
  4275.     inc    cx            ; number of scan lines
  4276. egadmp1:push    cx            ; save scan line counter
  4277.     mov    cx,linelen        ; 8*dots across the screen (640)
  4278. egadmp2:push    cx            ; save counter of inner loops
  4279.     mov    cx,4            ; number of planes to do
  4280.     mov    word ptr [bx],0        ; clear the four bytes for this loop
  4281.     mov    word ptr [bx+2],0
  4282. egadmp3:push    cx            ; save plane counter
  4283.     push    bx            ; don't advance buffer pointer here
  4284.     mov    dx,3ceh            ; (ega_gc)
  4285.     mov    al,4            ; command to select read map register
  4286.     out    dx,al            ; output command code
  4287.     inc    dx            ; dx is now data port
  4288.     mov    al,cl            ; do planes 3(I), then 2(R),1(G),0(B)
  4289.     dec    al            ; cx is one higher than plane
  4290.     out    dx,al            ; output value (end of ega_gc)
  4291.     mov    al,es:[di]        ; latch byte
  4292.                     ; got 8 bits from a plane
  4293.     mov    cx,4            ; do this for four output bytes
  4294. egadmp4:mov    ah,[bx]            ; eventually iRGB in each nibble
  4295.     shl    al,1            ; get left most pixel bit in plane
  4296.     jnc    egadmp5
  4297.     or    ah,8            ; set high nibble least sig bit
  4298. egadmp5:shl    al,1            ; odd numbered pixel
  4299.      rcl    ah,1            ; set low nibble least sig bit if c
  4300.     mov    [bx],ah
  4301.     inc    bx            ; next byte
  4302.     loop    egadmp4            ; do all four bytes
  4303.  
  4304.     pop    bx
  4305.     pop    cx            ; restore plane counter
  4306.     loop    egadmp3            ; do all planes
  4307.  
  4308.     inc    di            ; next screen memory address
  4309.     add    bx,4            ; just did four bytes
  4310.     cmp    bx,offset tempname+80    ; at end of 80 bytes?
  4311.     jb    egadmp6            ; b = no
  4312.     call    egadmpw            ; write the buffer
  4313.     mov    bx,offset tempname    ; reset buffer address
  4314.     jnc    egadmp6            ; nc = success
  4315.     pop    cx            ; clean stack
  4316.     pop    cx
  4317.     jmp    egadmp9            ; error
  4318.  
  4319. egadmp6:pop    cx            ; recover bytes per line counter
  4320.     loop    egadmp2            ; next group across scan line
  4321.     pop    cx            ; recover scan line counter
  4322.     loop    egadmp1            ; do next scan line
  4323.     call    egadmpw            ; flush the buffer for last scan line
  4324. egadmp9:mov    ah,close2        ; close the file
  4325.     mov    bx,dhandle
  4326.     int    dos
  4327.     mov    dhandle,-1        ; set handle to unused
  4328.     xor    di,di
  4329.     call    psetup
  4330.     pop    es
  4331.     ret
  4332.                        ; local worker
  4333. egadmpw:push    bx            ; write tempbuf from start to [bx-1]
  4334.     push    cx
  4335.     mov    dx,offset tempname    ; work buffer
  4336.     mov    cx,bx            ; buffer pointer to next free byte
  4337.     sub    cx,dx            ; buffer size to write
  4338.     cmp    cx,0
  4339.     jle    egadmpw1        ; le = nothing to write
  4340.     mov    bx,dhandle        ; file handle
  4341.     mov    ah,write2        ; write cx bytes from tempname
  4342.     int    dos
  4343.     jc    egadmpw2        ; c = error
  4344.     cmp    ax,cx            ; wrote all?
  4345.     jne    egadmpw2        ; ne = no
  4346. egadmpw1:clc                ; clc
  4347.     pop    cx
  4348.     pop    bx
  4349.     ret
  4350. egadmpw2:stc                ; carry set for failure
  4351.     pop    cx
  4352.     pop    bx
  4353.     ret
  4354.  
  4355. egadmp    endp
  4356.  
  4357. ; Worker. Write Kermit version and current date and time in TIFF header
  4358. dmpdate    proc    near
  4359.     mov    di,offset prog+10    ; place for version in prog field
  4360.     mov    ax,version        ; Kermit version
  4361.     call    dec2di            ; write the version
  4362.     mov    ah,getdate        ; DOS date (cx= yyyy, dh= mm, dl= dd)
  4363.     int    dos
  4364.     mov    di,offset dandt        ; where to write
  4365.     mov    ax,cx            ; get yyyy
  4366.     push    dx
  4367.     call    dec2di            ; write to buffer
  4368.     pop    dx
  4369.     mov    byte ptr [di],':'
  4370.     inc    di
  4371.     mov    al,dh            ; mm
  4372.     cmp    al,10            ; leading digit?
  4373.     jae    dmpdat1            ; ae = yes
  4374.     mov    byte ptr [di],'0'    ; make our own
  4375.     inc    di
  4376. dmpdat1:xor    ah,ah
  4377.     push    dx
  4378.     call    dec2di
  4379.     mov    byte ptr [di],':'
  4380.     pop    dx
  4381.     inc    di
  4382.     mov    al,dl            ; dd
  4383.     cmp    al,10            ; leading digit?
  4384.     jae    dmpdat2            ; ae = yes
  4385.     mov    byte ptr [di],'0'    ; make our own
  4386.     inc    di
  4387. dmpdat2:xor    ah,ah
  4388.     call    dec2di
  4389.     mov    byte ptr [di],' '
  4390.     inc    di
  4391.     mov    ah,gettim        ; DOS tod (ch=hh, cl=mm, dh=ss, dl=.s)
  4392.     int    dos
  4393.     push    dx            ; save dx
  4394.     xor    ah,ah
  4395.     mov    al,ch            ; Hours
  4396.     cmp    al,10            ; leading digit?
  4397.     jae    dmpdat3            ; ae = yes
  4398.     mov    byte ptr [di],'0'    ; make our own
  4399.     inc    di
  4400. dmpdat3:push    cx
  4401.     call    dec2di            ; write decimal asciiz to buffer
  4402.     pop    cx
  4403.     mov    byte ptr [di],':'
  4404.     inc    di
  4405.     xor    ah,ah
  4406.     mov    al,cl            ; Minutes
  4407.     cmp    al,10            ; leading digit?
  4408.     jae    dmpdat4            ; ae = yes
  4409.     mov    byte ptr [di],'0'    ; make our own
  4410.     inc    di
  4411. dmpdat4:call    dec2di            ; write decimal asciiz to buffer
  4412.     mov    byte ptr [di],':'
  4413.     inc    di
  4414.     pop    dx
  4415.     xor    ah,ah
  4416.     mov    al,dh            ; Seconds
  4417.     cmp    al,10            ; leading digit?
  4418.     jae    dmpdat5            ; ae = yes
  4419.     mov    byte ptr [di],'0'    ; make our own
  4420.     inc    di
  4421. dmpdat5:call    dec2di            ; write decimal asciiz to buffer
  4422.     inc    di
  4423.     ret
  4424. dmpdate    endp
  4425.  
  4426. ; Dispatch table processor. Enter with BX pointing at table of {char count,
  4427. ; address of action routines, characters}. Jump to matching routine or return.
  4428. ; Enter with AL holding received Final char.
  4429. atdispat proc near
  4430.     mov    cl,[bx]            ; get table length from first byte
  4431.     xor    ch,ch
  4432.     mov    di,bx            ; main table
  4433.     add    di,3            ; point di at first char in table
  4434.     push    es
  4435.     push    ds
  4436.     pop    es            ; use data segment for es:di below
  4437.     cld                ; set direction forward
  4438.     repne    scasb            ; find matching character
  4439.     pop    es
  4440.     je    atdisp2            ; e = found a match, get action addr
  4441.     cmp    al,' '            ; control char?
  4442.     jb    atdisp1            ; b = yes
  4443.     ret                ; ignore escape sequence
  4444. atdisp1:jmp    tekctl            ; process control char
  4445. atdisp2:sub    di,bx            ; distance scanned in table
  4446.     sub    di,4            ; skip count byte, address word, inc
  4447.     shl    di,1            ; convert to word index
  4448.     inc    bx            ; point to address of action routines
  4449.     mov    bx,[bx]            ; get address of action table
  4450.     jmp    word ptr [bx+di]    ; dispatch to the routine
  4451. atdispat endp
  4452.  
  4453. ansich    proc    near            ; insert Pn spaces at and after cursor
  4454.     mov    cx,param        ; get Pn
  4455.     or    cx,cx
  4456.     jnz    ansich1            ; got a value
  4457.     inc    cx            ; zero means one
  4458. ansich1:push    x_coord
  4459.     push    y_coord
  4460.     mov    al,spcontrol        ; preserve space control
  4461.     mov    tempname,al        ; save here
  4462.     mov    spcontrol,1        ; turn on destructive space
  4463.     and    x_coord,not 7        ; modulo 8x8 cells
  4464.     mov    ax,xmax            ; start of last cell
  4465.     sub    ax,x_coord        ; start of current cell
  4466.     shr    ax,1            ; divide by 8 dots per char
  4467.     shr    ax,1
  4468.     shr    ax,1
  4469.     cmp    ax,cx            ; want more spaces than are on line?
  4470.     jae    ansich2            ; ae = no
  4471.     mov    cx,ax            ; clip to right margin
  4472.     jcxz    ansich3            ; z = nothing to do
  4473. ansich2:push    cx
  4474.     mov    al,' '            ; a space
  4475.     call    outscrn            ; write to screen (BYPASS check??)
  4476.     pop    cx
  4477.     loop    ansich2            ; do them
  4478. ansich3:mov    al,tempname        ; space control
  4479.     mov    spcontrol,al        ; restored
  4480.     pop    x_coord
  4481.     pop    y_coord
  4482.     ret
  4483. ansich    endp
  4484.                     ; scaled by text screen height
  4485. atcuu    proc    near            ; cursor up Pn lines
  4486.     cmp    param,0            ; empty arg?
  4487.     jne    atcuu1            ; got a value
  4488.     inc    param            ; zero means one
  4489. atcuu1:    mov    ax,y_coord        ; where we are now
  4490.     add    ax,4            ; round up a smidge
  4491.     mov    cl,byte ptr low_rgt+1    ; highest text line
  4492.     xor    ch,ch
  4493.     mul    cx            ; proportion
  4494.     xor    dx,dx
  4495.     mov    cx,ybot            ; highest scan line
  4496.     div    cx            ; end, estimate currren text line
  4497.     sub    ax,param
  4498.     inc    ax            ; count lines from 1 again
  4499.     mov    param,ax        ; new text row
  4500.     jmp    atcva            ; do as absolute
  4501. atcuu    endp
  4502.  
  4503.                     ; scaled by text screen height
  4504. atcud    proc    near            ; cursor down Pn lines
  4505.     cmp    param,0            ; get Pn
  4506.     jne    atcud1            ; ne = got a value
  4507.     inc    param            ; zero means one
  4508. atcud1:    mov    ax,y_coord        ; where we are now
  4509.     add    ax,4            ; round up a smidge
  4510.     mov    cl,byte ptr low_rgt+1    ; highest text line
  4511.     xor    ch,ch
  4512.     mul    cx            ; proportion
  4513.     xor    dx,dx
  4514.     mov    cx,ybot            ; highest scan line
  4515.     div    cx            ; end, estimate currren text line
  4516.     inc    ax            ; count lines from 1 again
  4517.     add    param,ax        ; new text row
  4518.     jmp    atcva            ; do as absolute
  4519. atcud    endp
  4520.  
  4521. atcuf    proc    near            ; cursor forward Pn columns
  4522.     mov    ax,param        ; get Pn
  4523.     or    ax,ax
  4524.     jnz    atcuf1            ; got a value
  4525.     inc    ax            ; zero means one
  4526. atcuf1:    shl    ax,1            ; times 8 dots per char cell
  4527.     shl    ax,1
  4528.     shl    ax,1            ; Tek columns worth
  4529.     and    x_coord,not 7        ; modulo 8x8 cells
  4530.     add    x_coord,ax        ; forward to absolute column
  4531.     mov    ax,xmax
  4532.     cmp    x_coord,ax        ; beyond right most cell?
  4533.     jbe    atcuf2            ; be = no
  4534.     mov    x_coord,ax        ; limit to right
  4535. atcuf2:    ret
  4536. atcuf    endp
  4537.  
  4538. atcub    proc    near            ; cursor left/back Pn columns
  4539.     mov    ax,param        ; get Pn
  4540.     or    ax,ax
  4541.     jnz    atcub1            ; got a value
  4542.     inc    ax            ; zero means one
  4543. atcub1:    shl    ax,1
  4544.     shl    ax,1
  4545.     shl    ax,1            ; times 8 dots per cell
  4546.     and    x_coord,not 7        ; modulo 8x8 cells
  4547.     mov    cx,xmax
  4548.     cmp    x_coord,cx        ; beyond last col (wrap pending)?
  4549.     jbe    atcub3            ; be = no
  4550.     mov    x_coord,cx        ; set to last col
  4551. atcub3:    sub    x_coord,ax        ; back up
  4552.     jnc    atcub2            ; nc = ok
  4553.     mov    x_coord,0        ; stop in column zero
  4554. atcub2:    ret
  4555. atcub    endp
  4556.  
  4557. atcnl    proc    near            ; do Pn cr/lf's
  4558.     mov    x_coord,0        ; to left margin
  4559.     jmp    atcud            ; do the cursor downs
  4560. atcnl    endp
  4561.  
  4562. atcpl    proc    near            ; do Pn cursor ups
  4563.     jmp    atcuu            ; do the cursor ups
  4564. atcpl    endp
  4565.  
  4566.                     ; scaled by text screen width
  4567. atcha    proc    near            ; cursor to absolute column
  4568.     and    x_coord,not 7        ; modulo 8x8 cells
  4569.     mov    ax,param        ; get Pn
  4570.     or    ax,ax
  4571.     jz    atcha1            ; z = zero already
  4572.     dec    param            ; count columns from 0
  4573.     mov    ax,xmax            ; number of Tek dots/row
  4574.     mul    param            ; times columns they want
  4575.     mov    cl,byte ptr low_rgt    ; number of last text column
  4576.     xor    ch,ch
  4577.     xor    dx,dx
  4578.     div    cx            ; scale to ~80 column screen
  4579.     cmp    ax,xmax            ; too far?
  4580.     jbe    atcha1            ; be = no
  4581.     mov    ax,xmax            ; right most column
  4582. atcha1:    mov    x_coord,ax
  4583.     ret
  4584. atcha    endp
  4585.                     ; scaled by text screen height
  4586. atcva    proc    near            ; cursor to absolute row
  4587.     dec    param            ; count from 0
  4588.     mov    ax,param        ; desired text row
  4589.     or    ax,ax            ; zero or now -1?
  4590.     jg    atcva1            ; g = no, further down
  4591.     mov    ax,7            ; bottom of top text cell
  4592.     jmp    short atcva2
  4593. atcva1:    mov    ax,ybot
  4594.     inc    ax            ; number of scan lines on screen
  4595. ;;;;    and    ax,not 7        ; whole 8x8 char cells
  4596.     mul    param            ; times row they want
  4597.     mov    cl,byte ptr low_rgt+1    ; number of last text line (0..23)
  4598.     xor    ch,ch
  4599.     xor    dx,dx
  4600.     div    cx            ; scale to ~24 line screen 
  4601.     mov    cx,ybot
  4602. ;;;;    and    cx,not 7        ; whole 8x8 char cells
  4603.     cmp    ax,cx            ; too far?
  4604.     jbe    atcva2            ; be = no
  4605.     mov    ax,cx
  4606. atcva2:    mov    y_coord,ax        ; go to that line
  4607.     ret
  4608. atcva    endp
  4609.     
  4610. atcup    proc    near            ; cursor to absolute row, column
  4611.     call    atcva            ; process param[0] as absolute row
  4612.     push    param[2]        ; column
  4613.     pop    param
  4614.     jmp    atcha            ; process param[2] as absolute column
  4615. atcup    endp
  4616.  
  4617. ated    proc    near            ; erase display
  4618.     mov    al,spcontrol        ; preserve space control
  4619.     mov    tempname,al        ; save here
  4620.     mov    spcontrol,1        ; turn on destructive space
  4621.     push    x_coord
  4622.     push    y_coord            ; save cursor
  4623.     cmp    param,0            ; cursor to end of screen?
  4624.     je    ated1            ; e = yes
  4625.     cmp    param,1            ; start of screen to cursor?
  4626.     je    ated3            ; e = yes
  4627.     cmp    param,2            ; entire screen?
  4628.     je    ated5            ; e = yes
  4629.     ret                ; else ignore
  4630.  
  4631. ated1:    mov    param,0            ; cursor to end of this line
  4632.     call    atel            ; erase cursor to end of line
  4633.     add    y_coord,8        ; look at next line
  4634.     mov    ax,ybot
  4635.     cmp    y_coord,ax        ; are we at the end now?
  4636.     ja    ated6            ; a = yes
  4637.     mov    x_coord,0        ; start of line is here
  4638.     jmp    ated1            ; do through last line
  4639.  
  4640. ated3:    and    y_coord,not 7        ; modulo 8x8 char cells
  4641.     mov    cx,y_coord        ; start of screen to cursor
  4642.     shr    cx,1            ; char lines at 8 dots/char
  4643.     shr    cx,1
  4644.     shr    cx,1
  4645.     dec    cx            ; omit current line= # whole lines
  4646.     or    cx,cx            ; any whole lines?
  4647.     jle    ated3b            ; le = no
  4648.     mov    y_coord,7        ; start at the top line
  4649. ated3a:    push    cx
  4650.     mov    param,2            ; entire line
  4651.     call    atel            ; erase entire line
  4652.     add    y_coord,8        ; next line
  4653.     pop    cx
  4654.     loop    ated3a
  4655. ated3b:    mov    param,1            ; start of line to cursor
  4656.     call    atel            ; erase to cursor on this (last) line
  4657.     jmp    short ated6
  4658.  
  4659. ated5:    call    tekcls            ; erase whole screen
  4660.  
  4661. ated6:    mov    al,tempname        ; spacing control
  4662.     mov    spcontrol,al
  4663.     pop    y_coord
  4664.     pop    x_coord
  4665.     ret
  4666. ated    endp
  4667.  
  4668. atech    proc    near            ; erase Pn chars from cursor to eol
  4669.     mov    al,spcontrol        ; preserve space control
  4670.     mov    tempname,al        ; save here
  4671.     mov    spcontrol,1        ; turn on destructive space
  4672.     push    x_coord
  4673.     push    y_coord            ; save cursor
  4674.     mov    cx,x_coord
  4675.     and    cx,not 7        ; modulo 8x8 cells
  4676.     mov    ax,xmax
  4677.     sub    ax,cx            ; number of chars remaining on line
  4678.     shr    ax,1
  4679.     shr    ax,1
  4680.     shr    ax,1
  4681.     inc    ax            ; count cursor cell
  4682.     mov    cx,param        ; how many chars to erase
  4683.     or    cx,cx
  4684.     jz    atech1            ; z = zero, use one
  4685.     inc    cx
  4686. atech1:    cmp    ax,cx            ; want more than line length?
  4687.     jae    atech2            ; ae = no
  4688.     mov    cx,ax            ; clip at right margin
  4689.     or    cx,cx
  4690.     jle    atech3            ; le = nothing to do
  4691. atech2:    push    cx
  4692.     mov    al,' '
  4693.     call    outscrn            ; write spaces
  4694.     pop    cx
  4695.     loop    atech2
  4696. atech3:    mov    al,tempname        ; spacing control
  4697.     mov    spcontrol,al
  4698.     pop    y_coord
  4699.     pop    x_coord
  4700.     ret
  4701. atech    endp
  4702.  
  4703. atel    proc    near            ; erase on this line
  4704.     push    x_coord
  4705.     push    y_coord
  4706.     cmp    param,0            ; cursor to end of line?
  4707.     je    atel1            ; e = yes
  4708.     cmp    param,1            ; start of line to cursor?
  4709.     je    atel3            ; e = yes
  4710.     cmp    param,2            ; whole line?
  4711.     jne    atel5            ; ne = no, fail
  4712.     mov    x_coord,0        ; erase entire line
  4713.  
  4714. atel1:    mov    cx,xmax            ; cursor to end of line
  4715.     mov    ax,x_coord
  4716.     and    ax,not 7        ; modulo 8x8 cells
  4717.     sub    cx,ax
  4718.     shr    cx,1
  4719.     shr    cx,1
  4720.     shr    cx,1            ; 8 dots/char
  4721.     inc    cx            ; count the cursor cell
  4722.     or    cx,cx
  4723.     jle    atel5            ; le = do nothing
  4724.     mov    al,spcontrol        ; preserve space control
  4725.     mov    tempname,al        ; save here
  4726.     mov    spcontrol,1        ; turn on destructive space
  4727. atel2:    push    cx            ; start of line to cursor
  4728.     mov    al,' '
  4729.     call    outscrn
  4730.     pop    cx
  4731.     loop    atel2
  4732.     mov    al,tempname        ; space control
  4733.     mov    spcontrol,al        ; restored
  4734. atel5:    pop    y_coord
  4735.     pop    x_coord
  4736.     ret
  4737. atel3:    mov    cx,x_coord        ; start of line to cursor
  4738.     shr    cx,1
  4739.     shr    cx,1
  4740.     shr    cx,1
  4741.     inc    cx            ; count cursor cell
  4742.     mov    x_coord,0        ; go to start of line
  4743.     jmp    atel2            ; do the loops
  4744. atel    endp
  4745. code2    ends
  4746.     end
  4747.