REVLVL equ 5 ;Revision level 6-25-85 ;============================================================================= ; ; MSYTIPRO.ASM This file contains system dependent terminal emulation routines ; for the H19 and Tektronix 4010 terminals. ; ; NOTE: ESC Z and ANSI mode don't work. ; ; Credits: Dan Smith Computing Center (303) 273-3396 ; Colorado School of Mines ; Golden, Colorado 80241 ; Joe Smith, now at TYMSHARE, 39100 Liberty St, Fremont CA 94538 ; ; ; The following H19 escape codes are supported: ; ; Esc H Cursor home Esc L Insert line ; Esc C Cursor forward Esc M Delete line ; Esc D Cursor backward Esc N Delete character ; Esc B Cursor down Esc O Exit insert mode ; Esc A Cursor up Esc @ Enter insert mode ; Esc I Reverse index Esc p Enter reverse video mode ; Esc Y Direct cursor addressing Esc q Exit reverse video mode ; Esc E Clear display Esc j Save cursor position ; Esc J Erase to end of page Esc k Restore cursor position ; Esc K Erase to end of line ; Esc x4 Set block cursor Esc Z Identify as VT52 ; Esc y4 Set underscore cursor ; ; The following H19 codes are not supported: ; ; Esc n Cursor position report Esc < Enter ANSI mode ; Esc b Erase beginning of display Esc [ Enter hold screen mode ; Esc l Erase entire line Esc \ Exit hold screen mode ; Esc o Erase beginning of line Esc F Enter graphics mode ; Esc z Reset to power up config. Esc G Exit graphics mode ; Esc r ? Modify baud rate Esc t Enter keypad shifted mode ; Esc x 1-3 Set modes 1 through 3 Esc u Exit keypad shifted mode ; Esc x 5-9 Set modes 5 through 9 Esc = Enter alt keypad mode ; Esc y 1-3 Reset modes 1 through 3 Esc > Exit alt keypad mode ; Esc y 5-9 Reset modes 5 through 9 Esc } Keyboard disable ; Esc v Wrap around at end of line Esc { Keyboard enable ; Esc w Discard at end of line Esc ] Transmit 25th line ; Esc Z Identify as H-19 Esc # transmit page ; ;============================================================================= include mssdef.h datas segment public 'datas' extrn flags:byte tekflag db 0 ;Flag for ESCape sequences 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 tek_lox db 0 tek_lsb db 0 ; Low-order 2 bits of X + low Y (4014 mode) arrtab db 48h,'A' ;Up arrow db 50h,'B' ;Down arrow db 4bh,'D' ;Left arrow db 4dh,'C' ;Right arrow arrtabl equ ($-arrtab) / 2 ;Number of keys in arrtab spctab db 27,13,10,08,09,07,29,12 lspctab equ $-spctab spcjmp dw outesc,outcr,outlf,outbs,outtab,beep,tekini,ffeed esctab db 'YABCDEHIJKLMNO@pqjkxy' ;Recognized escape codes db 'Z',12,1ah lesctab equ $-esctab escjmp dw movcur,curup,curdwn,currt ;Escape code routines. This dw outbs,clrscr,curhom,revind ;array must parallel the codes dw clreow,clreol,inslin,dellin ;listed above. dw delchr,noins,entins,invvid dw nrmvid,savecur,restcur,setm,resetm dw sendid,escff,xhair argadr dw 0 escchar db 0 videobuf dw 0de00h ttstate dw 0 wcoord db 0 savrow db 0 insmod db 0 cursor dw 0 oldcur dw 0 xmult dw 9 ;Scale TEK to TI by 9/13 xdiv dw 13 ;so that 0-1023 converts to 0-708 ymult dw 5 ;Scale TEK to TI by 5/13 ydiv dw 13 ;so that 0-779 converts to 299-0 ybot dw 299 ;Bottom of screen is Y=299 oldx dw 0 ;Previous scaled coordinates oldy dw 0 grseg dw 0 datas ends code segment public assume cs:code,ds:datas extrn beep:near, prtchr:near, outchr:near public term ;============================================================================= ; Main entry point for Tektronix 4010 - Heathkit H19 terminal emulation. ;============================================================================= db 'term' term proc near mov argadr,ax ;Save address of argument block call termini term10: call inport ;Input from modem jnc term20 ;No input available; Check keyboard call outtty ;Print on terminal term20: mov ah,1 ;See if a character has been typed int 4ah ; on keyboard jz term10 ;Jump if not xor ah,ah ;Read char from keyboard buffer int 4ah cmp al,escchar ;See if the Esc character (^]) jz term30 ;Jump if it is call outport ;Send character out comm port jmp short term20 ;Make sure KB buffer doesnt overrun term30: call termend ret term endp ;============================================================================= ; TERMINI Subroutine to initialize the terminal before starting emulation ;============================================================================= termini proc near mov bx,argadr ;Save escape char in local storage mov al,[bx].escc mov escchar,al mov grseg,0d000h ;Assume green on a 3 plane system int 4fh ;Get system configuration test ax,4000h ;See if graphics plane 3 exists jnz ti10 ;Jump if it does mov grseg,0c000h ;Reset to plane 1 for a 1 plane system ti10: mov ttstate,offset nstate mov insmod,0 ;Turn off insert mode mov ah,13h ;Necessary to clear screen in order to int 49h ; get CRTC start address in sync with mov word ptr cursor,0 ; cursor position for direct video ret ; buffer access. termini endp ;============================================================================= ; TERMEND Subroutine to clean up after terminal emulation. ;============================================================================= termend proc near ;*; mov ah,13h ;Clear text screen ;*; int 49h ;*; mov ah,14h ;Clear graphics screen ;*; int 49h ret termend endp ;============================================================================= ; Routine to input a character from the modem port. If no character available ; this returns with the carry flag cleared. (NC) ;============================================================================= inport proc near ;Input from the modem call prtchr jmp short ip10 ;Character available nop ;Need 3 bytes clc ;Indicate no character ret ip10: and al,7fh ;No parity here for terminal emulation stc ;Indicate character available ret inport endp ;============================================================================= ; Subroutine to translate and send the character out the communication port ;============================================================================= outport proc near cmp flags.vtflg,1 jne op2 ;Jump if no Heath-19 emulation or al,al jz op5 ;Jump if a special key op2: mov ah,al jmp short op30 op5: mov cx,arrtabl ;Number of entries in translation table mov si,offset arrtab ;Point to start of translation table op10: cmp ah,[si] jz op20 ;Jump if found key add si,2 ;Point to next key scan code loop op10 ret ;Scan code not found; don't send it op20: mov ah,27 call outchr ;Send a leading escape char nop ;Waste 3 bytes to ignore error nop nop mov ah,[si+1] ;Get translated code value op30: call outchr ;Output character in AH nop ;Waste 3 bytes to ignore error nop nop ret outport endp ;============================================================================= ; Subroutine to send the character in AL to the screen. If Heath-19 emulation ; is on, the character will be interpreted according to H-19 and Tektronix 4010 ; escape codes. ;============================================================================= outtty proc near cmp flags.vtflg,1 jne otty10 ;Jump if no Heath-19 emulation mov dx,cursor ;These may need cursor... cld ;Set here so its not required later jmp ttstate ;Jump according to current state otty10: mov dl,al ;Print char in al at cursor position mov ah,2 ; using DOS int 21h ret outtty endp ;============================================================================= ; Subroutine to process the character in AL according to the normal state ;============================================================================= nstate proc near cmp al,32 ;Special character? jb conchar ;Yes, perform control char operation cmp insmod,0 ;In insert mode? je ns10 ;No, output normal push ax ;Save character call inschr ;Insert a blank in line pop ax ;Restore character ns10: jmp pchar ;Print char in AL nstate endp ;============================================================================= ; Subroutine to handle the ASCII character below 32 in al ;============================================================================= conchar proc near mov di,offset spctab ;See if character is in table mov cx,lspctab repne scasb jz cc10 ;Go process if it was push ax ;Save char mov al,'^' call pchar ;Print caret pop ax add al,'A'-1 ;Make control character printable jmp pchar ;Print, then return cc10: sub di,offset spctab+1 ;Get index of char shl di,1 ;Double for word offset jmp spcjmp[di] ;And go handle conchar endp ;============================================================================= ; special char routines. cursor is in dx, char in al ;============================================================================= outlf proc near inc dl ;Bump row jmp setcur outlf endp outcr proc near xor dh,dh ;Set col to 0 jmp setcur outcr endp outbs proc near or dh,dh jle setcur ;Col 0, can't back up dec dh ;Back up col jmp setcur ;And use if reasonable outbs endp outtab proc near add dh,8 ;Tab is at most 8 columns and dh,not 111b ;Round down to a multiple of 8 cmp dh,80 ;Out of range? jb outta1 ;No, go set it mov dh,80-1 ;Else just move to right margin outta1: jmp setcur outtab endp outesc proc near mov ttstate,offset estate ;Expect escape sequence. ret outesc endp ;============================================================================= ; Escape-char handling routines ;============================================================================= estate proc near mov ttstate,offset nstate ;Put state back to normal mov di,offset esctab ;Escape char tbl mov cx,lesctab ;Length of tbl repne scasb ;Look for it in tbl jz es10 ;Found, go use it push ax mov al,27 ;Output Esc character call pchar pop ax ;Output unrecognized escape code jmp pchar es10: sub di,offset esctab+1 ;Get offset into tbl shl di,1 ;Convert to word offset jmp escjmp[di] ;And go dispatch on it estate endp ;============================================================================= ; Subroutine to print a character at the current cursor position and advance ; the cursor to the next position. ;============================================================================= pchar proc near push es ;Save ES push ax ;Save char to print mov dx,cursor ;Get row and column call scrloc ;Map DX to ES:DI pop ax ;Restore char to print stosb ;Put into video buffer pop es ;Restore segment inc dh ;Bump col jmp setcur ;Position cursor pchar endp ;============================================================================= ; Subroutine to position the cursor. This routine will wrap lines and scroll ; the screen. The row is in DL, the column is in DH ;============================================================================= setcur proc near cmp dh,80 ;See if in range jae sc20 cmp dl,24 ;Lines go from 0 to 23 jbe sc10 ;Not off end, keep going push dx ;Save row/col xor dx,dx call dellin ;Scroll up one line by deleting top line pop dx mov dl,24 ;Go to bottom line again... sc10: mov cursor,dx ;Save cursor pos mov ah,2 int 49h ;Set cursor sc20: ret setcur endp ;============================================================================= ; Subroutine to move the cursor up and possibly scroll the screen down ;============================================================================= revind proc near cmp dl,0 jle rev10 dec dl ;back up a row jmp setcur ;and go set cursor rev10: xor dx,dx jmp inslin ;Insert a line at top of screen revind endp ;============================================================================= ; Subroutine to move the cursor up ;============================================================================= curup proc near cmp dl,0 ;w/in range? jle curu10 ;no, skip this dec dl ;else back up curu10: jmp setcur ;and go set position curup endp ;============================================================================= ; Subroutine to move the cursor down ;============================================================================= curdwn proc near inc dl jmp setcur ;increment row (setcur can scroll!) curdwn endp ;============================================================================= ; Subroutine to move the cursor 1 position to the right. ;============================================================================= currt proc near inc dh jmp setcur currt endp ;============================================================================= ; Subroutine to home cursor and clear screen ;============================================================================= clrscr proc near call curhom ;go home cursor mov dx,cursor jmp clreow ;then clear to end of window clrscr endp ;============================================================================= ; Subroutine to home the cursor ;============================================================================= curhom proc near xor dx,dx ;move to 0,0 jmp setcur curhom endp ;============================================================================= ; Subroutine to clear the screen from the cursor to the end of the window ;============================================================================= clreow proc near push es call scrloc ;Map DX into ES:DI in the video buffer mov cx,80*25 ;Number of chars on screen sub cx,di ;Number from the cursor on mov al,' ' ;Fill with blanks rep stosb ;Fill screen pop es ret clreow endp ;============================================================================= ; Subroutine to clear the screen from the cursor to the end of the line ;============================================================================= clreol proc near mov cx,80 ;Number of cols across screen sub cl,dh ;Number from cursor on jle eol10 ;Jump if past end push es call scrloc ;Map DX to ES:DI mov al,' ' ;Fill end with blanks rep stosb ;Blank end of line pop es eol10: ret clreol endp ;============================================================================= ; Subroutine to insert a line at the row that the cursor is in. ;============================================================================= inslin proc near xor dh,dh ;Move to start of row cmp dl,24 jae clreol ;Just clear bottom row push ds push es call scrloc ;Map DX to ES:DI mov ds,videobuf ;Set DS to video buffer mov cx,24*80 ;Number of chars on screen sub cx,di ;Number of chars past current row push di ;Save current row address mov di,25*80-1 ;Point to last char mov si,24*80-1 ;Point 1 line up std ;Auto decrement rep movsb ;Move lines down cld ;Auto increment mov cx,80 ;Number of chars on original line pop di ;Restore pointer to start of line mov al,' ' ;Fill with blanks rep stosb ;Blank line pop es pop ds ret inslin endp ;============================================================================= ; Subroutine to scroll the screen up over the current line ;============================================================================= dellin proc near xor dh,dh ;Move to start of row cmp dl,24 jae clreol ;Just clear bottom row push ds push es call scrloc ;Map DX to ES:DI mov ds,videobuf ;Set DS to video buffer mov cx,24*80 ;First char of last row sub cx,di ;Number of chars past current row mov si,di add si,80 ;Source is one line down rep movsb ;Move chars up mov cx,80 ;Number of chars on last line mov al,' ' ;Fill with blanks rep stosb ;Blank line pop es pop ds ret dellin endp ;============================================================================= ; Subroutine to delete the current character by scrolling to the left ;============================================================================= delchr proc near push ds push es call scrloc ;Map dx to es:di mov ds,videobuf mov cx,79 ;Last char on line sub cl,dh jz dch20 ;Jump if on last char mov si,di inc si ;Source is 1 char to right rep movsb ;Move chars to left dch20: mov byte ptr [di],' ' pop es pop ds ret delchr endp ;============================================================================= ; Subroutine to insert a character at the cursor position ;============================================================================= inschr proc near push ds push es mov cx,79 ;This is last col to move, +1 for length sub cl,dh ;Compute distance to end jle ichr20 ;Nothing to move... mov dh,78 ;This is address of last col to move call scrloc ;Compute pos mov ds,videobuf mov si,di inc di ;Destination is one byte over... std ;Remember to move us backwards rep movsb ;Move chars to right cld ichr20: pop es pop ds ret inschr endp ;============================================================================= ; Subroutine to turn off insert mode. ;============================================================================= noins proc near mov insmod,0 ;Turn off insert mode ret noins endp ;============================================================================= ; Subroutine to process ESC Y (The direct cursor addressing command) ;============================================================================= movcur proc near mov wcoord,0 ;Want two coordinates... mov ttstate,offset cstate ret movcur endp ;============================================================================= ; Subroutine to get a coordinate ;============================================================================= cstate proc near sub al,32 ;Coordinates offset by 32 cmp wcoord,0 ;See if first coord already received jnz cs10 ;Jump if it was inc wcoord ;Indicate first was received mov savrow,al ;Save first coordinate (row) ret cs10: mov ttstate,offset nstate ;Reset state mov dh,al ;Put column in DH mov dl,savrow ;Get saved row jmp setcur ;Position cursor cstate endp ;============================================================================= ; Subroutine to enter insert mode. ;============================================================================= entins proc near mov insmod,0ffh ;enter insert mode... ret ;and return entins endp ;============================================================================= ; Subroutine to enter inverse video mode ;============================================================================= invvid proc near ret invvid endp ;============================================================================= ; Subroutine to exit inverse video mode ;============================================================================= nrmvid proc near ret nrmvid endp ;============================================================================= ; Subroutine to handle the set mode command. Sequence = ESC x (1,2,3,4,5...) ;============================================================================= setm proc near ;Here if ESC x entered mov ttstate,offset mstate ;Wait for value ret mstate: mov ttstate,offset nstate ;Put state back to normal cmp al,'4' jz uscurs ;Set underscore cursor push ax mov al,27 ;Output Esc character call pchar mov al,'x' ;Output set mode character call pchar pop ax ;Output unrecognized mode code jmp pchar setm endp ;============================================================================= ; Subroutine to handle the reset mode command. Sequence = ESC y (1,2,3,4,5...) ;============================================================================= resetm proc near ;Here if ESC y entered mov ttstate,offset rstate ;Wait for value ret rstate: mov ttstate,offset nstate ;Put state back to normal cmp al,'4' jz blcurs ;Set block cursor push ax mov al,27 ;Output Esc character call pchar mov al,'x' ;Output set mode character call pchar pop ax ;Output unrecognized mode code jmp pchar resetm endp ;============================================================================= ; Subroutine to set the underscore cursor ;============================================================================= uscurs proc near mov cx,4a0bh mov ah,1 int 49h ret uscurs endp ;============================================================================= ; Subroutine to set a block cursor ;============================================================================= blcurs proc near mov cx,400bh mov ah,1 int 49h ret blcurs endp ;============================================================================= ; save cursor in DX ;============================================================================= savecur proc near mov oldcur,dx ret savecur endp ;============================================================================= ; restore cursor onto screen ;============================================================================= restcur proc near mov dx,oldcur jmp setcur restcur endp ;============================================================================= ; Computes screen location to es:di, given col and row in dx. ; Trashes ax,bx ;============================================================================= scrloc proc near mov al,dl ;Get row xor ah,ah shl ax,1 ;Row * 2 mov bx,ax shl ax,1 ;Row * 4 shl ax,1 ;Row * 8 add ax,bx ;Row * 10 shl ax,1 ;Row * 20 shl ax,1 ;Row * 40 shl ax,1 ;Row * 80 add al,dh adc ah,0 mov di,ax mov es,videobuf ret scrloc endp ;============================================================================= ; ; 12-Dec-84 Joe Smith, CSM Computing Center, Golden CO 80401 ; ; Description of Tektronix commands ; ; ESCAPE-CONTROL-E (ENQ) requests a status report ; ESCAPE-FORMFEED erases the screen. ; ESCAPE-CONTROL-Z turns on the crosshairs (not on 4006 or 4025) ; ESCAPE-A-E enables the interactive plotter ; ESCAPE-A-F turns off the interactive plotter ; ESCAPE-M-L-2 Selects color 2 for drawing lines on 4113 ; ESCAPE-M-T-: Selects color 10 for drawing text on 4113 ; CONTROL-] (GS) turns on plot mode, the first move will be with beam off. ; CONTROL-UNDERLINE (US) turns off plot mode. (CR also works for all but 4025.) ; CONTROL-X switches HDSGVT from TEKTRONIX mode to NORMAL alpha mode. ; ; 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, ; altho 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 w/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: 40 140 140 40 100 ; ; Note that LO-Y must be sent if HI-X has changed so the TEKTRONIX knows that ; the HI-X byte (in the range of 40-77 octal) 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 140 + MARGIN*20 + LSBY*4 + LSBX. (MARGIN=0) ; ;============================================================================ ;============================================================================ ; Subroutine to initialize tektronix emulation. Called when GS char received ;============================================================================ tekini proc near mov visible,0 ;Next move is invisible mov tekflag,1 mov ttstate,offset xystate ;Go to ystate next ret tekini endp ;============================================================================ ; Subroutine to clear the graphics screen. Called when a Form feed is received ;============================================================================ ffeed proc near mov ah,14h ;Clear only graphics (not text) int 49h ret ffeed endp ;============================================================================ ; Subroutine to clear the graphics and the text screen. Called if Esc FF rec. ;============================================================================ escff proc near mov ah,13h ;Erase both text and graphics screen int 49h mov ah,14h int 49h mov ttstate,offset nstate ret escff endp ;============================================================================= ; Subroutine to send an identification code back. (Esc Z) ;============================================================================= sendid proc near mov al,esc call outport mov al,'\' call outport mov al,'K' call outport mov ttstate,offset nstate ret sendid endp ;============================================================================= ; Subroutine to turn on the crosshairs. (Esc ^Z) ;============================================================================= xhair proc near mov ttstate,offset nstate ret xhair endp ;============================================================================= ; Subroutine to extract the X,Y coordinates for Tektronix emulation. ; Expecting HIY because LOX was seen tekflag = 1 ; Expecting HIX because LOY was seen tekflag = 0 ; Written by Joe Smith, CSM ;============================================================================= xystate proc near cmp al,29 ;Process Pen up command jz tekini cmp al,13 ;Exit graphics mode on CR,LF,US je go2text cmp al,10 je go2text cmp al,1fh je go2text cmp al,18h je go2text cmp al,20h ;Control char? jl tek20 ;Ignore it cmp al,40h jl tek30 ;20-3F are HIX or HIY cmp al,60h ;40-5F are LOX (causes beam movement) jl tek50 ;60-7F are LOY ;Extract low-order 5 bits of Y coordinate, set ESCFLAG=6 mov ah,tek_loy ;Copy previous LOY to MSB (in case 4014) mov tek_lsb,ah and al,1Fh ;LOY is 5 bits mov tek_loy,al cmp tekflag,0 ;2nd LOY in a row? je tek20 ;Yes, then LSB is valid mov tek_lsb,0 ;1st one, clear LSB mov tekflag,0 ;LOY seen, expect HIX (instead of HIY) tek20: ret ;Extract high-order 5 bits (X or Y, depending on ESCFLAG) tek30: and ax,1Fh ;Just 5 bits mov cl,5 shl ax,cl ;Shift over 5 bits cmp tekflag,1 ;Looking for HIY? jne tek40 ;No, HIX mov tek_hiy,ax ;Yes, this byte has HIY ret ;Keep ESCFLAG=4 tek40: mov tek_hix,ax ;This byte has HIX (because ESCFLAG=6) mov tekflag,1 ;Reset to look for HIY next time ret ;Extract low-order X, do beam movement tek50: and al,1Fh ;Just 5 bits mov tek_lox,al mov ax,tek_hix ;Combine HIX*32 or al,tek_lox ;with LOX mov bx,tek_hiy ;Same for Y or bl,tek_loy mov cl,visible ;0=move, 1=draw call tekdraw go2visi:mov visible,1 ;Next movement is with a visible trace mov tekflag,1 ;Reset to look for HIY next time ret go2text:mov ttstate,offset nstate ret xystate 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. ; Visiblity flag in CL, 0=move invisible, 1=draw a line. ; ; The TI-PRO has (719,299) as the coordinate of the lower-right corner. ; Calculate endpoint X=(9/13)*(HIX*32+LOX), Y=299-(5/13)*(HIY*32+LOY) ; ; The IBM-PC has (639,199) as the coordinate of the lower-right corner. ; Calculate endpoint X=(12/20)*(HIX*32+LOX), Y=199-(5/20)*(HIY*32+LOY) ; ;============================================================================= tekdraw proc near imul xmult ;Multiply by 9 idiv xdiv ;Divide by 13 push ax ;X is now between 0 and 708 mov ax,bx imul ymult ;Multiply by 5 idiv ydiv ;Divide by 13 mov bx,ybot ;Y is now between 0 and 299 sub bx,ax ;Put new Y in right reg pop ax ;Put new X in right reg or cl,cl jnz td10 ;Jump if line is visible mov oldx,ax ;Update last coordinates mov oldy,bx ret td10: mov si,oldx ;Previous position mov di,oldy mov oldx,ax ;Update position mov oldy,bx jmp line ;Plot line tekdraw endp ;============================================================================= ; LINE Subroutine to plot line with endpoints in BX,CX and SI,DI. The method ; used is an adaptation of octantal dynamic differential analyzer(DDA). ; SI,DI = Start X,Y coordinates. AX,BX = End X,Y coordinates. ; ;============================================================================= line proc near cmp ax,si ;Compare X1 to X2 jl plusx ;Jump if X1 is to left of X2 xchg ax,si ;Swap points so point 1 is to left xchg bx,di ; This mirrors quadrants 2,3 to 1,4 plusx: sub si,ax ;Get delta X into SI sub di,bx ;Get delta Y into DI ; Left-hand coordinate in (AX,BX), delta movement in (SI,DI) ; Map X1,Y1 in AX,BX to offset into the video buffer in BX and bit pos in AX shl bx,1 ;2*Y shl bx,1 ;4*Y mov bp,bx ;Save 4*Y shl bx,1 ;8*Y shl bx,1 ;16*Y shl bx,1 ;32*Y add bp,bx ;DX = 36*Y shl bx,1 ;64*Y shl bx,1 ;128*Y sub bx,bp ;128Y - 36Y = 92*Y mov cl,al ;Low 4 bits of X position and cl,0Fh shr ax,1 ;Divide by 8 bits per byte shr ax,1 shr ax,1 and ax,0fffeh ;Truncate down to word boundary add bx,ax mov ax,8000h ;Start with set bit on left edge shr ax,cl ;Shift it over the correct amount ;AX has bit in position, BX has word address, SI has delta-X, DI has delta-Y mov bp,92 ;Offset from 1 pixel to one below it or di,di ;See if delta y is below zero jg line10 ;Yes, already on quadrant 3 neg di ;Get absolute value of delta y neg bp ;Move toward top of screen line10: push ds mov ds,grseg cmp di,si ;Compare delta-Y with delta-X jg line30 ;Greater than +/- 45 degrees ; Here when slope is less than +/- 45 degrees line20: mov cx,si ;Number of pixels to plot = delta x inc cx ; + 1 mov dx,si ;Initialize line error to -(deltax)/2 shr dx,1 ; neg dx ; line2a: or [bx],ax ;Turn on pixel pointed to by BX and Al ror ax,1 ;Increment X direction jnc line2b ; add bx,2 ; line2b: add dx,di ;Add delta y to line error jl line2c ;Jump for next pixel if error < 0 add bx,bp ;Go up (or down) one pixel sub dx,si ;Subtract delta x from line error line2c: loop line2a ;Set next pixel pop ds ret ; Here when slope is greater than +/- 45 degrees line30: mov cx,di ;Number of pixels to plot = delta y inc cx ; + 1 (Delta Y was negated above) mov dx,di ;Initialize line error to -(deltay)/2 shr dx,1 ; neg dx ; line3a: or [bx],ax ;Turn on pixel pointed to by BX and Al add bx,bp ;Move up (or down) 1 pixel add dx,si ;Add delta x to line error jl line3c ;Jump for next pixel if error < 0 ror ax,1 ;Time to increment X direction jnc line3b ; add bx,2 ; line3b: sub dx,di ;Subtract delta y from line error line3c: loop line3a ;Set next pixel pop ds ret line endp code ends end