name msxapr ; File MSXAPR.ASM ; Last modification: 23 April 1986 ; Kermit system dependent module for ACT Apricot ; Added global entry point vtstat for use by Status in mssset. ; Added register save/restore in getbaud procedure. ; Also trimmed off trailing commas in publics. Joe R. Doupnik 12 March 1986 ; Add global procedures ihosts and ihostr to handle host initialization ; when packets are to be sent or received by us,resp. 24 March 1986 ; Add global procedure dtrlow (without worker serhng) to force DTR and RTS low ; in support of Kermit command Hangup. Says Not Yet Implemented. [jrd] ; Add global procedure Dumpscr, called by Ter in file msster, to dump screen ; to a file. Just does a beep for now. 13 April 1986 [jrd] ; Move Hangup message out from middle of Show Key area (my goof). ; 23 April 1986 [jrd] public serini, serrst, clrbuf, outchr, coms, vts, vtstat, dodel public ctlu, cmblnk, locate, lclini, prtchr, dobaud, clearl public dodisk, getbaud, beep public count, xofsnt, puthlp, putmod, clrmod, poscur public sendbr, term, machnam, setktab, setkhlp, showkey public ihosts, ihostr, dtrlow, dumpscr ; [jrd] include mssdef.h false equ 0 true equ 1 instat equ 6 rddev equ 3FH open equ 3DH control equ 0FCH ; System Control Device ; external variables used: ; drives - # of disk drives on system ; flags - global flags as per flginfo structure defined in pcdefs ; trans - global transmission parameters, trinfo struct defined in pcdefs ; portval - pointer to current portinfo structure (currently either port1 ; or port2) ; port1, port2 - portinfo structures for the corresponding ports ; global variables defined in this module: ; xofsnt, xofrcv - tell whether we saw or sent an xoff. modfrm struc ; Format of mode line db 'Esc chr: ' m_echr db 2 dup (?) db ', Speed: ' m_baud db 4 dup (?) db ', Parity: ' m_par db 4 dup (?) db ', Echo: ' m_echo db 3 dup (?) db ', Log: ' m_log db 3 dup (?) db ', Type ' m_hlp db 2 dup (?) db '? for Help$' modfrm ends datas segment public 'datas' extrn drives:byte, flags:byte, trans:byte extrn portval:word, port1:byte, port2:byte, dmpname:byte ; [jrd] ; machnam db 'ACT Apricot$' erms20 db cr,lf,'?Warning: System has no disk drives$' erms40 db cr,lf,'?Warning: Unrecognized baud rate$' erms41 db cr,lf,'?Warning: Cannot open com port$' erms50 db cr,lf,'Error reading from device$' badbd db cr,lf,'Unimplemented baud rate$' noimp db cr,lf,'Command not implemented.$' shkmsg db 'Not implemented.' shkmln equ $-shkmsg setktab db 0 setkhlp db 0 hngmsg db cr,lf,' The phone should have hungup.',cr,lf,'$' ; [jrd] hnghlp db cr,lf,' The modem control lines DTR and RTS for the current' db ' port are forced low (off)' db cr,lf,' to hangup the phone. Normally, Kermit leaves them' db ' high (on) when it exits.' db cr,lf,'$' ; [jrd] rdbuf db 80 dup (?) ; temp buf [jrd] crlf db cr,lf,'$' delstr db BS,BS,' ',BS,'$' ; Delete string. clrlin db cr,esc,'K$' ; Clear line. clreol db esc,'K$' ; Clear line. clrscr db esc,'H',esc,'J$' ; Home and clear screen. ; Use high/low intensity rather than inverse video. ; It is kinder on the eyes.... invseq db esc,'($' ; High intensity mode. nrmseq db esc,')$' ; Low intensity mode. on25 db esc,'j',esc,';$' ; Save cursor posn, move to line 25 off25 db esc,'k$' ; Restore cursor to saved position offmscr db esc,'/',0,esc,'s$' ; Turn off lights, clear, clock on onmscr db esc,'U',esc,'W' ; Direct output to microscreen db esc,'c',esc,'B' ; Disable scrolling, cursor down db 'Break Close Status ' db 'Push Help Log' db esc,'V' ; Revert to normal screen db esc,'/',3FH ; Turn on all keypad lights db '$' xofsnt db 0 ; Say if we sent an XOFF. count dw 0 ; Number of chars in int buffer. portin db 0 ; Port initialization flag inited db 0 ; Terminal handler init flag tmp db ?,'$' temp dw 0 temp1 dw ? ; Temporary storage. temp2 dw ? ; Temporary storage. ; This character string is used to program various keys to return ; the correct ASCII characters. kbdesc db esc,'43',44,'['-100O ; Program CTRL-[ key db esc,'43',45,']'-100O ; Program CTRL-] key db '$' ; This table is indexed by the baud rate definitions given in msdefs.h. ; Unsupported baud rates should contain FF. bddat label word dw 0FFH ; 45.5 Unsupported dw 1 ; 50 dw 2 ; 75 dw 3 ; 110 dw 4 ; 134.5 dw 5 ; 150 dw 6 ; 300 dw 7 ; 600 dw 8 ; 1200 dw 9 ; 1800 dw 0FFH ; 2000 Unsupported dw 10 ; 2400 dw 12 ; 4800 (Have to skip 3600) dw 14 ; 9600 (Have to skip 7200) dw 15 ; 19200 dw 0FFH ; 38400 Unsupported ourarg termarg <> modbuf modfrm <> ; Mode line buffer ; Some static data for the mode line. unkbaud db 'Unk ' baudn db '45.5' db ' 50' db ' 75' db ' 110' db ' 135' db ' 150' db ' 300' db ' 600' db '1200' db '1800' db '2000' db '2400' db '4800' db '9600' db ' 19K' db ' 38K' parnams db 'Even' db 'Mark' db 'None' db 'Odd ' db 'Spc ' offmsg db 'Off' onmsg db 'On ' lclmsg db 'Lcl' remmsg db 'Rem' keyoff dw 0 keyseg dw 0 ; datas ends keybd segment page public ; This keytable needs to aligned on a page boundary, else ; the whole machine fall apart. ; keytab dw 0400H dup (?) ; m1 db 2,0,defesc,'B' ; break m2 db 2,0,defesc,'C' ; close m3 db 2,0,defesc,'S' ; status m4 db 2,0,defesc,'P' ; push m5 db 2,0,defesc,'?' ; help m6 db 2,0,defesc,'R' ; resume logging ; mktab dw m1,m2,m3,m4,m5,m6 ; keybd ends code segment public 'code' extrn comnd:near, dopar:near, prserr:near, atoi:near, prompt:near extrn sleep:near ; [jrd] assume cs:code,ds:datas ; Produce a short beep. The PC DOS bell is long enough to cause a loss ; of data at the port. Returns normally. BEEP PROC NEAR mov dl,bell mov ah,dconio int dos ret BEEP ENDP ; Clear to the end of the current line. Returns normally. CLEARL PROC NEAR mov dx,offset clreol jmp tmsg ; Send terminal message CLEARL ENDP ; Clear the input buffer. This throws away all the characters in the ; serial interrupt buffer. This is particularly important when ; talking to servers, since NAKs can accumulate in the buffer. ; Returns normally. CLRBUF PROC NEAR push bx ; save regs. [jrd] push cx mov bx,34H ; Serial Device Driver mov cx,2 ; Read serial port clrbf1: int control ; Call System Control Device cmp ax,-1 ; Read anything ? jne clrbf1 ; Yes, try again pop cx ; [jrd] pop bx ret CLRBUF ENDP ; clear the mode line written by putmod. Returns normally. CLRMOD PROC NEAR mov dx,offset on25 ; Move to line 25 call tmsg call clearl ; Clear to end of line. mov dx,offset off25 ; Restore cursor position call tmsg ret CLRMOD ENDP ; This routine blanks the screen. Returns normally. CMBLNK PROC NEAR mov dx,offset clrscr jmp tmsg ; Send terminal message. CMBLNK ENDP ; Set the current port. COMS PROC NEAR jmp notimp COMS ENDP ; Make a copy of the keyboard table so that we can redefine some keys ; when we go into CONNECT state. CPYKTAB PROC NEAR push ds mov ax,0 mov es,ax ; ES -> lowest page in memory mov ax,es:[0712H] mov keyoff,ax ; Save offset to keytable mov si,ax ; For the copy mov ax,es:[0714H] mov keyseg,ax ; Save segment of keytable ; mov ds,ax ; DS:SI -> system keyboard table mov ax,keybd mov es,ax mov di,0 ; ES:DI -> our keyboard table ; mov cx,0400H ; Length of table cld rep movsb ; Copy table ; mov ax,keybd mov ds,ax ; Point to our keyboard segment ; mov si,offset mktab mov di,offset keytab+16 ; First microscreen key def mov cx,12 cld rep movsb ; copy pointers pop ds ; restore DS ret CPYKTAB ENDP ; Move the cursor to the left margin, then clear to end of line. ; Returns normally. CTLU PROC NEAR mov dx,offset clrlin jmp tmsg CTLU ENDP ; Set the baud rate for the current port, based on the value ; in the portinfo structure. Returns normally. DOBAUD PROC NEAR push ax ; save regs. [jrd] push bx push cx push bp mov bp,portval mov temp1,ax ; Save new rate, don't zap old rate yet mov ax,ds:[bp].baud ; Check if new rate is valid. mov tmp,2 mul tmp ; Get index into baud table. mov bx,offset bddat ; Start of table. add bx,ax mov ax,[bx] ; The data to output to the port cmp ax,0FFH ; Unimplemented baud rate. jne dobd0 mov ax,temp1 ; Get back original value. mov ds:[bp].baud,ax ; Leave rate as is. mov dx,offset badbd ; Give an error message. call tmsg pop bp ; [jrd] pop cx pop bx pop ax ret ; dobd0: mov dx,ax mov bx,34H ; Serial Device Driver mov cx,4 ; Set transmit baud rate int control mov cx,5 ; Set receive baud rate int control mov dx,1 ; Turn on XON/XOFF just in case... mov cx,10 ; Transmit XON/XOFF int control mov cx,11 ; Receive XON/XOFF int control mov cx,3 ; Install changes, zap line, etc... int control mov inited,0 ; Need to re-init on CONNECT pop bp ; [jrd] pop cx pop bx pop ax ret DOBAUD ENDP ; Delete a character from the terminal. This works by printing ; backspaces and spaces. Returns normally. DODEL PROC NEAR mov dx,offset delstr ; Erase weird character. jmp tmsg DODEL ENDP ; This is called by Kermit initialization. It checks the ; number of disks on the system, sets the drives variable ; appropriately. Returns normally. DODISK PROC NEAR mov ah,gcurdsk ; Current disk value to AL. int dos mov dl,al ; Put current disk in DL. mov ah,seldsk ; Select current disk. int dos ; Get number of drives in AL. mov drives,al ret DODISK ENDP ; Get the current baud rate from the serial card and set it ; in the portinfo structure for the current port. Returns normally. ; This is used during initialization. GETBAUD PROC NEAR push ax ; save some regs [jrd] push bx push cx ; [jrd] push dx ; [jrd] push bp ; [jrd] mov bx,34H ; Serial Device Driver mov cx,4 ; Transmit baud rate mov dx,-1 ; Fetch data int control ; Go speak to Control Device Driver mov bx,offset bddat ; -> baud rate table mov cl,0 ; Keep track of index getb0: cmp ax,[bx] je getb1 inc cl cmp cl,baudsiz ; At the end of the list jge getb2 add bx,2 jmp getb0 getb1: mov ch,0 mov bp,portval mov ds:[bp].baud,cx ; Save rate index in port structure ;;;[jrd] ret jmp getb3 ; [jrd] getb2: mov dx,offset erms40 call tmsg getb3: pop bp ; restore regs [jrd] pop dx ; [jrd] pop cx ; [jrd] pop bx ; [jrd] pop ax ; [jrd] ret GETBAUD ENDP ; Initialize local variables and communications port. LCLINI PROC NEAR mov flags.vtflg,0 ; Don't do terminal emulation. mov bx,34H ; Control Device Driver mov cx,0 ; Initialise driver mov dx,0 int control mov cx,6 ; Set transmit bits per character mov dx,8 ; to 8-bit bytes int control mov cx,8 ; Set receive bits per character mov dx,7 ; to 8-bit bytes int control mov cx,8 ; Set number of stop bits mov dx,1 ; to 1 stop bit int control mov cx,9 ; Set parity type mov dx,0 ; Parity handled by DOPAR. int control mov cx,10 ; Transmit XON/XOFF mov dx,1 ; Enabled int control mov cx,11 ; Receive XON/XOFF mov dx,1 ; Enabled int control mov cx,3 ; Install changes int control mov dx,offset kbdesc call tmsg ; Re-program keyboard call cpyktab ; Make a copy of the keyboard table. ret LCLINI ENDP ; Homes the cursor. Returns normally. LOCATE PROC NEAR mov dx,0000H ; Go to top left corner of screen. jmp poscur LOCATE ENDP ; Display mode line. MODLIN PROC NEAR mov al,ourarg.escc mov modbuf.m_echr,' ' mov modbuf.m_hlp,' ' cmp al,32 ; ESC char printable ? jnb modl1 ; Yes, keep going add al,40H ; Convert to printable mov modbuf.m_echr,'^' ; Note control char mov modbuf.m_hlp,'^' modl1: mov modbuf.m_echr+1,al ; Fill in character mov modbuf.m_hlp+1,al ; mov al,ourarg.baudb ; Get baud rate mov si,offset unkbaud ; Just in case it falls out of range cmp al,baudsiz ; Too big ? jnb modl2 ; Yes, use default mov cl,2 ; Each entry is 4 bytes shl al,cl mov ah,0 add ax,offset baudn ; ax -> baud rate string mov si,ax modl2: mov cx,size m_baud ; length of baud space mov di,offset modbuf.m_baud rep movsb ; Copy over baud rate ; mov al,ourarg.parity ; Get parity code mov cl,2 ; Each entry is 4 bytes long shl al,cl mov ah,0 add ax,offset parnams ; ax -> parity setting mov si,ax mov cx,4 mov di,offset modbuf.m_par rep movsb ; Copy over parity setting string ; mov si,offset remmsg ; Assume remote echoing test ourarg.flgs,lclecho jz modl3 mov si,offset lclmsg ; Doing local echo modl3: mov cx,3 mov di,offset modbuf.m_echo rep movsb ; mov si,offset offmsg ; Assume not logging test ourarg.flgs,capt jz modl4 mov si,offset onmsg ; Logging input modl4: mov cx,3 mov di,offset modbuf.m_log rep movsb ; mov dx,offset modbuf call putmod ; Print mode line ret MODLIN ENDP ; Clear microscreen, redisplay time and revert to system keyboard table. MSCROFF PROC NEAR mov ax,0000H mov es,ax ; Point to Segment zero mov al,es:[401H] ; Get machine type cmp al,0 jnz mscof1 ; Not our type mov dx,offset offmscr ; Send setup string call tmsg ; mov ax,keyoff mov es:[0712H],ax ; Point system to its own keytable mov ax,keyseg mov es:[0714H],ax mscof1: ret MSCROFF ENDP ; Test for machine type. If Apricot PC or XI then setup microscreen and ; touch keypad for connect functions. MSCRON PROC NEAR push ds mov ax,0000H mov es,ax ; Point to Segment zero mov al,es:[401H] ; Get machine type cmp al,0 jnz mscon3 ; Not our type mov dx,offset onmscr ; Send setup string call tmsg ; mov ax,0 mov es:[0712H],ax ; Point system to our keytable mov ax,keybd mov es:[0714H],ax mov dl,ourarg.escc ; Store our ESC char in table. mov dh,'R' ; Turn on logging test ourarg.flgs,capt jz mscon1 mov dh,'Q' ; Turn off logging mscon1: mov ds,ax ; Point DS to keytable segment mov bx,offset m1+2 mov cx,6 mscon2: mov [bx],dl add bx,4 loop mscon2 mov bx,offset m6 mov [bx+3],dh ; Setup log on/off mscon3: pop ds ret MSCRON ENDP NOTIMP: mov dx,offset noimp call tmsg jmp prserr ; Put the number in ax into the buffer pointed to by di. di is updated. NOUT PROC NEAR mov dx,0 mov bx,10 div bx push dx or ax,ax jz nout1 call nout nout1: pop ax add al,'0' stosb ret NOUT ENDP ; Put the char in AH to the serial port. This assumes the ; port has been initialized. XON/XOFF are handled by the port ; driver. Skip returns on success, returns normally if the ; character cannot be written. OUTCHR PROC NEAR push bx push cx push dx ; Save register. sub cx,cx mov al,ah ; Parity routine works on AL. call dopar ; Set parity appropriately. mov dl,al mov dh,0 mov cx,1 ; Transmit char mov bx,34H ; Serial Device Driver int control ; System Control Device pop dx pop cx pop bx jmp rskp OUTCHR ENDP ; Position the cursor according to contents of DX: ; DH contains row, DL contains column. Origin (top left) = 0, 0 ; Returns normally. POSCUR PROC NEAR push dx ; Save row & column position mov dl,esc ; Start cursor positioning sequence call tchr mov dl,'Y' call tchr pop dx ; Retrieve row position mov al,dh call poscr1 mov al,dl poscr1: push dx add al,' ' mov dl,al call tchr pop dx ret POSCUR ENDP ; Use for DOS 2.0 and above. Check the port status. If no data, skip ; return. Else, read in a char and return. PRTCHR PROC NEAR push bx push cx push si push bp mov bx,34H mov cx,2 int control ; Read serial port cmp ax,-1 ; Character there ? jnz prtch1 ; Yes, process it... pop bp pop si pop cx pop bx jmp rskp ; No character, skip return. prtch1: mov bp,portval cmp ds:[bp].parflg,PARNON ; no parity? je prtch3 ; then don't strip and al,7fh ; else turn off parity prtch3: pop bp pop si pop cx pop bx ret PRTCHR ENDP ; IHOSTS - Initialize the host by sending XON, or equivalent, and enter the ; cycle of clear input buffer, wait 1 second, test if buffer empty then exit ; else repeat cycle. Requires that the port be initialized before hand. ; Ihosts is used by the local send-file routine just after initializing ; the serial port. ; 22 March 1986 [jrd] IHOSTS PROC NEAR push ax ; save the registers push bx push cx push dx mov bx,portval ; port indicator mov ax,[bx].flowc ; put Go-ahead flow control char in ah call outchr ; send it (release Host's output queue) nop ; outchr can do skip return nop nop ihosts1:call clrbuf ; clear out interrupt buffer mov ax,1 ; sleep for 1 second call sleep ; procedure sleep is in msscom.asm call prtchr ; check for char at port jmp ihosts1 ; have a char in al, repeat wait/read cycle nop ; prtchr does skip return on empty buffer pop dx ; empty buffer. we are done here. pop cx pop bx pop ax ret IHOSTS ENDP ; IHOSTR - initialize the remote host for our reception of a file by ; sending the flow-on character (XON typically) to release any held ; data. Called by receive-file code just after initializing the serial ; port. 22 March 1986 [jrd] IHOSTR PROC NEAR push ax ; save regs push bx push cx mov bx,portval ; port indicator mov ax,[bx].flowc ; put Go-ahead flow control char in ah call outchr ; send it (release Host's output queue) nop ; outchr can do skip return nop nop pop cx pop bx pop ax ret IHOSTR ENDP DTRLOW PROC NEAR ; Global proc to Hangup the Phone by making ; DTR and RTS low. mov ah,cmtxt ; allow text to be able to display help mov bx,offset rdbuf ; dummy buffer mov dx,offset hnghlp ; help message call comnd ; get a confirm jmp r ; not yet imp. call serhng ; drop DTR and RTS mov ah,prstr ; give a nice message ; not yet imp. mov dx,offset hngmsg mov dx,offset noimp ; for now int dos jmp rskp DTRLOW ENDP ; Hang up the Phone. Similar to SERRST except it just forces DTR and RTS low ; to terminate the connection. 29 March 1986 [jrd] ; Calling this twice without intervening calls to serini should be harmless. ; Returns normally. ; SERHNG is Not Yet Implemented. ; Put a help message on the screen. ; Pass the message in ax, terminated by a null. Returns normally. PUTHLP PROC NEAR push ax ; preserve this mov dx,offset crlf call tmsg mov dx,offset invseq ; Turn on high intensity call tmsg pop si ; point to string again puthl3: lodsb ; get a byte cmp al,0 ; end of string? je puthl4 ; yes, stop mov dl,al mov ah,dconio int dos ; else write to screen jmp puthl3 ; and keep going puthl4: mov dx,offset nrmseq ; Back to normal call tmsg mov dx,offset crlf call tmsg ret PUTHLP ENDP ; Write a line in high intensity on line 25. The line is pointed to by ; ds:dx, terminated by a $. Returns normally. PUTMOD PROC NEAR push dx ; preserve message pointer. mov dx,offset on25 ; Move down to line 25 call tmsg mov dx,offset invseq ; Turn on high intensity call tmsg pop dx ; get message back call tmsg ; write it out mov dx,offset nrmseq ; Normal (low) intensity again call tmsg mov dx,offset off25 ; Restore cursor position call tmsg ret ; and return PUTMOD ENDP ; Jumping here is the same as a ret. R PROC NEAR ret R ENDP ; Jumping to this location is like retskp. It assumes the instruction ; after the call is a jmp addr. RSKP PROC NEAR pop bp add bp,3 push bp ret RSKP ENDP ; Send a break out to the serial port. Returns normally. ; Need to handle port directly since ACT's Control Device doesn't ; have a 'send break' facility. SENDBR PROC NEAR mov al,5 out 62H,al ; Select SIO write register 5 mov al,0FAH out 62H,al ; Start break mov al,2 sendb0: mov bx,-1 sendb1: dec bx ; Delay for a while... jnz sendb1 dec al jnz sendb0 mov al,5 out 62H,al ; Select SIO write register 5 mov al,0EAH out 62H,al ; Finished sending break ret SENDBR ENDP ; Initialization for using serial port. XON/XOFF has already been set by ; the local initialization routine. Returns normally. SERINI PROC NEAR cmp portin,0 ; Initialized already ? jne serin0 ; Yes, forget it. cld ; Do increments in string operations ; Some day we may have an interrupt handler to install... call clrbuf ; Clear input buffer. mov portin,1 ; Say we've been through once serin0: ret ; We're done. SERINI ENDP ; Reset the serial port. This is the opposite of serini. Calling ; this twice without intervening calls to serini should be harmless. ; Returns normally. SERRST PROC NEAR cmp portin,0 ; Reset already ? je srst1 ; Yes, forget it ; One day soon we may want to restore the interrupt handler, I hope... mov portin,0 srst1: ret ; All done. SERRST ENDP SHOWKEY PROC NEAR mov ax,offset shkmsg mov cx,shkmln ret SHOWKEY ENDP ; Send a character to the host, handle local echo. SNDHST PROC NEAR push ax mov ah,al call outchr ; Output the character nop nop nop pop ax test ourarg.flgs,lclecho ; Echoing ?? jz sndhs2 ; No, go on mov dl,al mov ah,dconio int dos sndhs2: ret SNDHST ENDP ; Print a character to the screen. Returns normally. TCHR PROC NEAR push ax push bx push cx push dx mov ah,conout int dos pop dx pop cx pop bx pop ax ret TCHR ENDP ; Dumb terminal emulator. TERM PROC NEAR mov si,ax ; this is source mov di,offset ourarg ; place to store arguments mov ax,ds mov es,ax ; address destination segment mov cx,size termarg cld rep movsb ; copy into our arg blk ; call clrmod ; Clear mode line test ourarg.flgs,modoff ; Is mode line disabled ? jnz term0 ; Yes, skip this call modlin ; term0: call mscron ; Set up microscreen cmp inited,0 ; inited yet ? jnz term1 ; yes, skip this bit... mov bx,34H mov dx,1 mov cx,12 ; Turn on RTS int control mov cx,13 ; Turn on DTR int control mov inited,1 ; Remember we've inited term1: call prtchr jmp short term2 ; have a char... nop nop jmp short term3 ; no char, go on term2: and al,7FH push ax mov dl,al mov ah,conout int dos ; go print it pop ax test ourarg.flgs,capt ; capturing output? jz term3 ; no, forget it call ourarg.captr ; else call the routine term3: mov ah,dconio mov dl,0ffh int dos jz term1 ; no character, go on cmp al,ourarg.escc ; escape char? je term5 ; yes, exit call trnout ; translate and output character(s) jmp term1 ; and keep going term5: call clrmod call mscroff ; Clear microscreen ret TERM ENDP ; Print a message to the screen. Returns normally. TMSG PROC NEAR push ax push bx push cx push dx mov ah,prstr int dos pop dx pop cx pop bx pop ax ret TMSG ENDP ; Enter with char and flags in AX. Does any necessary character ; translations, then outputs the character(s). TRNOUT PROC NEAR test ourarg.flgs,havtt ; Translation table given ?? jz trnou2 ; No, just output normally mov cx,ourarg.klen mov di,ourarg.ktab ; get redefined keys repne scasw ; look for this one jne trnou2 ; Not found, try something else. sub di,ourarg.ktab sub di,2 ; Get index add di,ourarg.krpl ; Get translation address mov si,[di] ; This is translation mov cl,[si] ; Pick up length, increment past it inc si mov ch,0 jcxz trnou6 ; No translation, just return trnou1: lodsb ; get a char push si push cx call sndhst ; Send the character pop cx pop si loop trnou1 ; loop thru rest of translation ret ; and return ; trnou2: call sndhst ; output character trnou6: ret TRNOUT ENDP ; Set heath emulation on/off. VTS PROC NEAR jmp notimp VTS ENDP VTSTAT PROC NEAR ; For use by Status in mssset [jrd] ret ; no emulator status to report VTSTAT ENDP ; Save the screen to a buffer and then append buffer to a disk file. [jrd] ; Default filename is Kermit.scn; actual file can be a device too. Filename ; is determined by mssset and is passed as pointer dmpname. DUMPSCR PROC NEAR ; Dumps screen contents to a file. Just Beeps here call beep ; [jrd] ret DUMPSCR ENDP CODE ENDS END