|
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: 46439 (0xb567) Types: TextFile Names: »msxgri.asm«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit └─⟦71044c191⟧ »EurOpenD3/misc/kermit.ms-2.32.tar.Z« └─⟦31f2d420d⟧ └─⟦this⟧ »msxgri.asm«
name msxgri ; File MSXGRI.ASM ; Grid Compass II dependent file for MS-DOS Kermit ; Use with msugri.asm keyboard translator file. ; ; Last edit: 12 June 1988 ; 1 July 1988 Version 2.31 ; 12 June 1988 Add error recovery if serial port fails to initialize, reduce ; serial port buffer to 1000 bytes. [jrd] ; 11 Jan 1988 Add 2.30 features. [jrd] ; 1 Jan 1988 version 2.30 ; ; Jim Noble ; Planning Research Corporation ; 1500 Planning Research Drive ; Mail Stop 5S3 ; McLean, VA 22102 ; May, 1985 ; Add global entry point vtstat for use by Status in mssset. ; Added register save/restore in procedure getbaud. ; 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 & 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] ; In proc Outchr add override of xon from chkxon sending routine. ; This makes a hand typed Xoff supress the xon flow control character sent ; automatically as the receiver buffer empties. 20 April 1986 [jrd] public serini, serrst, clrbuf, outchr, coms, vts, vtstat, dodel, ctlu public cmblnk, locate, prtchr, dobaud, clearl, lclini, getmodem public dodisk, getbaud, beep, setkhlp, setktab, pcwait, trnprs public machnam, xofsnt, count, term, poscur, serhng public clrmod, putmod, puthlp, sendbr, sendbl, showkey, shomodem public ihosts, ihostr, dtrlow, dumpscr, comptab, termtb ; [jrd] public chrout, cstatus, cquit, cquery ; kbd action verbs public snull, kdos, klogof, klogon include mssdef.h false equ 0 true equ 1 print_out equ 05h ; dos function to print to printer prtscr equ 80h ; print screen pressed gbuflen equ 1000 ; max bytes grid internal buffer holds mntrgh equ gbuflen/2 ; High point = 1/2 of buffer full. mntrgl equ bufsiz/4 ; Low point = 1/4 buffer full. [jrd] gserial equ 81h ; grid serial port interrupt gmodem equ 82h ; grid modem port interrupt ginit equ 0 ; function 0 - initialize port gread equ 1 ; function 1 - read data gwrite equ 2 ; function 2 - write data gwcmd equ 4 ; function 4 - write command grstat equ 5 ; function 5 - read status gflush equ 6 ; function 6 - buffer flush ggbaud equ 7 ; function 7 - get baud gsbaud equ 8 ; function 8 - set baud gspar equ 9 ; function 9 - set parity gsdata equ 10 ; function 10 - set data bits gssbit equ 11 ; function 11 - set stop bits gbufass equ 12 ; function 12 - buffer assign gcharto equ 13 ; function 13 - set character timeout gbrk equ 14 ; function 14 - break control gcts equ 19 ; function 19 - clear to send timeout gbrkon equ gbrk*100H+00H ; function 14 - set break on gbrkoff equ gbrk*100H+0ffH ; function 14 - set break off scnstrt equ 400h ; starting address of screen area (page 0) scnwrds equ 4800 ; number of words in screen memory area datas segment public 'datas' extrn drives:byte, flags:byte, trans:byte extrn portval:word, port1:byte, port2:byte, dmpname:byte extrn kbdflg:byte, rxtable:byte machnam db 'GRID COMPASS II version A' curini db 0 ; [gaw@prc] cursav db ESCAPE,'[s','$' ; [gaw@prc] curres db ESCAPE,'[u','$' ; [gaw@prc] curon db ESCAPE,'[3;3z','$' ; [gaw@prc] curoff db ESCAPE,'[3;4z','$' ; [gaw@prc] scrsav dw scnwrds DUP(?) erms20 db cr,lf,'?Warning: System has no disk drives$' erms40 db cr,lf,'?Warning: Unrecognized baud rate$' badbd db cr,lf,'Unimplemented baud rate$' crlf db cr,lf,'$' comphlp db cr,lf,'1 (SERIAL) 2 (MODEM)$' ; [19b] [gaw@prc] hngmsg db cr,lf,' The phone should have hungup.',cr,lf,'$' 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,'$' rdbuf db 80 dup (?) ; temp buf noimp db cr,lf,'?Not implemented.$' delstr db BS,' ',BS,'$' ; Delete string clrlin db cr,ESCAPE,'[0K','$' portin db 0 ; has clock int vector been initialized? xofsnt db 0 ; Say if we sent an XOFF. xofrcv db 0 ; Say if we received an XOFF. insrvc db 0 ; Say if in service on XON/XOFF interrupt parmsk db ? ; parity mask, 0ffh for no parity, 07fh with. flowoff db ? ; flow-off char, Xoff or null (if no flow) flowon db ? ; flow-on char, Xon or null captrtn dw ? ; routine to call for captured output invseq db ESCAPE,'[7m$' ; Reverse video. nrmseq db ESCAPE,'[0m$' ; Normal mode. ivlseq db 79 dup (' '),cr,'$' ; Make a line inverse video tmp db ?,'$' temp dw 0 temp1 dw ? ; Temporary storage. temp2 dw ? ; Temporary storage. fncerr db cr,lf,'Error on function ' fnctype db 'X with a status return of ' fncstat db 'Y$' argadr dw ? ; address of arg blk ; key redefinitions setktab db 0 setkhlp db 0 ontab db 2 ; Two entries. mkeyw 'Off',0 mkeyw 'On',1 ; Entries for choosing communications port. comptab db 4 ; number of entries mkeyw '1',1 ; com1 mkeyw '2',2 ; com2 mkeyw 'COM1',1 mkeyw 'COM2',2 termtb db 2 mkeyw 'none',ttgenrc mkeyw 'VT52',ttvt52 ; this table is indexed by the baud rate definitions given in ; pcdefs. Unsupported baud rates should contain -1. ; (*) - only two supported on modem bddat label word dw -1 ; 45.5 baud -- Not supported. dw 0 ; 50 baud dw 1 ; 75 baud dw 2 ; 110 baud dw 3 ; 134.5 baud dw 4 ; 150 baud dw 5 ; 300 baud - (*) dw 6 ; 600 baud dw 7 ; 1200 baud - (*) dw 8 ; 1800 baud dw 9 ; 2000 baud dw 10 ; 2400 baud dw 12 ; 4800 baud dw 14 ; 9600 baud dw 15 ; 19200 baud dw -1 ; 38400 baud -- Not supported. ; variables for serial interrupt handler gbuffer db gbuflen DUP(?) ; large internal buffer for grid [gaw@prc] source db bufsiz DUP(?) ; Buffer for data from port bufout dw 0 ; buffer removal ptr count dw 0 ; Number of chars in int buffer bufin dw 0 ; buffer insertion ptr telflg db 0 ; Are we acting as a terminal clreol db ESCAPE,'[0K$' blank db ESCAPE,'[2J$' movcur db ESCAPE,'[' colno db 20 dup (?) ten db 10 ourarg termarg <> datas ends code segment public 'code' extrn comnd:near, dopar:near, prserr:near, defkey:near extrn sleep:near, msuinit:near, keybd:near assume cs:code,ds:datas ; local initialization lclini proc near mov portin,0 ; serial port not yet initialized mov flags.vtflg,0 ; turn off terminal emulation [gaw@prc] call msuinit ; init keyboard translator ret lclini endp ; See how many disk drives we have. 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 ; Clear the input buffer before sending a packet. CLRBUF PROC NEAR cli mov ax,offset source mov bufin,ax mov bufout,ax mov count,0 sti clrb1: call prtchr ; get a character jmp clrb1 ; until there aren't any more nop ret CLRBUF ENDP ; Common routine to clear to end-of-line CLEARL PROC NEAR mov dx,offset clreol mov ah,prstr int dos ret CLEARL ENDP SHOMODEM PROC NEAR ; display CD, CTS, DSR. Not implemented here mov ah,prstr mov dx,offset noimp int dos jmp rskp SHOMODEM ENDP getmodem proc near mov al,0 ; modem status, none ret getmodem endp ; Do a grid function call to the correct com port and return GRDFNC PROC NEAR push es ; save es reg push ds ; then mov ds to es pop es push ax ; save function call and value in al add ah,"0" ; make function code printable mov fnctype,ah ; and save in error message pop ax ; restore ax cmp flags.comflg,1 ; serial port or modem? [gaw@prc] jne grdfnc1 ; if modem, do other int [gaw@prc] int gserial ; else do serial port function call [gaw@prc] jmp grdfnc2 ; skip other int [gaw@prc] grdfnc1: int gmodem ; do modem port function call [gaw@prc] grdfnc2: jnc grdfnc3 ; skip error msg if carry not set add al,"0" ; make error code printable mov fncstat,al ; and put in error message mov ah,prstr push dx mov dx,offset fncerr ; Give an error message int dos pop dx grdfnc3: pop es ; restore es ret GRDFNC 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 push bx mov bx,portval mov temp1,ax ; Don't overwrite previous rate mov ax,[bx].baud ; Check if new rate is valid shl ax,1 ; index words mov bx,offset bddat ; Start of table add bx,ax mov ax,[bx] ; The data to output to port cmp ax,0FFH ; Unimplemented baud rate jne dobd0 dobd01: mov ax,temp1 ; Get back original value mov bx,portval mov [bx].baud,ax ; Leave baud rate as is mov ah,prstr mov dx,offset badbd ; Give an error message int dos pop bx pop ax ret dobd0: mov temp1,ax ; Remember value to output cmp flags.comflg,1 ; is it com1? je dobd1 ; yep, skip test for 300/1200 cmp ax,7 ; is it 1200 on com2? je dobd1 ; yep, go do it cmp ax,5 ; is it 300 on com2? je dobd1 ; yep, go do it jmp short dobd01 ; go give unimplemented msg dobd1: mov ah,gsbaud ; set up to set the port baudrate call grdfnc ; do a grid function call to a com port pop bx pop ax ret DOBAUD ENDP ; Send a break out the current serial port. Returns normally. sendbr proc near push cx push ax xor cx,cx ; Clear loop counter mov ax,gbrkon ; setup to do break on [gaw@prc] call grdfnc ; do break on pause: loop pause ; Wait a while mov ax,gbrkoff ; setup to do break off [gaw@prc] call grdfnc ; do break off pop ax pop cx clc ret ; And return sendbr endp SENDBL PROC NEAR ; send a long break call sendbr ; do several of these call sendbr call sendbr call sendbr ret SENDBL ENDP ; Send char in al out the serial port. Checks flow control. ; Return rskp if success, return rskp even if failure. OUTCHR PROC NEAR push bx push cx mov bx,portval cmp [bx].floflg,0 ; Are we doing flow control pop bx je outch2 ; No, just continue xor cx,cx ; clear counter cmp ah,flowoff ; sending xoff? jne outch1 ; ne = no mov xofsnt,false ; supress xon from chkxon buffer routine outch1: cmp xofrcv,true ; Are we being held? jne outch2 ; No - it's OK to go on loop outch1 ; held, try for a while mov xofrcv,false ; timed out, force it off and fall thru outch2: mov byte ptr temp,ah ; put character in buffer push di ; Save register mov cx,1 ; set up to write one char to a grid port mov di,offset temp mov ah,gwrite call grdfnc ; go write a character pop di ; restore saved registers pop cx jmp rskp OUTCHR ENDP ; This routine blanks the screen. CMBLNK PROC NEAR push ax push dx mov ah,prstr mov dx,offset blank int dos pop dx pop ax ret CMBLNK ENDP LOCATE PROC NEAR mov dx,0 ; Go to top left corner of screen. jmp poscur ; callret... LOCATE 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 push bx push cx push dx mov ah,ggbaud ; set up to get port baud rate call grdfnc ; and go get it mov al,ah ; mov baudrate into al mov ah,0 ; and zero upper part of ax mov bx,offset bddat ; Find rate's offset into 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 bx,portval mov [bx].baud,cx ; Set baud rate jmp short getb3 getb2: mov ah,prstr mov dx,offset erms40 int dos getb3: pop dx ; restore regs pop cx pop bx pop ax ret GETBAUD ENDP ; skip returns if no character available at port, ; otherwise returns with char in al, # of chars in buffer in dx. PRTCHR PROC NEAR push si cmp count,0 ; any characters? jne prtch2 ; ne = yes, get from buffer prtch1: push di push bx push cx mov cx,bufsiz ; set up to read from grid port buffer mov di,offset source mov ah,gread call grdfnc pop cx ; restore saved registers pop bx pop di mov count,ax ; reset count or ax,ax jz prtch4 ; still no chars mov bufout,offset source ; this is output ptr prtch2: dec count mov dx,count ; return count in dx mov si,bufout cld lodsb ; get character mov bufout,si ; update ptr pop si ret prtch4: pop si jmp rskp ; no chars 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 or ah,ah ; don't send null if flow = none jz ihosts1 ; z = null call outchr ; send it (release Host's output queue) nop ; outchr can do skip return nop nop ihosts1:call clrbuf ; clear out interrupt 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 or ah,ah ; don't send null if flow = none jz ihostr1 ; z = null call outchr ; send it (release Host's output queue) nop ; outchr can do skip return nop nop ihostr1: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 clc 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. SERHNG PROC NEAR ret SERHNG ENDP ; Wait for the # of milliseconds in ax, for non-IBM compatibles. ; Based on 4.77 Mhz 8088 processor speeds. ; Thanks to Bernie Eiben for this one. pcwait proc near mov cx,240 ; inner loop counter for 1 millisecond pcwai1: sub cx,1 ; inner loop takes 20 clock cycles jnz pcwai1 dec ax ; outer loop counter jnz pcwait ; wait another millisecond ret pcwait endp ; Position the cursor according to contents of DX. POSCUR PROC NEAR push ax ; save regs push dx push es push di mov ax,ds mov es,ax ; address data segment!!! cld mov di,offset colno mov al,dh ; row inc al ; adjust offset from 1 instead of 0 mov ah,0 ; zero up half of reg containing number call nout mov al,';' stosb mov al,dl ; column inc al ; adjust offset from 1 instead of 0 mov ah,0 ; zero up half of reg containing number call nout mov al,'H' stosb mov al,'$' stosb mov dx,offset movcur mov ah,prstr int dos ; print the sequence pop di pop es pop dx pop ax ret POSCUR ENDP ; put the number in ax into the buffer pointed to by di. Di is updated nout proc near push dx ; save registers push bx push ax cld mov dx,0 ; high order is always 0 mov bx,10 div bx ; divide to get digit push dx ; save remainder digit or ax,ax ; test quotient jz nout1 ; zero, no more of number call nout ; else call for rest of number nout1: pop ax ; get digit back add al,'0' ; make printable stosb ; drop it off pop ax ; restore all registers pop bx pop dx ret nout endp ; Write a line in inverse video at the bottom of the screen... ; the line is passed in dx, terminated by a $. Returns normally. putmod proc near push dx ; preserve message mov dx,26 * 100H ; line 26 call poscur mov dx,offset invseq ; put into inverse video mov ah,prstr int dos pop dx int dos mov dx,offset nrmseq ; normal videw int dos ret ; and return putmod endp ; Clear the mode line written by putmod. Returns normally. clrmod proc near mov dx,26 * 100H call poscur call clearl ret clrmod endp ; Put a help message one the screen in reverse video. Pass ; the message in AX, terminated by a null. Returns normally. ; The message is put wherever the cursor currently is located. puthlp proc near push ax mov ah,prstr ; Leave some room before the message mov dx,offset crlf int dos pop si ; Put message address here puth0: mov ah,prstr mov dx,offset invseq ; Put into reverse video int dos mov ah,prstr mov dx,offset ivlseq ; Make line inverse video int dos cld puth1: lodsb cmp al,0 ; Terminated with a null je puth2 mov dl,al mov ah,conout int dos cmp al,lf ; Line feed? je puth0 ; Yes, clear the next line jmp puth1 ; Else, just keep on writing puth2: mov dx,offset crlf mov ah,prstr int dos mov dx,offset nrmseq ; Normal video int dos clc ret puthlp endp ; Perform a delete. DODEL PROC NEAR push ax push dx mov ah,prstr mov dx,offset delstr ; Erase character int dos pop dx pop ax ret DODEL ENDP ; Perform a Control-U. CTLU PROC NEAR push ax push dx mov ah,prstr mov dx,offset clrlin int dos pop dx pop ax ret CTLU ENDP COMS PROC NEAR mov dx,offset comptab mov bx,offset comphlp mov ah,cmkey call comnd jmp r nop push bx mov ah,cmcfm call comnd ; Get a confirm. jmp comx ; Didn't get a confirm nop pop bx mov flags.comflg,bl ; Set the comm port flag cmp flags.comflg,1 ; Using Com 1? jne coms0 ; Nope mov ax,offset port1 mov portval,ax clc ; carry clear for success ret coms0: mov ax,offset port2 mov portval,ax clc ; carry clear for success ret comx: pop bx stc ; carry set for failure ret COMS ENDP ; Set heath emulation on/off. VTS PROC NEAR mov dx,offset termtb mov bx,0 mov ah,cmkey call comnd jmp r nop push bx mov ah,cmcfm call comnd ; Get a confirm jmp vt0 ; Didn't get a confirm nop pop bx mov flags.vtflg,bl ; Set the VT52 emulation flag ret vt0: pop bx ret VTS ENDP VTSTAT PROC NEAR ; For Status display [jrd] ret ; no emulator status to display 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] clc ret DUMPSCR ENDP ; show the definition of a key. The terminal argument block (which contains ; the address and length of the definition tables) is passed in ax. ; Returns a string to print in AX, length of same in CX. ; Returns normally. showkey proc near ret ; and return showkey endp ; Common initialization for using serial port. SERINI PROC NEAR push es cmp portin,0 ; Did we initialize interrupt already? je serin0 ; No, skip exit jmp serin1 ; Yes, so just leave serin0: cli ; Disable interrupts cld ; Do increments in string operations xor ax,ax ; get vector of clock tick int at 1CH mov es,ax mov bx,1Ch*4 mov ax,es:[bx] mov cs:savclko,ax add bx,2 mov ax,es:[bx] mov cs:savclks,ax ;-> all because cli doesn't disable clock tick interrupt! push es ; save pointer to segment part of vector push bx mov es,ax ; point to location with offset replaced mov bx,offset serint mov cl,es:[bx] ; save value in cl mov al,0CFh ; load al with IRET instruction mov es:[bx],al ; put at location with offset replace pop bx pop es sub bx,2 ; now point to offset part of vector mov ax,offset serint mov es:[bx],ax ; and load with offset of serint add bx,2 ; now point to segment part of vector mov ax,cs mov es:[bx],ax ; and load with code segement address mov ax,cs:savclks ; now restore byte at offset of serint mov es,ax mov bx,offset serint mov es:[bx],cl ;<- mov portin,1 ; Remember interrupt has been initialized sti ; turn interrupts back on call dobaud ; reset baud just incase modem hung up xor ax,ax mov ah,gspar ; parity = none call grdfnc mov al,1 ; stopbit = 1 mov ah,gssbit call grdfnc mov al,8 ; data bits = 8 mov ah,gsdata call grdfnc mov dx,1 ; timeout on char read wait = 1ms mov ah,gcharto call grdfnc cmp flags.comflg,1 ; Using Com 1? jne skipcts ; Nope. mov dx,0 ; timeout on cts = 0 mov ah,gcts call grdfnc skipcts:mov ax,ds ; point to large buffer mov es,ax mov di,offset gbuffer mov cx,gbuflen mov ah,gbufass call grdfnc mov ah,gflush ; flush grid input buffer call grdfnc push bx mov bx,portval ; get port mov parmsk,0ffh ; parity mask, assume parity is None cmp [bx].parflg,parnon ; is it None? je serin2 ; e = yes mov parmsk,07fh ; no, pass lower 7 bits as data serin2: mov bx,[bx].flowc ; get flow control chars mov flowoff,bl ; xoff or null mov flowon,bh ; xon or null pop bx call clrbuf ; Clear input buffer serin1: pop es clc ; carry clear for success ret SERINI ENDP SERRST PROC NEAR cmp portin,0 ; Did we initialize interrupt already? je serrst0 ; No, skip resetting clock vector cli ; Disable interrupts ;-> all because cli doesn't disable clock tick interrupt! push es ; restore vector of clock tick int at 1CH mov ax,cs:savclks ; get pointer to location when segment replaced mov es,ax mov bx,offset serint mov cl,es:[bx] ; save value from there in cl mov al,0CFh ; load location with IRET mov es:[bx],al push es ; save segment pointer for later push bx xor ax,ax ; point to segment part of vector mov es,ax mov bx,(1Ch*4)+2 mov ax,cs:savclks ; replace with original value mov es:[bx],ax sub bx,2 ; now replace offset with original value mov ax,cs:savclko mov es:[bx],ax pop bx ; now restore location holding temporary IRET pop es mov es:[bx],cl pop es ; and clean up stack ;<- mov portin,0 ; Remember interrupt has been reset. sti ; turn interrupts back on serrst0: ret ; All done SERRST ENDP ; Comm port interrupt service routine to prevent grid buffer overflow ; sends Xoff if necessary if activated ; SERINT PROC NEAR push ax push bx push cx push dx push ds push es push si push di push bp pushf cld mov ax,seg datas mov ds,ax ; address data segment mov es,ax mov bx,portval cmp [bx].floflg,0 ; Doing flow control? je retint ; No, just leave. jmp retint ; <<===<< temporary stub until grid problem resolved cmp insrvc,true ; are we already doing interrupt service? je retint ; yes, then skip service until this one done mov insrvc,true ; nope, set in service flag sti ; flag set enable interrupts mov ah,grstat ; get the buffer count call grdfnc cmp xofsnt,true ; Have we sent an XOFF? je serint1 ; Yes. cmp cx,mntrgh ; Past the high trigger point? jbe intdone ; No, we're within our limit mov ah,flowoff ; Get the XOFF or ah,ah ; null (no flow control)? jz intdone ; z = yes, do nothing mov byte ptr temp,ah ; put character in buffer mov cx,1 ; set up to write one char to a grid port mov di,offset temp mov ah,gwrite call grdfnc ; go write a character mov xofsnt,true ; Remember we sent it jmp intdone serint1: cmp cx,mntrgl ; below the low trigger point? ja intdone ; no, don't send XON mov ah,flowon ; get the XON or ah,ah ; null? jz intdone ; z = yes, do nothing mov byte ptr temp,ah ; put character in buffer mov cx,1 ; set up to write one char to a grid port mov di,offset temp mov ah,gwrite call grdfnc ; go write a character mov xofsnt,false ; remember we sent it intdone: mov insrvc,false ; set in service flag to false retint: sti popf pop bp pop di pop si pop es pop ds pop dx pop cx pop bx pop ax jmp dword ptr cs:savclko savclko dw ? ; save clock tick interrupt vector offset savclks dw ? ; save clock tick interrupt vector segment SERINT ENDP ; Generate a short beep. BEEP PROC NEAR mov dl,bell mov ah,conout int dos ret BEEP ENDP ; put the character in al to the screen, do capture and printing, ; does translation for Set Input command. ; Adapted from msyibm.asm [jrd] outtty proc near test flags.remflg,d8bit ; keep 8 bits for displays? jnz outnp8 ; nz = yes, 8 bits if possible and al,7fh ; remove high bit outnp8: cmp rxtable+256,0 ; is translation off? je outnp7 ; e = yes, off push bx ; Translate incoming char [jrd] mov bx,offset rxtable ; address of translate table [jrd] xlatb ; new char is in al pop bx outnp7: push bx mov bx,argadr ; args from msster directly test [bx].flgs,capt ; capturing output? Can be shut off pop bx ; if out dev becomes not ready jz outnoc ; no, forget this part push ax ; save char call captrtn ; give it captured character pop ax ; restore character and keep going outnoc: test ourarg.flgs,prtscr ; should we be printing? jz outnop ; no, keep going push ax mov ah,print_out ; write to system printer device mov dl,al int dos pop ax jnc outnop ; nc = successful print push ax call beep ; else make a noise and call trnprs ; turn off printing pop ax outnop: cmp flags.vtflg,0 ; emulating a terminal? jnz outnop1 ; nz = yup, go do something smart test ourarg.flgs,trnctl ; debug? if so use dos tty mode jz outnp4 ; z = no mov ah,conout cmp al,7fh ; Ascii Del char or greater? jb outnp1 ; b = no je outnp0 ; e = Del char push ax ; save the char mov dl,7eh ; output a tilde for 8th bit int dos pop ax ; restore char and al,7fh ; strip high bit outnp0: cmp al,7fh ; is char now a DEL? jne outnp1 ; ne = no and al,3fH ; strip next highest bit (Del --> '?') jmp outnp2 ; send, preceded by caret outnp1: cmp al,' ' ; control char? jae outnp3 ; ae = no add al,'A'-1 ; make visible outnp2: push ax ; save char mov dl,5eh ; caret int dos ; display it pop ax ; recover the non-printable char outnp3: mov dl,al int dos ret outnp4: cmp al,bell ; bell (Control G)? [jrd] jne outnp5 ; ne = no jmp beep ; use short beep, avoid char loss. outnop1: outnp5: mov ah,conout ; dostty screen mode mov dl,al ; write without intervention. int dos ; else let dos display char ret ; and return outtty endp ; send the character in al out to the serial port ; handle echoing also... outprt proc near test flags,lclecho ; echoing? jz outpr1 ; no, forget it push ax ; save char call outtty ; print it pop ax ; restore outpr1: mov ah,al ; this is where outchr expects it call outchr ; output to the port nop nop nop ; skip returns ret outprt endp ; Get a char from the serial port manager ; returns with carry on if a character is available portchr proc near call prtchr ; character at port? jmp short portc1 ; yes, go handle nop portc0: clc ; no carry -> no character ret ; and return portc1: and al,parmsk ; apply 8/7 bit parity mask or al,al ; null? jz portc0 ; z = yes, ignore cmp al,DEL ; ascii DEL code? je portc0 ; e = yes, ignore stc ; have a character ret ; and return portchr endp argini proc near ; read passed arguments mov bx,argadr ; base of argument block mov al,[bx].flgs ; get flags and al,capt+emheath+havtt+trnctl+lclecho mov flags,al ; mask for allowable and save ; and flags1,not (prtscr) ; these are allowable ; (others remain). mov ax,[bx].captr mov captrtn,ax ; buffer capture routine mov parmsk,0ffh ; parity mask, assume parity = None cmp [bx].parity,parnon ; is parity None? je argin2 ; e = yes, keep all 8 bits mov parmsk,07fh ; else keep lower 7 bits argin2: ret ; that's it argini endp term proc near mov argadr,ax ; save argument ptr push es mov si,ax ; this is source mov di,offset ourarg ; place to store arguments push ds pop es ; address destination segment mov cx,size termarg cld rep movsb ; copy into our arg blk pop es call argini ; init options from arg address cmp curini,0 ; have we been in here before[gaw@prc] je term1 ; if not skip restoring cursor[gaw@prc] call restscr ; restore screen cmp flags.vtflg,0 ; are we in emulation mode[gaw@prc] jne term1 ; to skip restoring cursor[gaw@prc] mov ah,prstr ; send '<esc>[u' to ansi.sys[gaw@prc] mov dx,offset curres ; [gaw@prc] int dos ; [gaw@prc] term1: call portchr ; read char from serial port jnc short term3 ; nc = no char, go on call outtty ; display and capture char [jrd] term3: call keybd ; call keyboard xlator, send results jnc term1 ; nc = stay in Connect mode cmp flags.vtflg,0 ; are we in emulation mode[gaw@prc] jne term5 ; if we are skip saving cursor[gaw@prc] mov ah,prstr ; send '<esc>[s' to ansi.sys[gaw@prc] mov dx,offset cursav ; [gaw@prc] int dos ; [gaw@prc] mov byte ptr curini,1 ; now we've saved the cursor[gaw@prc] term5: ; [gaw@prc] call savescr ; save screen [gaw@prc] mov al,flags mov bx,argadr mov [bx].flgs,al ; update flags in arg block ret ; and return to caller term endp savescr proc near push es ; move ds base address to es push ds pop es mov di,offset scrsav ; point to start of screen save area mov si,scnstrt ; point to screen memory area mov cx,scnwrds ; setup word count push ds xor ax,ax ; point to base page with ds mov ds,ax cld rep movsw ; transfer image to save area pop ds ; restore registers and return pop es ret savescr endp restscr proc near mov dx,offset curoff ; turn off cursor mov ah,prstr int dos mov dx,offset blank ; clear screen to get rid of cursor mov ah,prstr int dos push es ; point to base page with es xor ax,ax ; restore screen mov es,ax mov di,scnstrt ; point to screen memory area mov si,offset scrsav ; point to start of screen save area mov cx,scnwrds ; setup word count cld rep movsw ; transfer image to screen pop es mov dx,offset curon ; turn on cursor mov ah,prstr int dos ret restscr endp ;; keyboard translator action routines, system dependent, called from msugen. ; These are invoked by a jump instruction. Return carry clear for normal ; processing, return carry set for invoking Quit (kbdflg has transfer char). ;trnmod: test flags,modoff ; mode line already off? ; jnz trnm1 ; yes, go turn on ; call clrmod ; no, clear mode line here ; or flags,modoff ; turn on flag ; ret ; and return ;trnm1: call modlin ; turn on mode line ; and flags,not modoff ; clear flag ; ret ; and return ; chrout: call outprt ; put char in al to serial port clc ; stay in Connect mode ret trnprs: push ax ; toggle Copy screen to printer test ourarg.flgs,prtscr ; are we currently printing? jnz trnpr2 ; nz = yes, its on and going off mov ah,ioctl mov al,7 ; get output status of printer push bx mov bx,4 ; file handle for system printer int dos pop bx jc trnpr1 ; c = printer not ready cmp al,0ffh ; Ready status? je trnpr2 ; e = Ready trnpr1: call beep ; Not Ready, complain jmp trnpr3 ; and ignore request trnpr2: xor ourarg.flgs,prtscr ; flip the flag trnpr3: pop ax clc ret klogon proc near ; resume logging (if any) test flags.capflg,logses ; session logging enabled? jz klogn ; z = no, forget it or ourarg.flgs,capt ; turn on capture flag klogn: clc ret klogon endp klogof proc near ; suspend logging (if any) and argadr.flgs,not capt ; stop capturing klogo: clc ret klogof endp snull: mov ah,0 ; send a null call outchr ; send without echo or logging nop nop nop clc ret kdos: mov al,'P' ; Push to DOS jmp short cmdcom cstatus:mov al,'S' ; these commands exit Connect mode jmp short cmdcom cquit: mov al,'C' jmp short cmdcom cquery: mov al,'?' jmp short cmdcom cmdcom: mov kbdflg,al ; pass char to msster.asm via kbdflg stc ; say exit Connect mode ret ; 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 ; Jumping here is the same as a ret. R PROC NEAR ret R ENDP code ends end