|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T m
Length: 117611 (0x1cb6b) Types: TextFile Names: »msgibm.asm«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit └─⟦71044c191⟧ »EurOpenD3/misc/kermit.ms-2.32.tar.Z« └─⟦31f2d420d⟧ └─⟦this⟧ »msgibm.asm«
Name msgibm ; File MSGIBM.ASM ; Tektronix emulator for use with MS Kermit/IBM. ; Edit history: ; Last edit 21 Nov 1988 ; 21 Nov 1988 Version 2.32 ; 16 Sept 1988 Also look in 0fc00:50h for AT&T logo. ; 1 July 1988 Version 2.31 ; 22 May 1988 Add support for ESC [ Pn ; Pn m (ANSI) screen coloring. ; 22 March 1988 Add global byte Tekgraf which forces graphics board type ; 0=auto-sensing, 1=cga, 2=ega, 3=VGA, 4=Hercules, 5=ATT. Tekgraf stored ; here and set in file MSX by Set Term Graphics <board type>. Permit chars ; to overlap existing pixels. [jrd] ; 27 Feb 1988 Add tests for Toshiba T3100 (tnx for assist from Rob Preuss), ; for Olivetti M28/AT&T 6300+, and for DEC VAXmate II (tnx to Frank da Cruz) ; Add pointer based dispatch to character-font drawing routine. Add tests ; for stdin being a file rather than a device (keyboard). [jrd] ; 27 Jan 1988 Supress GIN and Status echos with Bypass byte. Bypass is reset ; by receipt of BEL, LF, CR, US, escape sequences, terminal reset. ; Bypass is set by receipt of ESC Control-E, ESC Control-X, ESC Control-Z. ; Make GIN mode crosshairs remember last GIN mode postion until the terminal ; is reset; make major steps smaller. Add ESC query-mark stands for DEL. ; Make Horizontal Tab (Control-I) a non-printing cursor control character ; to move right one column (with line wrap). Let real Hercules boards use ; both pages of memory (clones behave differently), tnx to Daniel Gruner. ; 1 Jan 1988 version 2.30 ; 31 Dec 1987 change name from msvibm to msgibm for final release. [jrd] ; 29 Dec 1987 Add ESC [ ? 3 8 l as exit Tek mode command, from VT340's.[jrd] ; 26 Dec 1987 Add test to absorb echo of crosshairs report. [jrd] ; 22 Dec 1987 Revise parsing rules to make an escape sequence be a temporary ; interruption to the current command (except Clear Screen seq). [jrd] ; Add Control-C and Control-Break as non-reporting exits from GIN mode. [jrd] ; 21 Dec 1987 Add AT&T 6300, Olivetti M24 presence tests and run code. [jrd] ; 16 Dec 1987 Correct screen coloring for 64KB mono/med res color egas. [jrd] ; 4 Dec 1987 Add quirks for Environments, such as TopView, Windows. [jrd] ; 3 Dec 1987 Let 128KB EGA boards save screens. [jrd] ; 30 Nov 1987 Add relative plotting, thanks to help from Bob Parks. [jrd] ; 24 Nov 1987 Add dashed line patterns. [jrd] ; 21 Nov 1987 Add full color background. [jrd] ; 15 Nov 1987 Do screen clears manually because a Bios mode-set keeps ; interrupts off long enough to miss serial port characters. Make crosshairs ; smaller. [jrd] ; 8 Nov 1987 Modularize line drawing using Bresneham's algorithm, use pointers ; to action routines for different board types. Add screen save/restore. ; Do display board presence tests. Add FS as point plot introducer. Allow ; for virtual screens when operating under Environments (Windows, etc). [jrd] ; 1 Nov 1987 Heavy rewrite to integrate code into regular MS Kermit/IBM ; material. [jrd] ;============================================================================== ; Original version for TI Pro computers by ; 12-Dec-84 Joe Smith, CSM Computing Center, Golden CO 80401 ; adapted to IBM PC June 1987 by Brian Holley, ; Faculty of Economics and Politics ; University of Cambridge, England ; Email: BJH6@UK.AC.CAM.PHX ; Upgraded and integrated into MS Kermit 2.30 by Joe Doupnik, Utah State Univ. ; ; Description of Tektronix commands ; ; ESCAPE-CONTROL-E (ENQ) requests a status report ; ESCAPE-FORMFEED erases the screen. ; ESCAPE-CONTROL-X turns on bypass mode (no screen characters). ; ESCAPE-CONTROL-Z turns on the crosshairs (not on 4006 or 4025) ; ESCAPE-? is replaced by DEL code, to assist line plots with 7 bit systems. ; ESCAPE [ Pn ; Pn m set screen colors. Pn = 30 + sum of colors for foregnd, ; 40 + sum of colors for background, Pn = 0 sets b/w, Pn = 1 for high ; intensity. Colors are red = 1, green = 2, blue = 4. ; ESCAPE [ ? 3 8 l exits Tek mode and returns to host text terminal type ; (VT102 if none defined yet). This is an extension from DEC VT340's. ; CONTROL-] (GS) turns on plot mode, the first move will be with beam off. ; CONTROL-^ (RS) turns on incremental plot mode. RS space means move pen up ; RS P means move pen down, following letters:A, E, D, F, B, J, H, I mean ; move right, right and up, up, left and up, left, left and down, down, and ; right and down, respectively. Ex: RS <space> J J J means move three Tek ; positions left and down with the pen up (invisibly). ; CONTROL-UNDERLINE (US) turns off plot mode, as does CR (for all but 4025). ; CONTROL-X switches from TEKTRONIX sub mode to NORMAL alpha mode but is ; ignored if we are emulating a full Tek terminal rather than a sub mode ; of DEC or Heath. ; FF erases screen. ; ESCAPE letter, where letter is accent grave (`), a-e sets the line drawing ; pattern until reset to solid lines (same as escape accent) by command or ; a terminal reset. ; where ; ENQ = Control E ; ESC = Control [ (left square bracket) ; FF = Control L ; FS = Control \ (backslash) ; GS = Control ] (right square bracket) ; RS = Control ^ (caret) ; US = Control _ (underscore) ; ; The plot commands are characters which specify the absolute position to move ; the beam. All moves except the one immediately after the GS character ; (Control-]) are with a visible trace. ; ; For 4010-like devices - The positions are from 0 to 1023 for both X and Y, ; although only 0 to 780 are visible for Y due to screen geometry. The screen ; is 10.23 by 7.80 inches, and coordinates are sent as 1 to 4 characters. ; ; For 4014-like devices - The positions are from 0 to 4096, but each movement ; is a multiple of 4 positions unless the high-resolution LSBXY are sent. This ; makes it compatible with the 4010 in that a full sized plot fills the screen. ; ; HIX,HIY = High-order 5 bits of position ; LOX,LOY = Middle-order 5 bits of position ; LSBXY = Low-order 2 bits of X + low-order 2 bits of Y (4014 mode) ; ; Hi Y Lo Y Hi X LSBXY Characters sent (Lo-X always sent) ; ---- ---- ---- ----- ---------------------------------- ; Same Same Same Same Lo-X ; Same Same Same Diff LSB, Lo-Y, Lo-X 4014 ; Same Same Diff Same Lo-Y, Hi-X, Lo-X ; Same Same Diff Diff LSB, Lo-Y, Hi-X, Lo-X 4014 ; Same Diff Same Same Lo-Y, Lo-X ; Same Diff Same Diff LSB, Lo-Y, Lo-X 4014 ; Same Diff Diff Same Lo-Y, Hi-X, Lo-X ; Same Diff Diff Diff LSB, Lo-Y, Hi-X, Lo-X 4014 ; Diff Same Same Same Hi-Y, Lo-X ; Diff Same Same Diff Hi-Y, LSB, Lo-Y, Lo-X 4014 ; Diff Same Diff Same Hi-Y, Lo-Y, Hi-X, Lo-X ; Diff Same Diff Diff Hi-Y, LSB, Lo-Y, Hi-X, Lo-X 4014 ; Diff Diff Same Same Hi-Y, Lo-Y, Lo-X ; Diff Diff Same Diff Hi-Y, LSB, Lo-Y, Lo-X 4014 ; Diff Diff Diff Same Hi-y, Lo-Y, Hi-X, Lo-X ; Diff Diff Diff Diff Hi-y, LSB, Lo-Y, Hi-X, Lo-X 4014 ; Offset for byte: 20h 60h 60h 20h 40h ; ; Note that LO-Y must be sent if HI-X has changed so that the TEKTRONIX knows ; the HI-X byte (in the range of 20h-3fh) is HI-X and not HI-Y. LO-Y must ; also be sent if LSBXY has changed, so that the 4010 will ignore LSBXY and ; accept LO-Y. The LSBXY byte is 60h + MARGIN*10h + LSBY*4 + LSBX. (MARGIN=0) ; ; ; ; External variable tekflg and calls to tekini, tekemu, tekesc, tekcls: ; Byte TEKFLG is non-zero when the Tek emulator is active; it is set by the ; startup code in tekini and is maintained in this file. Internal variable ; inited remembers if we have a graphics screen saved, etc. ; TEKINI must be called when entering the emulator to establish the graphics ; screen mode and to calculate the screen dimensions. ; TEKRINT reinitialize complete emulator. ; TEKESC is called from say mszibm.asm to invoke Tek emulation when the ; external procedures have detected an Escape Control-L sequence. An implicit ; initialization is done if necessary. ; TEKEMU is the normal entry point to pass a received character to the emulator. ; It too will do an implicit initialization, if required. ; TEKCLS clears the graphics screen, but only if the emulator is active. ; The emulator remains active during Connect mode Help, Status, and other ; interrupts which do not change the terminal type. public tekemu,tekini,tekrint,tekend,tekgraf ; Terminal emulation public tekcls, tekesc, tekflg ; used by msz file include mssdef.h ENQ equ 05h ; ^E ENQ for TEK enquiries CAN equ 18h ; ^X to return to ANSI mode ESCZ equ 1Ah ; SUB, ESC-^Z triggers crosshairs VT equ 0bh ; ^K go up one line FS equ 1ch ; ^\ for point plot mode GS equ 1Dh ; ^] draw line (1st move is invisible) RS equ 1Eh ; ^^ for incremental line plot mode US equ 1Fh ; ^_ (underscore) returns to text mode accent equ 60h ; accent grave txtmode equ 4 ; text mode for TEKTRONIX status maxtekx equ 1024 ; horizontal and maxteky equ 780 ; vertical resolution of TEK 4010 screen equ 10h ; IBM Bios screen call uparr equ 72 ; DOS scan codes for arrow keys dnarr equ 80 lftarr equ 75 rgtarr equ 77 homscn equ 71 ; DOS home screen scan code shuparr equ '8' ; ascii codes for shifted arrows shdnarr equ '2' shlftarr equ '4' shrgtarr equ '6' ; Graph_mode for different systems: cga equ 6 ; highest resolution mode for CGA mono equ 7 ; real monochrome display adapter colorega equ 14 ; Low-res mode, color EGA monoega equ 15 ; mono ega needs mode 15 ega equ 16 ; Hi-res mode - EGA olivetti equ 72 ; Olivetti's Hi-res - 50 lines text toshiba equ 74h ; Toshiba T3100, like Olivetti vaxmate equ 0D0h ; DEC VAXmate II, like Olivetti hercules equ 255 ; pseudo mode for Hercules graphics ; Note: IBM VGA modes 17 & 18, 640 by 480, can be used by setting "ega" above ; to 17 or 18 and modifying ybot to be 479 and ymult to be 48 at label tekin5. ; The code will scale everything appropriately for the new screen size, but ; there will be insufficient memory to retain the entire graphics image. ; Manual override SET TERMINAL GRAPHICS VGA accomplishes these two steps. segega equ 0a000h ; segments of display memory, EGA,VGA segcga equ 0b800h ; CGA, AT&T/Olivetti and relatives seghga equ 0b000h ; HGA segmono equ 0b000h ; Monochrome ; Hercules equates: index equ 03b4h ; 6845 index register cntrl equ 03b8h ; Display mode control port hstatus equ 03bah ; status port scrn_on equ 8 ; bit to turn screen on grph equ 2 ; graphics mode text equ 20h ; text mode config equ 03bfh ; configuration port genable equ 1+2 ; enable graphics (1) on two pages (2) hiy equ 1 ; codes for Tek graphics components loy equ 2 hix equ 4 lox equ 3 datas segment public 'datas' extrn flags:byte, portval:word, rxtable:byte, vtemu:byte extrn tv_mode:byte xmult dw ? ; scaling factor for x is xdiv dw ? ; xmult/xdiv ymult dw ? ; scaling factor for y is ydiv dw ? ; ymult/ydiv xmax dw ? ; ybot dw ? ; ; required for Hercules screen handling gtable db 35h,2dh,2eh,7 ; bytes for 6845 controller db 5bh,2,57h,57h ; - graphics mode db 2,3,0,0 ttable db 61h,50h,52h,0fh ; bytes for 6845 controller db 19h,6,19h,19h ; - text mode db 2,0dh,0bh,0ch attlogo db 'OLIVETTI' ; Olivetti M24/28, AT&T 6300 rom id attlen equ $-attlogo ; length toshlogo db ' TT33110000 TTOOSSHHIIBBAA' ; Toshiba T3100 logo toshlen equ $-toshlogo ; length declogo db 'Copyright Digital Equipment Corp' ; DEC VAXmate declen equ $-declogo ttstate dw tektxt ; state machine control pointer prestate dw 0 ; previous state, across interruptions visible db 0 ; 0 to move, 1 to draw a line tek_hiy dw 0 ; Y coordinate in Tektronix mode tek_loy db 0 tek_hix dw 0 ; X coordinate in Tektronix mode tek_lox db 0 tek_lsb db 0 ; Low-order 2 bits of X + low Y ; (4014 mode) status db 0 lastc db 0 ; last x/y coord fragment seen masktab db 80h,40h,20h,10h,8,4,2,1 ; quicker than calculations! ; dashed line patterns linetab dw 0ffffh ; ESC accent 11111111 11111111 dw 0aaaah ; ESC a 10101010 10101010 dw 0f0f0h ; ESC b 11110000 11110000 dw 0fafah ; ESC c 11111010 11111010 dw 0ffcch ; ESC d 11111111 11001100 dw 0fc92h ; ESC e 11111100 10010010 linepat dw 0ffffh ; active line pattern, from above ;End of init data IDSEQ dw tekem ; address of response to terminal CTLTAB dw 0 ; .. inquiry tekem db 'IBM_TEK' ; .. and the response db escape,'/Z',0 x_coord dw 0 ; Tek text char X coordinate y_coord dw 8 ; Tek text char Y coordinate xcross dw 0 ; cross hairs to start at centre ycross dw 0 oldx dw 0 ; Tek coordinates of last point oldy dw 767 ; initially top left scalex dw 0 ; PC coord for scaled x value scaley dw 0 ; for scaled y value curmode db 0 ; screen mode before graphics tekgraf db 0 ; Tek graphics board selection (def=auto) ; local variables for LINE plotting routine graph_mode db 0 ; graphics video mode, default is none cursor dw 0 ; saved text cursor inited db 0 ; non-zero if inited (retains page) tekflg db 0 ; Tek mode active flag yflags db 0 ; flags byte from msy flow dw 0 ; flow control word gpage db 0 ; display adapter graphics page gfcol db 15 ; graphics foreground colour gbcol db 0 ; graphics background color tfcol db 0 ; temp foreground color tbcol db 0 ; temp background color lastd db 0,0 ; worker for ESC [ Pn ; Pn m scanner colortb db 0,4,2,6,1,5,3,7 ; color reversed-bit setting bytes moremsg db ' More >' mormsglen equ $-moremsg ; length of message ccode db 0 ; temp for holding plot color code linelen dw 0 ; offset increment between scan lines putc dw mputc ; ptr to plot a character routine psetup dw psetupm ; ptr to plot setup routine pincy dw pincym ; ptr to inc y routine plotptr dw pltmon ; ptr to dot plot routine gcplot dw gcgen ; ptr to char plot routine segscn dw 0b800h ; actual screen segment to use ; ANSI Escape sequence to exit Tek mode tkoff db escape,'[?38l' ; Exit Tek mode escape sequence tkofflen equ $-tkoff ; length of sequence tkoffs db 6 dup (0) ; received chars in rcv'd sequence tkcnt dw 0 ; counter of matched char in tkoffs bypass db 0 ; GIN mode bypass condition (0=off) temp dw 0 ; 8*8 font for Hercules and such, CGA, and EGA ; - allows 43 lines, and 80 (90 for Hercules) chars per line. ; all printing (?) characters from <space> to <del> - two characters per line ; 8 bits per scan line, given top line first, 8 scan lines. font db 0,0,0,0,0,0,0,0, 18h,18h,18h,18h,18h,0,18h,0 db 6ch,6ch,6ch,0,0,0,0,0, 36h,36h,7fh,36h,7fh,36h,36h,0 db 0ch,3fh,68h,3eh,0bh,7eh,18h,0, 60h,66h,0ch,18h,30h,66h,06h,0 db 38h,6ch,6ch,38h,6dh,66h,3bh,0, 0ch,18h,30h,0,0,0,0,0 db 0ch,18h,30h,30h,30h,18h,0ch,0, 30h,18h,0ch,0ch,0ch,18h,30h,0 db 0,18h,7eh,3ch,7eh,18h,0,0, 0,18h,18h,7eh,18h,18h,0,0 db 0,0,0,0,0,18h,18h,30h, 0,0,0,7eh,0,0,0,0 db 0,0,0,0,0,18h,18h,0, 0,06h,0ch,18h,30h,60h,0,0 db 3ch,66h,6eh,7eh,76h,66h,3ch,0, 18h,38h,18h,18h,18h,18h,7eh,0 db 3ch,66h,06h,0ch,18h,30h,7eh,0, 3ch,66h,06h,1ch,06h,66h,3ch,0 db 0ch,1ch,3ch,6ch,7eh,0ch,0ch,0, 7eh,60h,7ch,06h,06h,66h,3ch,0 db 1ch,30h,60h,7ch,66h,66h,3ch,0, 7eh,06h,0ch,18h,30h,30h,30h,0 db 3ch,66h,66h,3ch,66h,66h,3ch,0, 3ch,66h,66h,3eh,06h,0ch,38h,0 db 0,0,18h,18h,0,18h,18h,0, 0,0,18h,18h,0,18h,18h,30h db 0ch,18h,30h,60h,30h,18h,0ch, 0,0,0,7eh,0,7eh,0,0,0 db 30h,18h,0ch,06h,0ch,18h,30h, 0,3ch,66h,0ch,18h,18h,0,18h,0 db 3ch,66h,6eh,6ah,6eh,60h,3ch, 0,3ch,66h,66h,7eh,66h,66h,66h,0 db 7ch,66h,66h,7ch,66h,66h,7ch, 0,3ch,66h,60h,60h,60h,66h,3ch,0 db 78h,6ch,66h,66h,66h,6ch,78h, 0,7eh,60h,60h,7ch,60h,60h,7eh,0 db 7eh,60h,60h,7ch,60h,60h,60h, 0,3ch,66h,60h,6eh,66h,66h,3ch,0 db 66h,66h,66h,7eh,66h,66h,66h, 0,7eh,18h,18h,18h,18h,18h,7eh,0 db 3eh,0ch,0ch,0ch,0ch,6ch,38h, 0,66h,6ch,78h,70h,78h,6ch,66h,0 db 60h,60h,60h,60h,60h,60h,7eh, 0,63h,77h,7fh,6bh,6bh,63h,63h,0 db 66h,66h,76h,7eh,6eh,66h,66h, 0,3ch,66h,66h,66h,66h,66h,3ch,0 db 7ch,66h,66h,7ch,60h,60h,60h, 0,3ch,66h,66h,66h,6ah,6ch,36h,0 db 7ch,66h,66h,7ch,6ch,66h,66h, 0,3ch,66h,60h,3ch,06h,66h,3ch,0 db 7eh,18h,18h,18h,18h,18h,18h, 0,66h,66h,66h,66h,66h,66h,3ch,0 db 66h,66h,66h,66h,66h,3ch,18h, 0,63h,63h,6bh,6bh,7fh,77h,63h,0 db 66h,66h,3ch,18h,3ch,66h,66h, 0,66h,66h,66h,3ch,18h,18h,18h,0 db 7eh,06h,0ch,18h,30h,60h,7eh, 0,7ch,60h,60h,60h,60h,60h,7ch,0 db 0,60h,30h,18h,0ch,06h,0,0, 3eh,06h,06h,06h,06h,06h,3eh,0 db 18h,3ch,66h,42h,0,0,0,0, 0,0,0,0,0,0,0,0ffh db 30h,18h,0ch,0,0,0,0,0, 0,0,3ch,06h,3eh,66h,3eh,0 db 60h,60h,7ch,66h,66h,66h,7ch,0, 0,0,3ch,66h,60h,66h,3ch,0 db 06h,06h,3eh,66h,66h,66h,3eh,0, 0,0,3ch,66h,7eh,60h,3ch,0 db 0eh,18h,18h,3ch,18h,18h,18h,0, 0,0,3eh,66h,66h,3eh,06h,3ch db 60h,60h,7ch,66h,66h,66h,66h,0, 18h,0,38h,18h,18h,18h,3ch,0 db 18h,0,38h,18h,18h,18h,18h,70h, 60h,60h,66h,6ch,78h,6ch,66h,0 db 38h,18h,18h,18h,18h,18h,3ch,0, 0,0,76h,7fh,6bh,6bh,63h,0 db 0,0,7ch,66h,66h,66h,66h,0, 0,0,3ch,66h,66h,66h,3ch,0 db 0,0,7ch,66h,66h,7ch,60h,60h,0, 0,3eh,66h,66h,3eh,06h,07h db 0,0,6ch,76h,60h,60h,60h,0, 0,0,3eh,60h,3ch,06h,7ch,0 db 30h,30h,7ch,30h,30h,30h,1ch,0, 0,0,66h,66h,66h,66h,3eh,0 db 0,0,66h,66h,66h,3ch,18h,0, 0,0,63h,6bh,6bh,7fh,36h,0 db 0,0,66h,3ch,18h,3ch,66h,0, 0,0,66h,66h,66h,3eh,06h,3ch db 0,0,7eh,0ch,18h,30h,7eh,0, 0ch,18h,18h,70h,18h,18h,0ch,0 db 18h,18h,18h,0,18h,18h,18h,0, 30h,18h,18h,0eh,18h,18h,30h,0 db 31h,6bh,46h,0,0,0,0,0, 8 dup (0ffh) datas ends code segment public 'code' extrn outchr:near, beep:near, scrseg:near, cmblnk:near extrn clrmod:near, savescr:near, cptchr:near, pcwait:near extrn restscr:near, getflgs:near, clrbuf:near, vtans52:near extrn iseof:near, beep:near assume cs:code, ds:datas, es:nothing ; Initialise TEK mode by setting high resolution screen, etc tekini PROC NEAR push ax ; do presence tests push bx push cx push dx push si push di push es mov bx,portval ; get port flow control chars: mov bx,[bx].flowc ; bh=xon, bl=xoff or both are nulls mov flow,bx ; save here mov ax,bx ; get flow control word cmp al,0 ; able to do xoff? je tekin0 ; e = no call outmodem ; tell host xoff while we change modes tekin0: mov bx,vtemu.att_ptr ; emulator screen color ptr mov al,[bx] mov gfcol,al ; save foreground color and gfcol,0fh ; save just foreground bits and al,70h ; select background color, no bold mov cl,4 shr al,cl ; get background colors mov gbcol,al ; set graphics background color mov ah,15 ; get current screen mode int screen cmp al,3 ; in a mono/color text mode (2/3)? jbe tekin1 ; be = yes cmp al,mono ; mono text mode (7)? je tekin1 ; e = yes cmp tekflg,0 ; are we active as Tek device now? je tekin1 ; e = no jmp tekin13 ; yes, don't redo graphics setup tekin1: mov curmode,al ; save mode here mov ah,3 ; get cursor position xor bh,bh ; page 0 int screen mov cursor,dx ; save position call savescr ; save text screen ; Presence tests. tekin2: mov graph_mode,cga ; Color. Assume CGA mov segscn,segcga ; assume cga screen segment mov gpage,0 ; graphics page 0 but no page 1 mov putc,offset gputc ; CGA character display routine mov gcplot,offset gcgen ; General character plot routine mov psetup,offset psetupc ; CGA plot setup routine mov plotptr,offset pltcga ; CGA dot plot routine mov pincy,offset pincyc ; CGA inc y routine mov xmult,5 ; CGA. Scale TEK to PC by 640/1024 mov xdiv,8 ; so that 0-1023 converts to 0-639 mov xmax,640-8 ; x-coord of rightmost character mov ymult,10 ; vertical scale for IBM is 200/780 mov ydiv,39 ; mov ybot,199 ; Bottom of screen is Y=199 mov al,tekgraf ; user video board specification cmp al,0 ; auto-sensing? je tekin2c ; e = yes (default) cmp al,1 ; user wants CGA? jne tekin2a ; ne = no jmp tekin13 ; do CGA tekin2a:cmp al,4 ; user wants Hercules? jne tekin2b ; ne = no jmp tekin8 ; do Hercules tekin2b:cmp al,5 ; user wants AT&T style? jne tekin2c ; ne = no jmp tekin7 ; do AT&T kind ; do auto-sensing of display board ; test for EGA tekin2c:mov ax,1200H ; EGA: Bios alternate select mov bl,10H ; Ask for EGA info mov bh,0ffH ; Bad info, for testing mov cl,0fH ; Reserved switch settings int screen ; EGA, are you there? and cl,0fh ; four lower switches cmp cl,0cH ; Test reserved switch settings jb tekin3 ; b = ega present jmp tekin7 ; else no EGA, check other adapters tekin3: mov ax,40h ; check Bios 40:87h for ega being mov es,ax ; the active display adapter test byte ptr es:[87h],8 ; is ega active? jz tekin3a ; z = yes jmp tekin7 ; ega is inactive, check others tekin3a:cmp bl,1 ; is there 128KB on ega board? jb tekin4 ; b = less, so no screen saves mov gpage,1 ; >=128 KB, use two graphics pages tekin4: mov graph_mode,ega ; assume high resolution color cmp cl,3 ; high resolution color? je tekin5 ; e = yes cmp cl,9 ; high resolution color? je tekin5 ; e = yes mov graph_mode,monoega ; assume mono monitor on ega board test bh,1 ; ega mono mode in effect? jnz tekin5 ; nz = yes mov graph_mode,colorega ; say ordinary cga on ega board, 64KB mov gpage,1 ; is enough memory with 200 scan lines jmp short tekin5a ; use current cga parameters tekin5: mov ybot,349 ; text screen bottom is 349 on EGA mov ymult,35 ; mov ydiv,78 ; scale y by 350/780 tekin5a:mov segscn,segega ; use ega screen segment mov psetup,offset psetupe ; plot setup routine mov plotptr,offset pltega ; ega dot plot routine mov pincy,offset pincye ; inc y routine mov putc,offset gputc ; character display routine mov gcplot,offset gcega ; EGA character plot routine call fixcolor ; correct color mapping for some bds jmp tekin13 ; end of EGA part, do VGA tests below tekin7: mov ax,0fc00h ; Olivetti/AT&T 6300, check rom id mov es,ax mov di,0 ; start here mov graph_mode,olivetti ; Olivetti mov cx,attlen ; length of logo mov si,offset ATTLOGO ; master string repe cmpsb ; do a match je tekin7c ; e = a match mov di,0050h ; look here too mov si,offset ATTLOGO mov cx,attlen repe cmpsb je tekin7c ; e = a match mov di,2014h ; and look here mov si,offset ATTLOGO mov cx,attlen repe cmpsb ; do a match je tekin7c ; e = a match, else try other types tekin7a:mov graph_mode,toshiba mov ax,0f000h ; Check for Toshiba T3100, rom scan mov es,ax mov di,0014h ; start here mov si,offset TOSHLOGO ; master string mov cx,toshlen ; length repe cmpsb ; do a match je tekin7c ; e = a match, else try other types tekin7b:mov graph_mode,vaxmate ; DEC VAXmate II mov ax,0f000h ; Check for VAXmate II rom signature mov es,ax mov di,0e000h ; start here mov si,offset DECLOGO ; master string mov cx,declen ; length repe cmpsb ; do a match jne tekin7d ; ne = mismatch, try other types ; Olivetti/AT&T, Toshiba, VAXmate tekin7c:mov gpage,0 ; only page 0 with 640 by 400 mode mov segscn,segcga ; use cga screen segment (0b800h) mov psetup,offset psetupo ; plot setup routine mov plotptr,offset pltcga ; cga dot plot routine mov pincy,offset pincyh ; inc y routine (Herc style addresses) mov putc,offset gputc ; character display routine mov gcplot,offset gcgen ; General character plot routine mov ybot,399 ; bottom of screen is y = 399 mov ymult,20 ; vertical scale = 400/780 mov ydiv,39 ; same as cga setup jmp tekin13 tekin7d:cmp curmode,mono ; mono text mode? je tekin8 ; e = yes jmp tekin11 ; ne = no, try cga ; test for Hercules tekin8: call scrseg ; get screen segment, test Environment cmp tv_mode,0 ; Environment active? je tekin8a ; e = no, ok to test for Hercules jmp tekin10 ; don't do Herc mode, do Mono tekin8a:mov dx,hstatus ; Herc status port in al,dx ; read it mov bl,al ; save here and bl,80h ; remember retrace bit mov cx,0ffffh ; do many times (for fast machines) tekin8b:mov dx,hstatus ; check status port in al,dx and al,80h ; select bit jmp $+2 ; use a little time cmp bl,al ; did it change? loope tekin8b ; test again if not je tekin10 ; e = no change in bit, not Herc mov graph_mode,hercules ; say have Herc board mov segscn,seghga ; assume hga screen segment mov putc,offset gputc ; character display routine mov gcplot,offset gcgen ; General character plot routine mov psetup,offset psetuph ; plot setup routine to use mov plotptr,offset pltcga ; use cga dot plot routine for Herc mov pincy,offset pincyh ; inc y routine mov xmult,45 ; Scale TEK to Hercules by 720/1024 mov xdiv,64 ; so that 0-1023 converts to 0-719 mov xmax,720-8 ; x-coord of rightmost character mov ymult,87 ; vertical scale for Hercules is mov ydiv,195 ; 348/780 mov ybot,347 ; bottom of screen is y = 347 mov ax,seghga ; segment of Herc video display mov es,ax mov al,es:[8000h] ; read original contents, page 1 not byte ptr es:[8000h] ; write new pattern mov ah,es:[8000h] ; read back not byte ptr es:[8000h] ; restore original contents not ah ; invert this too cmp ah,al ; same (memory present?) jne tekin9 ; ne = not same, no memory there mov gpage,1 ; say two pages of display memory tekin9: jmp tekin13 ; set to MONO tekin10:mov graph_mode,mono ; force monochrome adapter text mov segscn,segmono ; assume mono screen segment call scrseg ; Environments: get virtual screen mov segscn,ax ; seg returned in ax and es:di mov gpage,0 mov putc,offset mputc ; character display routine mov psetup,offset psetupm ; plot setup routine to use mov plotptr,offset pltmon ; use hga dot plot routine mov pincy,offset pincym ; inc y routine mov xmult,5 ; Scale TEK to mono by 640/1024 mov xdiv,8 ; so that 0-1023 converts to 0-639 mov xmax,640-8 ; x-coord of rightmost character mov ymult,10 ; vertical scale for mono is 200/780 mov ydiv,39 mov ybot,200 ; bottom of screen is y = 200 for Bios jmp tekin13 ; Uses TEXT mode, for safety ; test for CGA tekin11:mov graph_mode,cga ; set CGA high resolution graphics mov segscn,segcga ; CGA screen segment jmp tekin13 ; Set Graphics mode tekin13:cmp graph_mode,hercules ; Hercules? jne tekin14 ; ne = no call hgraf ; set Herc graphics mode, clear regen jmp short tekin16 ; restore screen tekin14:mov ah,0 ; set screen mode mov al,graph_mode ; to this screen mode cmp tekgraf,3 ; user wants "VGA" modes (640x480)? jne tekin14a ; ne = no cmp al,monoega ; yes, allow high resolution stuff? jb tekin14a ; b = no cmp al,ega ; ditto ja tekin14a ; a = no add al,2 ; use modes 17(b/w) and 18(10)(color) mov ybot,479 ; text screen bottom is 479 on VGA mov ymult,48 tekin14a:cmp gpage,0 ; only page 0 available? je tekin15 ; e = yes, and watch for Bios errors cmp inited,0 ; first time through? je tekin15 ; e = yes, clear the page of old junk or al,80h ; save regen buffer (save area too) tekin15:int screen ; Bios Set Mode. tekin16:mov tekflg,1 ; starting Tek sub mode cmp inited,0 ; inited yet? jne tekin19 ; ne = yes, restore screen mov ttstate,offset tektxt ; do displayable text mov prestate,offset tektxt ; set a previous state of text mov inited,1 ; say we have initialized mov al,gfcol mov tfcol,al ; remember current coloring mov al,gbcol mov tbcol,al call tekcls ; clear screen, for ega coloring jmp short tekin20 tekin19:call tekrest ; restore old graphics screen mov al,tfcol ; and coloring mov gfcol,al mov al,tbcol mov gbcol,al tekin20:mov ax,flow ; get flow control word xchg ah,al ; get xon into al cmp al,0 ; able to send xon? je tekin21 ; e = no call outmodem ; tell host xon tekin21:clc ; clear carry for success jmp short tekin23 tekin22:stc ; set carry for failure tekin23:pop es pop di pop si pop dx pop cx pop bx pop ax ret tekini ENDP TEKRINT proc near ; Tek reinitialization entry point mov inited,0 ; do complete reinitialization jmp tekini TEKRINT endp ;Terminal emulation. Enter with received character in AL. TEKEMU PROC NEAR ; main emulator cmp tekflg,0 ; Tek mode active yet? (msz call) jne tektt1 ; ne = yes call tekini ; init now mov ttstate,offset tektxt ; initial state mov prestate,offset tektxt ; set a previous state of text jnc tektt1 ; nc = succeeded ret ; else failed to init, just return tektt1: and al,7fh ; force Tek chars to be 7 bits cmp al,0 ; NUL char? je tekign ; e = yes, ignore it before logging push ax call getflgs ; get msy yflags into al mov yflags,al test al,capt ; capturing output? pop ax jz tektt4 ; z = no, forget this part push ax ; save char call cptchr ; give it captured character pop ax ; restore character and keep going tektt4: test yflags,trnctl ; debug? if so use tty mode jz tektt5 ; z = no cmp al,DEL ; DEL char? jne tektt4a ; ne = no mov al,5eh ; make DEL a caret query mark call outscrn mov al,3fh ; the query mark call outscrn jmp short tekign tektt4a:cmp al,' ' ; control char? jae tektt4b ; ne = no push ax mov al,5eh ; caret call outscrn pop ax add al,'A'-1 ; make char printable tektt4b:call outscrn tekign: ret ; Ignore this character tektt5: call tkscan ; scan for "ESC [ ? 3 8 l" exit code tektt5a:cmp al,0 ; null char response? je tekign ; e = yes, ignore the character cmp al,' ' ; control code? jb tektt6 ; b = yes, decode jmp ttstate ; no, do current state ; Control characters: tektt6: cmp al,GS ; Line plot command? jne tektt7 ; ne = no mov visible,0 ; Next move is invisible and status,not txtmode ; set status report byte mov ttstate,offset tekline ; expect coordinates next jmp tektt12 tektt7: cmp al,RS ; Incremental dot command? jne tektt8 ; ne = no and status,not txtmode ; set status report mov ttstate,offset tekrlin ; expect pen command next jmp tektt12 tektt8: cmp al,FS ; Point plot command? jne tektt9 ; ne = no mov visible,0 ; next move is invisible and status,not txtmode ; set status report byte mov ttstate,offset tekpnt jmp tektt12 tektt9: cmp al,US ; assert text mode? [bjh] jne tektt10 ; ne = no or status,txtmode ; set status report byte mov ttstate,offset tektxt ; Go to TEKTXT next time mov bypass,0 ; reset bypass condition jmp tektt12 tektt10:cmp al,ESCAPE ; Escape? jne tektt11 ; ne = no or status,txtmode ; set status report byte cmp ttstate,offset tekesc ; already in escape state? je tektt14 ; e = yes, nest no further push ttstate ; current state pop prestate ; save here as previous state mov ttstate,offset tekesc ; next state parses escapes ret tektt11:cmp al,CAN ; Control X? (exits Tek sub mode) jne tektt13 ; ne = no, stay in current state cmp ttstate,offset tekesc ; ESC Control-X? je tektt13 ; yes, parse it in tekesc code mov ttstate,offset tektxt ; back to text mode test flags.vtflg,tttek ; main Tek emulator? jnz tektt12 ; nz = yes, ignore the ^X call tekend ; else exit sub mode mov tekflg,0 ; clear Tek sub mode flag tektt12:mov prestate,offset tektxt ; make previous state text tektt14:ret tektt13:jmp ttstate ; let someone else worry about this TEKEMU ENDP ; End TEK emulation, recover previous screen TEKEND PROC NEAR cmp tekflg,0 ; Tek sub mode active? jne teknd0 ; ne = yes ret ; else return as is. teknd0: call teksave ; save graphics screen to page 1 cmp graph_mode,hercules ; Hercules? jne teknd1 ; ne = no call htext ; yes then set up Hercules text mode teknd1: mov ah,0 ; set video mode mov al,curmode ; restore previous screen mode int screen ; revert to text screen call restscr ; restore text screen mov dx,cursor ; saved cursor position mov bh,0 ; page 0 mov ah,2 ; set cursor int screen ret TEKEND ENDP ; State machine active while Tek is active. Senses ESC [ ? 3 8 l to exit ; Tek mode and return to either non-sub mode terminal or to a VT102. ; Plays back unmatched escape sequences. Enter with character in al. tkscan proc near and al,7fh ; strip high bit cmp al,byte ptr tkoff ; start of Tek Off sequence? jne tkscn1 ; ne = no call tkscn4 ; playback previously matched chars mov tkcnt,1 ; count matched chars (one now) mov tkoffs,al ; save full character, with high bit mov al,0 ; our temporary response jmp short tkscnx ; and exit tkscn1: push bx ; check for char in Tek Off sequence mov bx,tkcnt ; number of chars matched in Tek Off mov tkoffs[bx],al ; save this char cmp al,byte ptr tkoff[bx] ; match expected char in sequence? pop bx jne tkscn3 ; ne = no, play back partial match inc tkcnt ; count new match mov al,0 ; our temporary response cmp tkcnt,tkofflen ; matched all char in sequence? jne tkscnx ; ne = not yet, wait for more mov tkcnt,0 ; clear counter cmp flags.vtflg,tttek ; are we a full Tek terminal now? jne tkscn2 ; ne = no, a submode call vtans52 ; toggle terminal type, in msyibm tkscn2: mov al,CAN ; simulate arrival of Control-X jmp short tkscnx ; all done tkscn3: call tkscn4 ; playback previously matched chars mov tkcnt,0 ; reset to no match and exit tkscnx: ret ; common exit ; local worker procedure tkscn4: push ax ; save break char (in al) push cx ; playback partial sequence to screen mov cx,tkcnt ; number of chars matched before break jcxz tkscn4b ; z = none push si mov si,offset tkoffs ; string to be played back tkscn4a:cld lodsb ; get a char into al push cx push si ; save these around tektt5a work call tektt5a ; use it pop si pop cx loop tkscn4a ; do all that came in previously pop si tkscn4b:pop cx pop ax ; recover break char ret tkscan endp TEKTXT proc near ; Dispatch on text characters cmp al,DEL ; RUBOUT? jne tektx1 ; ne = no mov al,bs ; make BS jmp short tektx7 tektx1: cmp al,CR ; carriage return (^M)? je tektx9 ; e = yes tektx2: cmp al,LF ; line feed (^J)? je tektx9 ; e = yes tektx3: cmp al,FF ; form feed (^L)? jne tektx4 ; ne = no call tekcls ; clear the screen jmp short tektx8 tektx4: cmp al,VT ; vertical tab (^K)? je tektx7 cmp al,bell ; bell (^G)? jne tektx5 ; ne = no call beep mov bypass,0 ; clear GIN mode bypass condition jmp short tektx8 tektx5: cmp al,tab ; horizontal tab (^I)? je tektx7 ; e = yes tektx6: cmp al,BS ; backspace (^H)? je tektx7 ; e = yes cmp al,' ' ; control char? jb tektx8 ; b = yes, ignore it tektx7: cmp bypass,0 ; bypass mode off? jne tektx8 ; ne = no, it's on so skip display call OUTSCRN ; output character to the screen tektx8: ret tektx9: mov bypass,0 ; clear GIN mode bypass condition jmp short tektx7 TEKTXT endp ; Process escape sequences. Callable from msz terminal emulator. ; Enter with received character in AL. Escape sequences are generally ; treated as interruptions to the current plotting/text command. Screen ; clearing is the exception by causing a general emulator reset. TEKESC PROC NEAR mov bypass,0 ; clear GIN mode bypass condition mov ttstate,offset tekesc ; in case get here from msz file cmp tekflg,0 ; Tek mode active yet? (msz call) jne tekesc1 ; ne = yes call tekini ; init now mov prestate,offset tektxt ; set a previous state of text jnc tekesc1 ; nc = succeeded ret ; else failed to init, just return tekesc1:cmp al,'Z' ; ESC-Z Identify? jne tekesc2 ; ne = no call SENDID ; Send terminal identification jmp tekescx tekesc2:cmp al,FF ; ESC-FF Clear screen? jne tekesc3 ; ne = no call tekcls ; Clear screen mov prestate,offset tektxt ; make previous state text mode jmp tekescx ; Return to text mode after ESC-FF tekesc3:cmp al,ESCZ ; ESC-^Z Enter GIN mode? jne tekesc4 ; ne = no cmp graph_mode,mono ; Monochrome text mode? je tekesc3a ; e = yes, no crosshairs in text mode mov bypass,1 ; turn on GIN mode bypass conditon call CROSHAIR ; Activate the cross-hairs jmp tekescx tekesc3a:call beep ; tell the user we are unhappy jmp tekescx ; and ignore the command tekesc4:cmp al,ENQ ; ESC-^E Enquiry for cursor position? jne tekesc5 ; ne = no mov bypass,1 ; set bypass mode call SENDSTAT ; send status jmp tekescx tekesc5:cmp al,CAN ; ESC Control-X? jne tekesc6 ; ne = no mov bypass,1 ; set bypass condition jmp tekescx tekesc6:cmp al,3fh ; query mark? (ESC ? means DEL) jne tekesc7 ; ne = no mov al,DEL ; replace with DEL code jmp tekescx ; and process it as if received. tekesc7:cmp al,accent ; accent grave, line pattern series? jb tekesc8 ; b = no cmp al,65h ; lowercase e? ja tekescx ; a = beyond line pattern series push bx mov bl,al sub bl,accent ; remove bias and bl,7 ; eight patterns, roll over excess mov bh,0 shl bx,1 ; make this a word index mov bx,linetab[bx] ; get line pattern word mov linepat,bx ; save in active word pop bx ; return to previous mode tekesc8:cmp al,5bh ; right square bracket? jne tekescx ; ne = no jmp tekcol ; start coloring scan tekescx:push ax mov ax,prestate ; get previous state mov ttstate,ax ; restore it or ax,ax ; test for none pop ax jz go2text ; z = none, use text mode clc ret ; resume previous state go2text:mov ttstate,offset tektxt ; Go to TEKTXT next time mov lastc,0 ; clear last drawing coordinate flag or status,txtmode ; set text mode in status byte clc ret TEKESC ENDP ; Parse ESC [ Pn ; Pn m ; where Pn = 30-37 foreground color, 40-47 background color, ANSI standard TEKCOL proc near mov word ptr lastd,0 ; clear parsing flags used below mov ttstate,offset tekco1 ; resume parsing below clc ret tekco1: cmp lastd,'3' ; units digit in 30 series? jne tekco2 ; ne = no inc lastd+1 ; count argument sub al,'0' ; ascii to binary cmp al,7 ; numeric? jbe tekco1a ; be = yes jmp tekco10 ; a = no, error tekco1a:push bx mov bl,al mov bh,0 mov al,byte ptr colortb[bx] ; reverse coloring pop bx and tfcol,not (7) ; retain intensity bit or tfcol,al ; remember foreground color mov lastd,0 ; clear parsing flag ret tekco2: cmp lastd,'4' ; units digit in 40 series? jne tekco4 ; ne = no inc lastd+1 ; count argument sub al,'0' cmp al,7 ; numeric? ja tekco10 ; a = no, error push bx mov bl,al mov bh,0 mov al,byte ptr colortb[bx] ; reverse coloring pop bx mov tbcol,al ; remember background color mov lastd,0 ; clear parsing flag ret tekco4: cmp lastd,0 ; looking for tens digit? jne tekco10 ; ne = yes, error cmp al,';' ; separator? jne tekco5 ; ne = no ret ; ignore it tekco5: cmp al,'0' ; remove intensity, set b/w? jne tekco6 ; ne = no mov tfcol,7 ; regular white mov tbcol,0 ; on black inc lastd+1 ; count argument ret tekco6: cmp al,'1' ; intensity bit? jne tekco7 ; ne = no and tfcol,not (8) or tfcol,8 ; set foreground intensity inc lastd+1 ; count argument ret tekco7: cmp al,'m' ; end of sequence je tekco8 ; e = yes cmp al,'3' jb tekco10 ; b = not allowed tens digit cmp al,'4' ja tekco10 ; a = not allowed tens digit mov lastd,al ; remember tens digit inc lastd+1 ; count argument ret tekco8: cmp lastd+1,0 ; number of ansi arguments, zero? ja tekco9 ; a = no, got some mov tbcol,0 ; none is same as 0, set b/w mov tfcol,7 tekco9: mov al,tbcol ; success, store coloring mov gbcol,al ; set background color mov al,tfcol mov gfcol,al ; set foreground color tekco10:mov word ptr lastd,0 ; clear argument and number of args call fixcolor ; do special ega corrections mov al,gfcol ; update these in case error mov tfcol,al mov al,gbcol mov tbcol,al jmp tekescx ; finish escape state TEKCOL endp ; Revise screen color codes for ega boards with mono displays and limited ; memory. fixcolor proc near cmp graph_mode,ega ; one of these ega modes? je fixcol0 ; e = yes cmp graph_mode,colorega je fixcol0 cmp graph_mode,monoega je fixcol0 ret ; else ignore color corrections fixcol0:mov ah,gfcol mov al,gbcol cmp graph_mode,monoega ; monochrome display? jne fixcol3 ; ne = no test al,7 ; bright backgound? jnz fixcol1 ; nz = yes mov ah,1 ; normal foreground test gfcol,8 ; intensity on? jz fixcol1 ; z = no mov ah,5 ; say bright foreground fixcol1:test al,7 ; black backgound? jz fixcol2 ; z = yes mov al,1 ; regular video fixcol2:cmp ah,al ; same color in both? jne fixcol3 ; ne = no mov ah,1 ; make foreground regular mov al,0 ; and background black fixcol3:mov gfcol,ah mov gbcol,al cmp gpage,0 ; minimal memory (64KB mono and ega)? ja fixcol4 ; a = no, enough, else strange mapping mov al,gfcol ; fix coloring to map planes C0 to C1 and al,5 ; and C2 to C3 (as 0, 3, 0Ch, or 0Fh) mov ah,al ; make a copy shl ah,1 ; duplicate planes C0, C2 in C1, C3 or al,ah ; merge the bits mov gfcol,al ; store proper foreground color mov al,gbcol ; repeat for background color and al,5 mov ah,al shl ah,1 or al,ah mov gbcol,al fixcol4:ret fixcolor endp TEKLINE proc near ; GS line drawing call tekxyc ; parse coordinates from input bytes jnc teklin1 ; nc = not done yet mov cl,visible ; get moveto or drawto variable call tekdraw ; move that point mov visible,1 ; say next time we draw teklin1:ret TEKLINE endp TEKPNT proc near ; FS plot single point call tekxyc ; parse coordinates jnc tekpnt1 ; nc = not done yet mov cl,0 ; do not draw call tekdraw ; move to the point mov ax,si ; copy starting point to end point mov bx,di ; ax,bx,si,di are in PC coordinates mov cl,1 ; make plot visible call line ; draw the dot mov visible,0 ; return to invisibility tekpnt1:ret TEKPNT endp ; Decode graphics x,y components. Returns carry set to say have all ; components for a line, else carry clear. Understands 4014 lsb extensions. ; Permits embedded escape sequences. TEKXYC proc near cmp al,CR ; Exit drawing on CR,LF,RS,US,FS,CAN je tekghx ; e = yes, a cr cmp al,LF ; these terminate line drawing cmds je tekghx cmp al,FS ; <FS> je tekghx cmp al,RS ; <RS> je tekghx cmp al,US ; <US> je tekghx cmp al,CAN ; and <CAN> je tekghx ; BUT ignore other control chars cmp al,20h ; Control char? jb tekgh0 ; b = yes, ignore it cmp al,40h jb tekgh2 ; 20-3F are HIX or HIY cmp al,60h ; 40-5F are LOX (causes beam movement) jb tekgh4 ; 60-7F are LOY ; Extract low-order 5 bits of Y coord mov ah,tek_loy ; Copy previous LOY to MSB (4014) mov tek_lsb,ah and al,1Fh ; LOY is 5 bits mov tek_loy,al cmp lastc,loy ; 2nd LOY in a row? je tekgh1 ; Yes, then LSB is valid mov tek_lsb,0 ; 1st one, clear LSB tekgh1: mov lastc,loy ; LOY seen, expect HIX (instead of HIY) tekgh0: clc ; c clear = not completed yet ret tekghx: jmp go2text ; Extract high-order 5 bits (X or Y, depending on lastc) tekgh2: and ax,1Fh ; Just 5 bits mov cl,5 shl ax,cl ; Shift over 5 bits cmp lastc,loy ; was last coordinate a low-y? je tekgh3 ; e = yes, parse hix mov tek_hiy,ax ; this byte has HIY mov lastc,hiy clc ret tekgh3: mov tek_hix,ax ; This byte has HIX mov lastc,hix clc ret tekgh4: and al,1Fh ; Just 5 bits mov tek_lox,al mov lastc,lox mov ax,tek_hix ; Combine HIX*32 or al,tek_lox ; with LOX mov bx,tek_hiy ; Same for Y or bl,tek_loy stc ; set c to say completed operation ret TEKXYC endp TEKRLIN proc near ; RS relative line drawing cmp al,' ' ; Pen up command? jne tekrli1 ; ne = no, try pen down mov visible,0 ; do invisible movements jmp short tekrli2 ; do the command tekrli1:cmp al,'P' ; pen down command? jne tekrli3 ; ne = no, return to text mode mov visible,1 ; set visible moves tekrli2:mov ax,x_coord ; PC x coordinate of pen mov bx,y_coord ; y coordinate call pctotek ; get current pen position in Tek coor mov cl,0 ; invisible, moveto call tekdraw ; move that point, set oldx and oldy mov ttstate,offset tekinc ; next get incremental movement cmds ret tekrli3:mov visible,0 ; bad char, reset visibility push prestate pop ttstate ; restore previous state jmp tektt5 ; deal with the break char TEKRLIN endp ; interpret RS inc plot command byte TEKINC proc near ; get movement character and do cmd cmp al,'A' ; move right? jne tekinc1 ; ne = no inc oldx ; adjust beam position jmp short tekinc9 tekinc1:cmp al,'E' ; move right and up? jne tekinc2 ; ne = no inc oldx inc oldy jmp short tekinc9 tekinc2:cmp al,'D' ; move up? jne tekinc3 ; ne = no inc oldy jmp short tekinc9 tekinc3:cmp al,'F' ; move left and up? jne tekinc4 ; ne = no dec oldx inc oldy jmp short tekinc9 tekinc4:cmp al,'B' ; move left? jne tekinc5 ; ne = no dec oldx jmp short tekinc9 tekinc5:cmp al,'J' ; move left and down? jne tekinc6 ; ne = no dec oldx dec oldy jmp short tekinc9 tekinc6:cmp al,'H' ; move down? jne tekinc7 ; ne = no dec oldy jmp short tekinc9 tekinc7:cmp al,'I' ; move right and down? jne tekincb ; ne = no, bad command inc oldx dec oldy tekinc9:cmp oldx,0 ; too far left? jge tekinc10 ; ge = no mov oldx,0 ; else stop at the left margin tekinc10:cmp oldx,maxtekx-1 ; too far left? jle tekinc11 ; le = no mov oldx,maxtekx-1 ; else stop that the left margin tekinc11:cmp oldy,maxteky-1 ; above the top? jle tekinc12 ; le = no mov oldy,maxteky-1 ; else stop at the top tekinc12:cmp oldy,0 ; below the bottom? jge tekinc13 ; ge = no mov oldy,0 ; else stop at the bottom tekinc13:mov ax,oldx ; ax is vector x end point mov bx,oldy ; bx is vector y end point mov cl,visible call tekdraw ; move/draw to that point ret tekincb:push prestate ; bad character, exit inc plot mode pop ttstate ; new state is previous state mov visible,0 jmp tektt5 ; reparse the bad char TEKINC endp ; Routine to trigger the crosshairs, wait for a key to be struck, and send ; the typed char (if printable ascii) plus four Tek encoded x,y position ; coordinates and then a carriage return. ; ax, cx, xcross, ycross operate in PC coordinates. CROSHAIR PROC NEAR push linepat ; save line drawing pattern mov linepat,0ffffh ; reset line type to solid mov ax,xmax ; right margin minus 7 dots add ax,7 mov temp,ax ; right margin dot crosha1:call crosdraw ; draw the cross-hairs call iseof ; is stdin at EOF? jc crosha2 ; c = yes, exit this mode now mov ah,coninq ; DOS, quiet read char int dos push ax ; save char for later call crosdraw ; erase cross hairs pop ax or al,al ; ascii or scan code returned jnz arrow5 ; nz = ascii char returned call iseof ; is stdin at EOF? jc crosha2 ; c = yes, exit this mode now mov ah,coninq ; read scan code int dos cmp al,0 ; Control-Break? jne crosha3 ; ne = no, something else crosha2:pop linepat ; restore line pattern ret ; exit crosshairs mode crosha3:cmp al,homscn ; is it 'home'? jne arrow1 ; ne = no, try other keys mov ax,temp ; right margin shr ax,1 ; central position mov xcross,ax ; save PC coord for crosshair mov ax,ybot ; last scan line shr ax,1 mov ycross,ax ; this is the center of the screen jmp crosha1 ; home the crosshairs arrow1: cmp al,lftarr ; left arrow? jne arrow2 ; ne = no mov cx,-1 ; left shift jmp short xkeys arrow2: cmp al,rgtarr ; right arrow? jne arrow3 ; ne = no mov cx,1 ; right shift jmp short xkeys arrow3: cmp al,uparr ; up arrow? jne arrow4 ; ne = no mov cx,-1 ; up shift jmp short vertkey arrow4: cmp al,dnarr ; down arrow? jne badkey ; ne = no, ignore it mov cx,1 ; down shift jmp short vertkey badkey: call beep ; tell user we don't understand jmp crosha1 ; keep going ; Shifted keys yield ascii keycodes arrow5: cmp al,'C' and 1fh ; Control-C? je crosha2 ; e = yes, exit crosshairs mode now cmp al,shlftarr ; shifted left arrow? jne arrow6 ; ne = no mov cx,-10 ; big left shift jmp short xkeys arrow6: cmp al,shrgtarr ; shifted right arrow? jne arrow7 ; ne = no mov cx,10 ; big right shift jmp short xkeys arrow7: cmp al,shuparr ; shifted up arrow? jne arrow8 ; ne = no mov cx,-10 ; big up shift jmp short vertkey arrow8: cmp al,shdnarr ; shifted down arrow? jne charkey ; ne = no, send this key as is mov cx,10 ; big down shift jmp short vertkey xkeys: add cx,xcross ; add increment jns noxc ; gone too far negative? mov cx,0 ; yes - then make it 0 noxc: cmp cx,temp ; too far right? jb xdraw9 ; b = no mov cx,temp ; yes - then make it the right xdraw9: mov xcross,cx ; new x value for cross hairs jmp crosha1 ; and redraw vertkey:add cx,ycross ; adjust cx jns noyc ; gone negative? mov cx,0 ; yes then make 0 noyc: cmp cx,ybot ; too high? jb yok mov cx,ybot ; make it maximum yok: mov ycross,cx ; save new y crosshair jmp crosha1 ; and redraw charkey:call clrbuf ; purge received data to date call outmodem ; send the break character mov ax,xcross ; set beam to xcross,ycross mov bx,ycross ; must convert to Tek coordinates call pctotek ; scale from PC screen coord to Tek push ax ; save around drawing push bx mov cx,0 ; just a move call tekdraw ; moveto ax,bx in Tek coord pop bx ; recover Tek y pop ax ; recover Tek x call sendpos ; send position report to host pop linepat ; recover current line drawing pattern mov ttstate,offset tektxt ; Go to TEKTXT next time mov lastc,0 ; clear last drawing coordinate flag or status,txtmode ; set text mode in status byte ret CROSHAIR ENDP ; CROSDRAW draws cross-hairs by XORing cross with picture. ; xcross and ycross are in PC coordinates. CROSDRAW PROC NEAR mov si,xcross ; move to (xcross, ycross-10) mov di,ycross sub di,10 ; half the size of the cross jns crosd1 ; no sign bit means ok mov di,0 ; else limit to start of screen crosd1: mov ax,si ; next, draw to (xcross, ycross+10) mov bx,ycross ; make bottom stroke add bx,10 cmp bx,ybot ; too large? jbe crosd2 ; be = no mov bx,ybot ; vertical line to (xcross,ybot) crosd2: mov cx,0ffh ; invert pixels call line ; and draw vertical sub si,12 ; move to (xcross-12, ycross) jns crosd3 ; no sign means ok mov si,0 ; else limit to start of line crosd3: mov di,ycross mov bx,di mov ax,xcross ; draw to (xcross+12, ycross) add ax,12 cmp ax,temp ; temp is right margin, too large? jbe crosd4 ; be = no, ok mov ax,temp ; max x value crosd4: mov cx,0ffh ; set XOR code call line ; draw to (xcross+12, ycross) ret CROSDRAW ENDP ; SENDPOS sends position of cross-hairs to the host. ; ax has Tek X and bx has Tek Y coord of center of crosshair SENDPOS PROC NEAR push bx ; preserve register call sendxy ; send x coord pop ax call sendxy ; send y coord mov al,cr ; follow up with cr call outmodem ret SENDPOS ENDP ; SENDXY sends value of ax as Tek encoded bytes ; ax is in Tek coordinates SENDXY PROC NEAR shl ax,1 shl ax,1 ; move all but lower 5 bits to ah shl ax,1 shr al,1 shr al,1 ; move low five bits to low 5 bits shr al,1 or ah,20h ; make it a printing char as per TEK xchg al,ah ; send high 5 bits first call outmodem xchg al,ah ; then low five bits or al,20h call outmodem xchg ah,al ; al is first sent byte ret SENDXY ENDP SENDID PROC NEAR ; Pretend VT100 with graphics option mov bx,IDSEQ ; Get addr of string sndid1: mov al,[bx] ; Get char from sequence cmp al,0 ; End of sequence? jz sndid0 ; Yes, return call OUTMODEM ; Send it out the port inc bx jmp sndid1 sndid0: ret SENDID ENDP ; SENDSTAT - send status and cursor position to host SENDSTAT PROC NEAR mov al,STATUS ; get tek status or al,20h ; make it printable call OUTMODEM ; and send it mov ax,oldx ; now send x coordinate (oldx is Tek) call SENDXY mov ax,oldy ; and y coordinate (oldy is Tek coord) call SENDXY mov al,cr ; end with a cr call OUTMODEM ret SENDSTAT ENDP ; routine to send al to the modem port OUTMODEM PROC NEAR push ax mov ah,al call outchr ; outchr reads from ah nop ; ignore errors nop nop pop ax ret OUTMODEM ENDP ; Convert X and Y from PC coordinates to Tek coordinates. AX = X, BX = Y ; for both input and output. pctotek proc near mul xdiv ; scale from PC screen coord to Tek div xmult xchg bx,ax ; save Tek x coord in bx neg ax ; y axis. Turn upside down for Tek add ax,ybot mul ydiv ; scale y from PC screen coord to Tek div ymult xchg ax,bx ; ax has X, bx has Y in Tek coords ret pctotek endp ; Routine to output character in AL to the screen. OUTSCRN PROC NEAR ; Output one character to the screen cmp bypass,0 ; GIN mode bypass off? je outscp ; e = yes ret ; else ignore characters outscp: ; Set Translation Input filter cmp rxtable+256,0 ; translation turned off? je outsct ; e = yes, no translation push bx mov bx,offset rxtable ; address of translate table xlatb ; new char is in al and al,7fh ; retain only lower seven bits pop bx outsct: mov si,ybot ; get last scan line inc si ; number of scan lines sub si,y_coord ; minus where char bottom needs to go jnc outscc ; nc = enough space for char ; else give "More >" message push ax ; save current char push cx mov cx,mormsglen ; characters in More message mov ax,cx shl ax,1 shl ax,1 shl ax,1 ; times 8 bits/character neg ax ; (note: leave last char cell empty) add ax,xmax ; right justify mov x_coord,ax ; set starting x dot mov ax,ybot mov y_coord,ax ; set starting y line mov ccode,1 ; write in foreground colors push cx mov al,DEL ; fill all pixels outscm1:call putc ; write loop outscm1 pop cx push cx mov al,BS ; backup to overwrite with More text outscm2:call putc loop outscm2 pop cx mov ccode,0 ; main text in background colors mov si,offset moremsg ; give More message outsclf:cld lodsb ; read a byte from string call putc ; display the string loop outsclf ; repeat for all string chars pop cx mov ccode,1 ; restore normal foreground coloring call iseof ; EOF on redirected stdin? jc outscl3 ; c = yes, proceed anyway mov ah,coninq ; read keyboad via DOS int dos ; wait for keystroke or al,al ; scan code being returned? jne outscl3 ; ne = no mov ah,coninq ; clear away scan code too int dos outscl3:call tekcls ; clear the screen pop ax ; recover current character cmp al,lf ; just a line feed? jne outscc ; ne = no, display it ret ; else ignore the line feed outscc: push ax mov ax,xmax cmp x_coord,ax ; beyond right margin? jbe outsc3 ; be = no mov al,cr ; else simulate cr/lf call putc ; before displaying current char mov al,lf call putc outsc3: pop ax call putc ; routine to draw characters ret OUTSCRN ENDP ; TEKCLS routine to clear the screen. ; Entry point tekcls1 clears screen without resetting current point. TEKCLS PROC NEAR cmp tekflg,0 ; Tek sub mode active yet? jne tekcls0 ; ne = yes ret ; else ignore this call tekcls0:mov x_coord,0 ; starting text coordinates mov y_coord,8 mov oldx,0 ; assumed cursor starting location mov oldy,maxteky ; top right corner (Tek coord) mov scalex,0 ; clear last plotted point (PC coord) mov scaley,0 mov lastc,0 ; last parsed x,y coordinate mov visible,0 ; make lines invisible mov linepat,0ffffh ; reset line pattern to solid mov ccode,1 ; reset to ordinary writing mov bypass,0 ; clear bypass condition mov ttstate,offset tektxt ; do displayable text push ax mov ax,xmax ; right margin minus 7 dots add ax,7 ; right most dot shr ax,1 ; central position mov xcross,ax ; save PC coord for crosshair mov ax,ybot ; last scan line shr ax,1 mov ycross,ax ; this is the center of the screen pop ax tekcls1:push ax ; save registers push cx cmp graph_mode,hercules ; Hercules? jne tekcls2 ; ne = no call hgraf ; set Hercules board to Graphics mode jmp tekcls7 tekcls2:mov di,0 ; point to start of screen, di=row call psetup ; setup graphics routine and es:di mov cx,4000h ; CGA, 200 lines times 80 bytes worth cmp graph_mode,cga ; cga? je tekcls3 ; e = yes mov cx,8000h ; Olivetti, 400 lines times 80 bytes cmp graph_mode,olivetti ; AT&T-Olivetti? je tekcls3 ; e = yes cmp graph_mode,toshiba ; Toshiba? je tekcls3 ; e = yes cmp graph_mode,vaxmate ; VAXmate? jne tekcls4 ; ne = no tekcls3:cld ; clear screen directly of text stuff mov al,0 ; color is black rep stosb ; clear the bytes jmp short tekcls7 tekcls4:cmp graph_mode,ega ; EGA? je tekcls5 ; e = yes cmp graph_mode,monoega ; EGA with mono display? je tekcls5 ; e = yes cmp graph_mode,colorega ; EGA with medium resolution monitor? je tekcls5 ; e = yes jmp short tekcls6 ; else use Bios tekcls5: ; EGA clear screen quickly mov ax,0ff08h ; set all 8 bits to be changed call ega_gc ; set bit mask register accordingly mov cx,ybot ; last scan line inc cx ; number of scan lines mov ax,80 ; bytes per scan line mul cx mov cx,ax ; cx = number of bytes to clear mov al,gbcol ; select background colour cld rep stosb ; write backgound color jmp short tekcls7 tekcls6:push es ; clear screen by scrolling up call cmblnk ; clear screen, for Environments pop es tekcls7:mov si,0 ; starting x (in case screen is mov di,0 ; starting y cleared by user) pop cx pop ax ret TEKCLS ENDP ; Routine to draw a line on the screen, using TEKTRONIX coordinates. ; X coordinate in AX, 0=left edge of screen, 1023=right edge of screen. ; Y coordinate in BX, 0=bottom of screen, 779=top of screen. ; CL=0 - invisible move, CL=1 - draw a line, CL=0FFh - invert pixels on line TEKDRAW PROC NEAR mov si,scalex ; get old x already scaled mov di,scaley ; get old y already scaled call scale ; scale new end point to PC coords cmp cl,0 ; invisible drawing? je moveto ; z = just move, skip draw part call LINE ; draw the line moveto: mov x_coord,ax ; update text coordinates to match mov y_coord,bx ; last drawn point ret TEKDRAW ENDP ; Scale TEKTRONIX coordinates to the currently defined screen coordinates ; AX holds X axis, BX holds Y axis. Both are changed from Tektronix coord ; to PC coordinates by this procedure. SCALE PROC NEAR push dx push si mov oldx,ax ; save current Tek x for next draw mov oldy,bx ; save current Tek y for next draw mul xmult ; scale x-coord mov si,xdiv ; get the divisor shr si,1 ; halve it add ax,si ; add in - to round to nearest integer adc dx,0 div xdiv push ax mov ax,bx mul ymult ; scale y-coord mov si,ydiv ; get divisor shr si,1 ; halve it add ax,si ; add in - to round to nearest integer adc dx,0 div ydiv mov bx,ybot sub bx,ax ; Put new Y in right reg jns scale3 ; ns = not too far mov bx,0 scale3: pop ax ; Put new X in right reg mov scalex,ax ; save scaled values mov scaley,bx pop si pop dx ret SCALE ENDP ; LINE Subroutine to plot a line with endpoints in AX,BX and SI,DI. ; fast line drawing routine for the IBM PC ; ; Registers at CALL ; ----------------- ; SI=Start X coord, all in PC coordinates ; DI=Start Y coord ; AX=End X coord ; BX=End Y coord ; CL=Color code: 1=draw foreground, 0=draw background, 0ffh=invert ; BP= line drawing pattern (is changed here by rotation) ; registers are all unchanged LINE PROC NEAR push ax push bx push cx push dx push si push di push es mov bp,linepat ; store active line pattern word in BP mov ccode,cl ; save color code in ccode for use by plot() ; first get coord to achieve increasing x; deltax >= 0 sub ax,si ; deltax = x2 - x1 jge line1 ; ge = going to the right, as desired neg ax ; make deltax non-negative sub si,ax ; swap the x coordinates xchg bx,di ; swap the y coordinates too ; second, compute deltay. ax = deltax, si = x1 line1: sub bx,di ; deltay = y2 - y1 call psetup ; setup display adapter for plotting ; and setup es:di to screen memory ; Choose algorithm based on |deltay| < |deltax| (use shallow) else steep. ; We arrange matters such that both deltas are non-negative. cmp bx,0 ; deltay jge line2 ; ge = non-negative neg linelen neg bx ; make non-negative line2: cmp bx,ax ; |deltay| versus |deltax| jbe shallow ; be = do shallow algorithm jmp steep ; else do steep algorithm ; shallow algorithm, move along x, di=y1, bx=deltay, si=x1, ax=deltax shallow:add bx,bx ; bx = 2*deltay mov cx,ax ; cx = number of steps (deltax here) inc cx ; loop dec's cx before testing mov dx,bx ; dx holds error sub dx,ax ; error = 2*deltay - deltax add ax,ax ; ax = 2*|deltax| shal1: call plotptr ; Plot(x,y) cmp dx,0 jle shal2 ; le = error <= 0 call pincy ; increment y by one scan line sub dx,ax ; error = error - 2*deltax shal2: add dx,bx ; error = error + 2*deltay inc si ; x = next dot right loop shal1 shal3: jmp short plotex ; steep algorithm, move along y, di=y1, bx=deltay, si=x1, ax=deltax steep: add ax,ax ; ax = 2*deltax mov dx,ax ; dx holds error sub dx,bx ; error = 2*deltax(bx) - deltay (bx) mov cx,bx ; cx = number of steps (deltay here) inc cx ; loop dec's cx before testing add bx,bx ; bx = 2*|deltay| stee1: call plotptr ; Plot(x,y) x = ax, y = di cmp dx,0 jle stee2 ; le error <= 0 inc si ; x = next dot right sub dx,bx ; error = error - 2*deltay stee2: add dx,ax ; error = error + 2*deltax call pincy ; increment y loop stee1 stee3:;;;jmp plotex plotex: mov ccode,1 ; reset to do foreground coloring pop es pop di pop si pop dx ; restore the world pop cx pop bx pop ax ret LINE ENDP ;;;;;;; EGA plot support routines psetupe proc near ; EGA setup for plotting push ax mov linelen,80 ; for y going down screen by pincy mov ax,segscn ; set es to screen memory segment mov es,ax mov ax,0205h ; mode: write mode 2 call ega_gc mov ax,0003h ; assume writing bits directly cmp ccode,0ffh ; inverting bits? jne psete2 ; ne = no mov ax,1803h ; then say XOR the bits psete2: call ega_gc ; set controller mov ax,80 ; compute starting point in regen buff mul di mov di,ax ; di = di * 80 pop ax ret psetupe endp pincye proc near ; EGA inc y add di,linelen ; includes sign of deltay ret pincye endp pltega proc near ; EGA plot(x,y). x is in si, y is in di rol bp,1 ; rotate line pattern jnc pltega1 ; nc = no bit to be plotted push bx push si push di mov bx,si ; want si/8 for bytes along line shr si,1 shr si,1 shr si,1 add di,si ; starting point in regen buffer and bx,0007h ; leave lower 3 bits for bit in byte mov bh,masktab[bx] ; 0-7 into bit mask in byte, x pos mov bl,ccode ; get line type code call ega_plt pop di pop si pop bx pltega1:ret pltega endp ;;;;;;;; CGA plot support routines ; The CGA graphics memory mapping in mode 6 (640 by 200) is 8 dots per byte, ; left most dot in the high bit, 80 bytes per scan line, scan line segments ; alternating between 0b800h (even lines 0, 2, ...) and 0ba00h (odd lines). psetupc proc near ; CGA setup for plotting push ax push cx mov linelen,80 ; 80 bytes per scan line mov cx,segscn mov es,cx mov cx,di ; save copy of di, start y line ; compute starting point in regen buff shr di,1 ; half the lines in each bank mov ax,80 ; 80 bytes per line mul di mov di,ax ; di = di * 80 / 2 test cx,1 ; even or odd line jz psetc1 ; z = even add di,2000h ; offset to odd bank (seg 0ba00h) psetc1: and di,3fffh pop cx pop ax ret psetupc endp pincyc proc near ; CGA inc y cmp linelen,0 ; increasing or decreasing y? jl pinyc2 ; l = decreasing cmp di,2000h ; in upper bank now? jb pinyc1 ; b = no, in lower bank add di,linelen ; add a line pinyc1: add di,2000h ; switch banks and di,3fffh ; roll over address ret pinyc2: cmp di,2000h ; in upper bank now? jae pinyc4 ; ae = yes add di,linelen ; subtract a line pinyc4: add di,2000h ; switch banks and di,3fffh ; roll over address ret pincyc endp pltcga proc near ; CGA plot(x,y). x is in si, y is in di push bx ; used for HGA plot also. push si push di rol bp,1 ; rotate line pattern jnc pltcg3 ; nc = no bit to be plotted mov bx,si ; want si/8 for bytes along line shr si,1 shr si,1 shr si,1 add di,si ; starting point in regen buffer and bx,0007h ; leave lower 3 bits for bit in byte ; di = offset in regen buffer mov bh,masktab[bx] ; 0-7 into bit mask in byte. x position mov bl,ccode ; get line type code cmp bl,1 ; draw the bit? jne pltcg1 ; ne = no or es:[di],bh ; drawn jmp short pltcg3 pltcg1: cmp bl,0 ; draw in background (erase)? jne pltcg2 ; ne = no not bh and es:[di],bh ; erase the dots jmp short pltcg3 pltcg2: xor es:[di],bh ; xor in this color pltcg3: pop di pop si pop bx ret pltcga endp ;;;;;;; HGA plot support routines ; The HGA graphics memory mapping in mode 255 (720 by 348) is 8 dots per byte, ; left most dot in the high bit, 90 bytes per scan line, scan line segments ; sequence as 0b000h, 0b200h, 0b400h, 0b800h for lines 0-3 and repeat 90 bytes ; higher for the rest. psetuph proc near ; HGA setup for plotting push ax push cx mov linelen,90 ; for y going down screen by incy mov ax,segscn ; base segment of display memory mov es,ax mov cx,di ; save copy of di, start y line ; compute starting point in regen buff shr di,1 ; quarter the lines in each bank shr di,1 mov ax,90 mul di mov di,ax ; di = di * 90 / 4 and cx,3 ; compute bank from 2 lsb of line num jcxz pseth2 ; z means it is in bank 0 (0b000h) pseth1: add di,2000h ; add offset for each bank loop pseth1 ; do cx times pseth2: pop cx pop ax ret psetuph endp pincyh proc near ; HGA inc y, step offset of line cmp linelen,0 ; increasing y? jg pinyh2 ; g = yes cmp di,2000h ; in lowest for four banks? ja pinyh1 ; a = no add di,linelen ; yes, add a line pinyh1: add di,6000h ; move back by adding a lot and di,7fffh ; roll over address ret pinyh2: cmp di,6000h ; in top most bank? jb pinyh4 ; b = no add di,linelen ; yes, first add a line pinyh4: add di,2000h ; switch to next bank and di,7fffh ; roll over address ret pincyh endp ;;;;;;; AT&T-Olivetti, Toshiba, VAXmate Graphics Adapter plot support routines ; The graphics memory mapping in 640 by 400 mode is 8 dots per byte, ; left most dot in the high bit, 80 bytes per scan line, scan line segments ; sequence as 0b800h, 0ba00h, 0bc00h, 0be00h for lines 0-3 and repeat 80 bytes ; higher for the rest. Use Hercules line incrementing (inc y) and CGA dot ; writing. This is a monographic display. psetupo proc near ; setup for plotting push ax push cx mov linelen,80 ; for y going down screen by incy mov ax,segscn ; base segment of display memory mov es,ax mov cx,di ; save copy of di, start y line ; compute starting point in regen buff shr di,1 ; quarter the lines in each bank shr di,1 mov ax,80 mul di mov di,ax ; di = di * 80 / 4 and cx,3 ; compute bank from 2 lsb of line num jcxz pseto2 ; z means it is in bank 0 (0b800h) pseto1: add di,2000h ; add offset for each bank loop pseto1 ; do cx times pseto2: pop cx pop ax ret psetupo endp ;;;;;;;; Monochrome, simulate dots with text char psetupm proc near mov linelen,1 ; 80 characters but one line ret psetupm endp pltmon proc near ; Monochrome dot plot mov x_coord,si ; put dot at row=di, col=si, PC Coord mov y_coord,di push ax mov al,'+' ; our dot character call mputc ; display text char pop ax ret pltmon endp pincym proc near ; Monochrome inc y add di,linelen ; includes sign ret pincym endp ; GPUTC - a routine to send text characters from font to true graphics boards ; such as EGA, Hercules or CGA. Char is in al. Drawing routine ptr is gcplot. gputc proc near cmp al,' ' ; control character? jae gputc1 ; ae = no, display the char jmp putctrl ; else handle controls at putctrl gputc1: push ax ; first save some registers push bx push cx push es push di mov bl,al ; now BL has char to be displayed and bl,7fh ; no high bits allowed here ; set board mode mov di,y_coord ; get current y coord (char bottom) sub di,8 ; start 8 lines higher jnc gputc2 ; nc = ok mov di,0 ; move up to first line mov y_coord,8 ; and reset scan line indicator gputc2: call psetup ; enter with di=line number, sets es:di to ; start of line in display buf and ; sets byte-wide plot mode mov ax,x_coord ; compute regen buffer byte shr ax,1 ; want x_coord/8 for bytes along line shr ax,1 shr ax,1 add di,ax ; byte in regen buffer xor bh,bh sub bx,32 ; characters in font start at 32 shl bx,1 shl bx,1 ; 8 bytes per char - hence * 8 shl bx,1 mov cx,8 ; 8 bytes (scan lines) to transfer call gcplot ; call character plot routine call incx ; move to next char position pop di pop es pop cx pop bx pop ax ret gputc endp putctrl proc near ; CONTROL CHARS = cursor movement push ax ; save character cmp al,FF ; formfeed? jne putct0 ; ne = no call TEKCLS ; FF clears the screen jmp putctx putct0: cmp al,BS ; BS? sends (logical) cursor back one jne putct2 ; ne = no, try next mov ax,x_coord sub ax,8 ; so delete 8 dots (move left) jns putct1 ; ns = non-negative mov ax,0 ; but not less than 0 putct1: mov x_coord,ax ; and replace x coordinate mov al,' ' ; send a space call putc sub x_coord,8 ; restore cursor jmp putctx putct2: cmp al,tab ; tabs move forward one char position jne putct4 ; ne = not a tab call incx ; let incx move cursor right one col jmp putctx putct3: mov x_coord,ax jmp putctx putct4: cmp al,cr ; <CR> means go to beginning of line jne putct5 mov x_coord,0 ; zero the x coordinate jmp putctx putct5: cmp al,lf ; <LF> means go down 8 pixels (1 line) jne putct7 ; ne = not LF add y_coord,8 ; border managed by outscrn and incx jmp putctx putct7: cmp al,vt ; <VT> move up screen 1 line (8 pixels) jne putctx sub y_coord,8 ; subtract one line (8 pixels) jnc putctx ; nc = space left mov y_coord,8 ; else set to top of screen putctx: pop ax ret putctrl endp mputc proc near ; MONO put char in AL via Bios push ax ; updates x_coord,y_coord with push bx ; new cursor position push cx push dx mov ah,0 ; marker for cursor setting not needed cmp al,' ' ; control code? jae mputc1 ; ae = no, printable call putctrl ; do cursor arithmetic mov ah,1 ; marker to set cursor but no display mputc1: push ax ; save char and marker mov cl,3 ; char cell is 8 x 8 dots mov ax,x_coord ; get resulting cursor PC positions shr ax,cl mov dl,al ; column mov ax,y_coord sub ax,8 ; minus 8 dots, like other modes jnc mputc2 ; nc = non-negative mov ax,0 ; else start at the top mov y_coord,8 ; here too mputc2: shr ax,cl mov dh,al ; row mov ah,2 ; set cursor to x_coord,y_coord mov bh,0 ; page 0 int screen pop ax cmp ah,0 ; write a char in al? jne mputcx ; ne = no mov ah,09h ; write char at cursor postion mov cx,1 ; just one char mov bh,0 ; page 0 mov bl,gfcol ; foreground coloring int screen inc dl ; next column mov ah,2 ; set real cursor ahead of last char int screen call incx ; move logical cursor mputcx: pop dx pop cx pop bx pop ax ret mputc endp incx proc near ; move the logical cursor right mov ax,x_coord ; shift the (logical) cursor right add ax,8 ; one character cell mov x_coord,ax cmp ax,xmax ; at end of the line? jbe incx1 ; b = no mov x_coord,0 ; wrap to next line add y_coord,8 ; next row mov ax,ybot ; last scan line cmp ax,y_coord ; below bottom line? jge incx1 ; ge = no mov y_coord,ax ; set to bottom row mov al,lf ; simulate a line feed operation call outscrn ; invoke More message incx1: ret incx endp ; EGA Character plot routine. Enter with bx pointing at font array for char ; cx = number of bytes in char font, es:di = screen memory. Worker for gputc. ; ccode: 0=plot in background colors, 1=foreground, 0ffh=xor with screen gcega proc near gcega1: mov al,font[bx] ; EGA byte plot: get bits from font push bx ;;;;; mov bh,0ffh ; write these bits to clear field ;;;;; mov bl,0 ; in background coloring ;;;;; call ega_plt ; plot a byte mov bh,al ; set bit pattern of character mov bl,ccode ; plot in back/fore/xor (ccode) colors call ega_plt ; byte plot routine for EGA systems pop bx inc bx ; next byte of char pattern call pincy ; next scan line (linelen is preset) loop gcega1 ret gcega endp ; General Character plot routine. Enter with bx pointing at font array for ; char, cx = number of bytes in char font, es:di = screen memory. ; Worker for gputc. gcgen proc near gcgen1: mov al,font[bx] ; Non-EGA systems: get bits from font cmp ccode,1 ; write in foreground? je gcgen2 ; e = yes xor es:[di],al ; background or xor (same) jmp short gcgen3 ;;;; mov es:[di],al ; write desired pattern (no overwrite) gcgen2: OR es:[di],al ; write desired pattern (no overwrite) gcgen3: inc bx ; point to next byte of char pattern call pincy ; next scan line (linelen is preset) loop gcgen1 ; and repeat until complete ret gcgen endp ; routines to manipulate ega graphics controller and mode register ; command code in al, value in ah - destroys al and dx ega_gc proc near ; ega graphics controller mov dx,3ceh out dx,al ; output command code inc dx ; dx is now data port mov al,ah ; get value to al out dx,al ; output value ret ega_gc endp ega_md proc near ; ega mode controller mov dx,3c4h out dx,al ; output command code inc dx ; dx is now data port mov al,ah ; get value to al out dx,al ; output value ret ega_md endp ; Plot eight pixels using an EGA board ; Enter with ES:[DI] pointing to screen address of byte, ; bh has pattern of bits to be set, bl has attributes: ; 0 = draw in background color, 1 = draw in foreground color, ; 0ffh = XOR with current dot colors. ; registers preserved ega_plt proc near push ax push dx mov al,8 ; command to set bit mask register mov ah,bh ; get bits to be modified (1) call ega_gc ; unprotect those bit positions mov ah,gfcol ; get foreground colour cmp bl,1 ; draw in foreground? je ega2 ; ne = no mov ah,gbcol ; get grahics background colour cmp bl,0ffh ; do an XOR? jne ega2 ; ne = no mov ah,0ffh ; XOR, touch all color bits ega2: mov al,es:[di] ; latch byte mov es:[di],ah ; set the byte pop dx pop ax ret ega_plt endp ; routine to set Hercules card to graphics mode - both pages are enabled HGRAF PROC NEAR push ax push bx ; save used registers push cx push si mov al,grph ; graph mode lea si,gtable ; requires graphics table mov bx,0 mov cx,4000h ; clear 4000h words call setmd ; and set the mode pop si pop cx pop bx pop ax ret HGRAF ENDP ; set Hercules card to text mode HTEXT PROC NEAR push ax push bx push cx push si mov al,text ; text mode lea si,ttable ; requires text table mov bx,0720h ; blank value (space, white on black) mov cx,2000 ; whole screen to clear (80*25) call setmd ; set the mode pop si pop cx pop bx pop ax ret HTEXT ENDP ; Hercules mode set - called from HTEXT and HGRAF SETMD PROC NEAR push dx push ax mov dx,config ; configuration port mov al,genable ; allow graphics mode to be set out dx,al pop ax push ax push cx ; save count mov dx,cntrl ; control port out dx,al ; set to text or graphics mov dx,index ; send 12 bytes from table to 6845 mov cx,12 ; number of registers to load xor ah,ah ; start with register 0 of 6845 cld setmd1: jmp $+2 ; small pause for hardware mov al,ah ; ah is counter out dx,al ; set register inc dx ; point to data port lodsb ; get next byte in table jmp $+2 ; small pause for hardware out dx,al ; and send to 6845 inc ah ; next register dec dx ; point to register port loop setmd1 ; and continue 'til cx=0 pop cx ; recover count cld push di push es mov ax,segscn ; start of screen mov es,ax xor di,di mov ax,bx ; get blanking character rep stosw ; store blanking char in whole screen pop es pop di mov dx,cntrl ; now to re-enable screen pop ax ; get mode or al,scrn_on ; enable screen out dx,al pop dx ret SETMD ENDP teksave proc near ; saves graphics screen from page 0 to page 1 push si push di cmp gpage,0 ; only graphics page 0 on display board? je teksavx ; e = yes, no saving possible here mov si,segscn ; segment (!) of current screen cmp graph_mode,ega je teksav1 cmp graph_mode,monoega je teksav1 cmp graph_mode,colorega je teksav1 cmp graph_mode,hercules je teksav2 jmp short teksavx ; else nothing teksav1:mov di,segega+800h ; EGA page 1 screen segment call egasr ; call common save/restore code jmp short teksavx teksav2:mov di,seghga+800h ; Hercules page 1 screen segment call hgasr ; call common save/restore code teksavx:pop di pop si ret teksave endp tekrest proc near ; saves graphics screen of page 0 in page 1 push si push di cmp gpage,0 ; only graphics page 0 on display board? jne tekres0 ; ne = no, more so work to do here call tekcls1 ; else clear the screen to color it jmp short tekresx ; and exit tekres0:mov di,segscn ; segment (!) of new graphics screen cmp graph_mode,ega je tekres1 cmp graph_mode,monoega je tekres1 cmp graph_mode,colorega je tekres1 cmp graph_mode,hercules je tekres2 jmp short tekresx ; else nothing tekres1:mov si,segega+800h ; segment of EGA page 1 call egasr ; call common save/restore code jmp short tekresx tekres2:mov si,seghga+800h ; segment of Hercules page 1 call hgasr ; call common save/restore code tekresx:pop di pop si ret tekrest endp egasr proc near ; common code for Tek ega save/restore ops push ax push cx push dx mov ax,0f00h ; enable 4 plane set/resets call ega_gc ; set controller mov ax,0f01h ; enable Set/Reset register call ega_gc mov ax,0f02h ; set color compare register for 4 planes call ega_gc mov ax,0905h ; set mode reg: write latches, read mode call ega_gc mov ax,0ff02h ; enable all planes call ega_md mov cx,ybot ; last scan line inc cx ; number of scan lines mov ax,80 ; bytes per scan line mul cx mov cx,ax push es ; save es push ds ; save ds mov es,di ; destination, set es to video memory mov ds,si ; source, set ds to video memory xor si,si ; clear offset fields xor di,di cld rep movsb ; copy from page [si] to page [di] pop ds ; recover ds pop es ; and other registers mov ax,0000h ; disable 4 plane set/resets call ega_gc ; set controller mov ax,0001h ; disable Set/Reset register call ega_gc ; set controller mov ax,0002h ; disable color compare register call ega_gc mov ax,1005h ; set mode reg: write latches, odd/even call ega_gc pop dx pop cx pop ax ret egasr endp hgasr proc near ; Hercules save restore screen push cx mov cx,4000h ; number of words to move push es ; save es push ds ; save ds mov es,di ; destination, set es to video memory mov ds,si ; source, set ds to video memory xor si,si ; clear offset fields xor di,di cld rep movsw ; copy from page [si] to page [di] pop ds ; recover ds pop es ; and other registers pop cx ret hgasr endp code ends end