home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / ccdos / ccgibm.asm < prev    next >
Assembly Source File  |  2020-01-01  |  96KB  |  2,069 lines

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