NAME msyz10 ; File MSYZ10.ASM include mssdef.h ; Copyright (C) 1982,1991, Trustees of Columbia University in the ; City of New York. Permission is granted to any individual or ; institution to use, copy, or redistribute this software as long as ; it is not sold for profit and this copyright notice is retained. ; Kermit system dependent module for Heath/Zenith Z100 ; Edit history ; 2 March 1991 version 3.10 ; Last change: 3 November 1990. ; Minor changes to outtty and outprt. Added setchtab, modified termtb. ; Putcirc and getcirc have been modified from msyibm and added but remains ; untested and inactive. VTS and VTSTAT and most of the corresponding data ; is kept in msx in order to allow assemly of this file , msy, with MASM 4. ; Procedures savescr, restscr, atsclr and setcol added and calls to these ; added to scrini and quit. Procedure revscn (2 variants) added. ; Procedure dumpscr moved from msxz10.asm and restructured to allow general ; use of some code now put in local subroutines rdset, rdlne and endfix. ; Procedure scroll added, to allow 26 lines scrolling entirely in video ; memory, provided 64k video ram chips are installed. ; Handling of ESC E and ESC J in outtty for the S-100 ports, COM3/COM4, ; refined. ; Getpos and setpos corrected (dl = col, dh = row, comments incorrect in ; msyibm.asm). ; ; Bo Gedda ; public term, lclyini, holdscr, scroll, savescr, restscr, atsclr public outprt, prtbout, chrout, vclick, vtemu, yflags public cquit, udkclear, low_rgt, vtclear, getpos, setpos public csrtype, termtb, comptab, ontab, beltab public scrtab, curtab, chatab, cntltab, kpamtab, dirtab public vtbell, dumpscr, fcsrtype public f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, sf0 public sf1, sf2, sf3, sf4, sf5, sf6, sf7, sf8, sf9, sf10, sf11 public i_chr, d_chr, i_line, d_line public uparrw, dnarrw, rtarr, lfarr, pf1, pf2, pf3, pf4 public kp0, kp1, kp2, kp3, kp4, kp5, kp6, kp7, kp8, kp9 public kpminus, kpcoma, kpenter, kpdot, cstatus, cquit public out8bit, trnmod, cdos, cquery, chang, trnprs, dmpscn public homwnd, endwnd, dnwpg, upwpg, upone, dnone, klogon, klogof public snull, doscol, setcol, revscn, lincur public belltype, vtroll, setchtab public extmacro, vtmacname, vtmaclen true equ 1 false equ 0 delaycount equ 1fffh ; Range 1h to 0h (ffffh + 1h = 0h!) ; Entry points to ROM monitor MTR_SEG SEGMENT AT 0FE01H ; Segment addr for Monitor ROM calls ORG 000H MTR_RES LABEL FAR ; Reset function ORG 005H MTR_MON LABEL FAR ; Monitor call ORG 00AH MTR_SWIM LABEL FAR ; Trace/breakpoint handler ORG 00FH MTR_DCRT LABEL FAR ; Dumb display output ORG 014H MTR_DKBD LABEL FAR ; Dumb keyboard handler ORG 019H MTR_SCRT LABEL FAR ; Smart display output ORG 01EH MTR_SKBD LABEL FAR ; Smart keyboard input ORG 023H MTR_TTY_INTR LABEL FAR ; Vertical retrace interrupt handler MTR_SEG ENDS MTR_D_SEG SEGMENT AT 0 ; Monitor data segment(not really at 0) ORG 000H ; Monitor Parameters MTR_WIP LABEL FAR ; Far jump to wild interrupt handler DB 5 DUP(?) ; the far jump MTR_VER DB ? ; BCD version of ROM monitor MTR_CVER EQU 01H ; Lowest version BIOS can run on MTR_DS_SIZE DW ? ; Size of the ROM monitor data segment ; Boot parameters MTR_BINDX DB ? ; Boot device index MTR_BPORT DB ? ; Boot device base port number MTR_BSTRING DB 80 DUP(?) ; Boot string MTR_BUNIT DB ? ; Boot unit number ; Pointers to All sorts of things MTR_DCI DD ? ; Addr of Display Character Initialization MTR_DFC DD ? ; Addr of Display Font Character Routine MTR_DXMTC DD ? ; Addr of Dumb Keyboard Transmit Character MTR_EDC DD ? ; Addr of Erase Display Character Routine MTR_EMEC DD ? ; Addr of Escape Character Handler Routine MTR_FONT DD ? ; Addr of Character Font table MTR_FNT_SIZE EQU 9*(256-' ') ; Size of reserved font table ; number of bytes copied from rom font ; area if version = 1) MTR_MDC DD ? ; Addr of Move Display Characters Routine MTR_MDL DD ? ; Addr of Move Display Line Routine MTR_PROMPT DD ? ; Addr of Display ROM Monitor Prompt Routine MTR_RDC DD ? ; Addr of Read Displayed Character Routine MTR_SXMTC DD ? ; Addr of Smart Keyboard Transmit Character MTR_UIES DD ? ; Addr of Unimplemented Escape Sequence MTR_XCA DD ? ; Addr of Transmit Character Attributes MTR_FNTSIZ DW ? ; Size of FONT in bytes (If version > 1) MTR_KYB DB 256 DUP (?) ; Keyboard map table MTR_CHR DB 256 DUP (?) ; Display map table MTR_HORP DB ? ; Horizontal position of cursor (column) MTR_VERP DB ? ; Vertical position of cursor (row) MTR_MIB DB ? ; Base interrupt number for master MTR_SIB DB ? ; Base interrupt number for slave MTR_RESF DB ? ; Reset flag to re-enter monitor ; Color structure ORG 2A1H FORE DB ? ; Current foreground color BACK DB ? ; Current backpround color MSK DB ? ; Color to mask CLEAR DB ? ; Color to clear PAINTED DB ? ; Color to paint PFONT DB ? ; Color to set to font pattern COMP_FONT DB ? ; Color to set to complement of font pattern ; These are the new ones BACK_CB DB ? ; Back control bits BACK_SEG DW ? ; Back segment CP_BACK_CB DB ? ; Complement back control bits CP_BACK_SEG DW ? ; Complement back segment CLEAR_CB DB ? ; Clear control bits CLEAR_SEG DW ? ; Clear segment PAINTED_CB DB ? ; Painted control bits PAINTED_SEG DW ? ; Painted segment PFONT_CB DB ? ; Font control bits PFONT_SEG DW ? ; Font segment CP_FONT_CB DB ? ; Complement font control bits CP_FONT_SEG DW ? ; Complement font segment ; CRT-C display structure ORG 2BDH DISP_START DW ? ; CRT-C display start address DISP_UPDATE DB ? ; FF to request update ; H-19 mode structure ORG 2D1H BWO DB ? ; Black/white optimization ORG 2DBH STATUS DB ? ; FF modeline on, 0 modline off ; H-19 parameter structure ORG 2E1H PROVRAM DB ? ; 0 = monochrome, 3 = color ORG 2E6H VRAM_SIZE DB ? ; 0 = 32k, 1 = 64k MTR_D_SEG ENDS IPAGE_SEG SEGMENT AT 0 ; The interrupt area page ORG 03FEH MTR_DS LABEL WORD ; Location that contains monitor DS value IPAGE_SEG ENDS ;bios definitions BIOS_SEG SEGMENT AT 40H ; Define segment where BIOS really is ORG 1*3 BIOS_STATUS LABEL FAR ; Console input status ORG 2*3 BIOS_CONIN LABEL FAR ; Console input ORG 3*3 BIOS_CONOUT LABEL FAR ; Console output ORG 4*3 BIOS_PRINT LABEL FAR ; Printer output ORG 6*3 BIOS_AUXOUT LABEL FAR ; AUX output routine ORG 25*3 BIOS_PRNFUNC LABEL FAR ; PRN: FUNCTION ORG 26*3 BIOS_AUXFUNC LABEL FAR ; AUX: function ORG 27*3 BIOS_CONFUNC LABEL FAR ; CON: function BIOS_SEG ENDS ; Define functions of BIOS_CONFUNC, BIOS_PRNFUNC, and BIOS_AUXFUNC CHR_WRITE EQU 0 ; Write function CHR_READ EQU CHR_WRITE+1 ; Read function CHR_STATUS EQU CHR_READ+1 ; Status function CHR_SFGS EQU 0 ; Get status subfunction CHRS_WA EQU 00000001B ; sent, waiting for CHRS_WD EQU 00000010B ; seen, waiting for CHRS_SN EQU 00000100B ; Sending nulls CHRS_TXR EQU 10000000B ; Transmitter ready to send data CHRS_RXR EQU 01000000B ; Receiver has data CHRS_RXOF EQU 00100000B ; Receiver queue overflow CHRS_RXE EQU 00010000B ; Other type of reciver error CHRS_TXE EQU 00001000B ; Transmitter error CHR_SFGC EQU CHR_SFGS+1 ; Get configuration info subfunction CHR_CONTROL EQU CHR_STATUS+1 ; Control function CHR_CFSU EQU 0 ; Setup new configuration parms subfunction CHR_CFCI EQU CHR_CFSU+1 ; Clear input subfunction CHR_CFCO EQU CHR_CFCI+1 ; Clear output subfunction CHR_LOOK EQU CHR_CONTROL+1; Nondestructive read function CHR_FMAX EQU CHR_LOOK ; Maximum function number ; Z-100 Keyboard commands keyrst equ 00h ; reset keyrpon equ 01h ; auto repeat on keyrpof equ 02h ; auto repeat off keyclon equ 03h ; click on keyclof equ 04h ; click off keyclr equ 05h ; clear buffer keycli equ 06h ; make key click keybel equ 07h ; make bell sound keyena equ 08h ; enable keyboard keydis equ 09h ; disable keyboard keyeve equ 0ah ; make keyboard event driven (up/down mode) keyasc equ 0bh ; make keyboard scan ascii keyiena equ 0ch ; enable interrupt keyidis equ 0dh ; disable interrupt ; Definitions for cursor type. ; bit 0 set = 1 => Cursor on cleared = 0 => Cursor off ; bit 1 set = 2 => Block cursor cleared = 0 => Underline cursor ; bit 2 set = 4 => Non blinking cursor cleared = 0 => Blinking cursor cur_on equ 1 ; 00000001b cur_blo equ 2 ; 00000010b cur_nob equ 4 ; 00000100b ; Miscellaneous scan codes used for functions prscan equ 0a2h ; print-screen scan code (F12)... brkscan equ 0aah ; Break key COLUMNS EQU 80 ; Characters per screen line ROWS EQU 24 ; Text lines per screen VID_CMD EQU 0d8h ; Video-memory control port VID_NOR EQU 01111000b ; Video access on, individual color write ; only, all colors displayed PAR_GRN EQU 0e000h ; Green video plane segment address PAR_RED EQU 0d000h ; Red video plane segment address PAR_BLU EQU 0c000h ; Blue video plane segment address ; Kinds of terminals available ;ttgenrc equ 0 ; Type 0: no emulation done by Kermit ;ttheath equ 1 ; Type 1: Heath-19 ;ttvt52 equ 2 ; Type 2: VT52 ;ttvt100 equ 3 ; Type 3: VT102 ;TTTYPES equ 4 ; Number of terminal types defined ; DEC emulator status flags (bits in words vtemu.vtflgst and vtemu.vtflgop) ;anslnm equ 1H ; ANSI line feed/new line mode ;decawm equ 2H ; DEC autowrap mode ;decscnm equ 80H ; DEC screen mode ;decckm equ 200H ; DEC cursor keys mode ;deckpam equ 400H ; DEC keypad application mode ;decom equ 800H ; DEC origin mode ;deccol equ 1000H ; DEC column mode (0=80 col) ;decanm equ 2000H ; ANSI mode ;dececho equ 4000H ; ANSI local echo on (1 = on) ; ; Terminal SETUP mode flags (joint with bits above, some name dups) ;vsnewline equ 1H ; ANSI new line (0 = off) ;vswrap equ 2H ; Line wrap around (0 = no wrap) ;vsnrcm equ 4H ; National Rep Char set (0=none) ;vswdir equ 8H ; Writing direction (0=left, 1 right) ;vskeyclick equ 10H ; Keyclick (0 = off) ;vsmarginbell equ 20H ; Margin bell (0 = off) ;vscursor equ 40H ; Cursor (0 = block, 1 = underline) ;vsscreen equ 80H ; Screen (0 = normal, 1 = rev. video) ;vscntl equ 100h ; 8 or 7 bit controls (1 = 8-bit) ; bit for flag byte havtt equ 10h ; have translate table modfrm struc ; format of mode line db 'Esc chr: ' m_echr db 2 dup (?) db ' Help: ' m_hlp db 2 dup (?) db '?' db ' Port: ' m_prt db 1 dup (?) db ' Speed: ' m_baud db 4 dup (?) db ' Parity: ' m_par db 4 dup (?) db ' Echo: ' m_echo db 3 dup (?) db ' ' m_emul db 10 dup (?) m_pad db 1 dup (?) db ' ' m_prn db 3 dup (?) db '$' modfrm ends data segment extrn flags:byte, caplft:byte, portval:word, trans:byte extrn klen:word, ktab:word, krpl:word, flowon:byte, flowoff:byte extrn dosnum:word, kbdflg:byte, kbcodes:byte, npages:word extrn taklev:byte, takadr:word, mcctab:byte, dupflg:byte extrn ttyact:byte, dmpname:byte, filtst:byte, rdbuf:byte extrn prnhand:word anspflg db 0 ; printer flag bits and definitions vtmacname dw 0 ; pointer to selected macro name vtmaclen db 0 udkseg dw 18 dup (0) ; segment of user definable key defs oldsp dw 0 ; offset to longjmp to for i/o failure inited equ 08h ; been here before vtinited db 0 ; flag for emulator having been inited cursor dw 0 lincur dw ? ; cursor type save area doscol db ?,? ; foreground col, background col tercol db 6,0 ; foreground col, background col dosattr db ? ; screen attributes at init time tv_segs dw 0 ; Topview virtual screen, segment tv_sego dw 0 ; and offset yflags db 0 ; status flags argadr dw ? ; address of arg blk savadr dw 2 dup (0) ; offset then segment of saved screen trmtyp dw 0 ; most recent terminal type vtclear db 0 ; nonzero to redo emulator screen insert db 'O' ; flag for overwrite/insert mode, O/@ temp dw 0 ; scratch storage pntmsg db 'Printer not ready, printing request skipped$' pntptr dw dumpbuf ; pointer to next free byte in buffer dumplen equ 132 dumpbuf db dumplen dup (?) ; / 134 byte dump work buffer crlf db cr,lf,'$' ; \ needs these too scbattr db ? ; screen background attribute belltype db 0 ; 0 = aural bell, 1 = visual fairness dw 0 savattr db 78h ; cur. emul. attrib., 78h = all colors fairprn dw 0 parmsk db 0 ; 8/7 bit parity mask, for reception captrtn dw 0 ; routine to call for captured output portno db 0 memerr db cr,lf,'Not enough memory for terminal emulator$' vstate db 0 ; Video ram port-status at invocation. int_cy dw 0 ; Vertical screen index (line number). line db (COLUMNS+4) dup (0) ; Screen's line buffer. lines dw 0 ; Number of lines valid on screen. eos db 0 ; flag: 0= not end of screen, 1= yes. dmphand dw ? ; screen dump file handle [jrd] dmperr db cr,' Cannot open save screen file $' dmperr1 db cr,' Cannot write save screen file $' holdscr db 0 ; Hold-Screen, non-zero to stop reading ; storage for multi-window stuff swidth equ COLUMNS ; max screen width, 80 slen equ ROWS ; and length of text, 24 crt_norm db 3 ; video mode for normal screen crt_mode db 3 ; video mode (typ 3, must be text) crt_cols db COLUMNS ; number of screen columns (typ 80) crt_lins db ROWS ; number of screen rows - 1 (typ 24) low_rgt dw 174fh ; lower right corner of text window startad dw 0 ; storage for CRTC Start Address refresh db 0 ; screen refresh (0=wait for retrace) vtroll db 0 ; auto roll back allowed (0 = no) inipara dw 0 ; initial paragraphs of scroll memory even ; screen rollback material iniseg dw ? ; (BDT) initial seg of scroll memory ppl dw 0 ; (BDT) paragraphs per line lcnt dw 0 ; (BDT) number of "filled" buffer lines linef dw 0 ; (BDT) "first" filled line is here linec dw 0 ; (BDT) "current" screen line number linee dw 0 ; (BDT) total # of lines in the buffer lmax dw 0 ; (BDT) max lines in buff (less 1 scrn) lxtra dw 0 ; (BDT) "extra" lines rqd for screen ; begin video ram complement storage vidmsg db cr,' Cannot scroll, need 64k video ram $' mtrmsg db cr,lf,'Monitor boot rom must be Version 2.5 or above. Refer ' db 'to your Z-100 Manual$',cr,lf ; begin Terminal emulator data set setchtab db 6 ; Set File Character-Set table mkeyw 'CP437',437 ; hardware default Code Page mkeyw 'CP850',850 ; Multilingual CP mkeyw 'CP860',860 ; Portuguese CP mkeyw 'CP863',863 ; French Canadian CP mkeyw 'CP865',865 ; Norwegian CP mkeyw 'CP866',866 ; Latin5/Cryillic CP termtb db 2 ; entries for Status, not Set mkeyw 'Heath-19',ttheath mkeyw 'none',ttgenrc comptab db 12 ; Twelve entries. mkeyw '1',1 mkeyw '2',2 mkeyw '3',3 mkeyw '4',4 mkeyw 'COM1',1 mkeyw 'COM2',2 mkeyw 'COM3',3 mkeyw 'COM4',4 mkeyw 'A',2 mkeyw 'B',1 mkeyw 'J1',2 mkeyw 'J2',1 cntltab db 2 ; 8-bit controls mkeyw '7-bit',0 mkeyw '8-bit',1 scrtab db 2 ; screen attributes mkeyw 'normal',0 mkeyw 'reverse',1 ontab db 2 ; two entries mkeyw 'off',0 mkeyw 'on',1 chatab db 14 ; National Replacement Character sets mkeyw 'ASCII',0 ; ASCII is default (0, no NRC) mkeyw 'British',1 ; start NRC set (1-12) mkeyw 'Dutch',2 mkeyw 'Finnish',3 mkeyw 'French',4 mkeyw 'Fr-Canadian',5 mkeyw 'German',6 mkeyw 'Italian',7 mkeyw 'Norwegian/Danish',8 mkeyw 'Portuguese',9 mkeyw 'Spanish',10 mkeyw 'Swedish',11 mkeyw 'Swiss',12 ; end of NRC proper mkeyw 'Transparent',14 ; use native display adapter hardware curtab db 3 ; cursor attributes mkeyw 'block',0 mkeyw 'underline',1 mkeyw 'none',2 beltab db 3 ; bell type mkeyw 'audible',0 mkeyw 'visual',1 mkeyw 'none',2 dirtab db 2 ; writing direction mkeyw 'left-to-right',0 mkeyw 'right-to-left',1 kpamtab db 2 ; keypad, application mkeyw 'Numeric',0 mkeyw 'Application',1 flags1 db 0 ; internal flags prtscr equ 80h ; print screen pressed flag escflg db 0 ; esc character received flag padflg db 0 ; keypad mode changed flag ansflgs dw 0 ; ANSI/VT100 mode flags ; (flags are defined in mssdefs.h) vtemu emulst <> ; emulator flags eeolstr db ESCAPE,'K$' ; Erase to end of line enascan db ESCAPE,'y?$' ; Enable scan codes, disable key expansion disscan db ESCAPE,'x?$' ; Disable scan codes, enable key expansion enacurs db ESCAPE,'y5$' ; Enable cursor discurs db ESCAPE,'x5$' ; Disable cursor enablnk db ESCAPE,'y;$' ; Enable cursor blink disblnk db ESCAPE,'x;$' ; Disable cursor blink enabloc db ESCAPE,'x4$' ; Enable block cursor enaunde db ESCAPE,'y4$' ; Enable underscore cursor savcur db ESCAPE,'j$' ; Save current cursor position begrev db ESCAPE,'p$' ; Enter reverse video padpos db ESCAPE,'Y8k$' ; Row 25 column 75 endrev db ESCAPE,'q$' ; Exit reverse video precur db ESCAPE,'k$' ; Restore cursor to previous position modbuf modfrm <> ; mode line buffer ; some static data for mode line unkbaud db 'Unk ' ; must be 4 chars... 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' baudnsiz equ 16 ; # of baud rates known (tbl size / 4) parnams db 'Even' db 'Mark' db 'None' db 'Odd ' ; must be 4 chars db 'Spc ' lclmsg db 'Lcl' remmsg db 'Rem' prmsg db 'PRN' db ' ' noleds db ' None ' ; For no emulation ansleds db 'VT102 ....' ; "LEDs". Terminal ident (10 bytes) v52leds db ' VT52 ' ; This is used in VT52 mode h19leds db ' Heath-19 ' ; For Heath-19 mode vtable dw ontab, ontab, chatab, dirtab ,ontab, ontab, curtab, scrtab dw cntltab, kpamtab, 0 ; which are newline wrap char direct key margin cursor screen ; controls key-app data ends code1 segment fcsrtype proc far ret fcsrtype endp code1 ends code segment extrn prtchr:near,outchr:near,putmod:near,clrmod:near,sendbr:near extrn sprtch:near, beep:near, pcwait:near, poscur:near, cmblnk:near extrn msuinit:near, keybd:near, keycom:near, isfile:near, outch2:near extrn atoi:near, strlen:near extrn comnd:near, statc:near, replay:near, pntchr:near, pntflsh:near assume cs:code, ds:data, es:nothing ; do initialization local to this module ; Dynamically allocates 4000 bytes for screen save/restore buffer plus ; 320 to 38400 bytes for screen scroll back buffers. Tries to leave space ; for Command.com before enlarging buffers. [jrd] lclyini proc near mov ax,ipage_seg ; the interrupt page mov es,ax mov es,word ptr es:mtr_ds ; find monitor data segment here cmp es:MTR_VER,25 ; Must be higher than Version 2.5 jnl lclyini1 mov ah,prstr ; Tell user and abort mov dx,offset mtrmsg int dos mov ah,4ch int dos lclyini1:mov ax,word ptr es:FORE ; get current colors mov word ptr doscol,ax ; save it in al,VID_CMD ; Get the current video status. mov dosattr,al ; Save it. mov al,VID_NOR ; Set up video to normal out VID_CMD,al ; suit us, normally all colors active call msuinit ; initialize keyboard module msuxxx mov al,1 ; underscore call csrtype ; turn on underline cursor ; call getpos ; get cursor position ; mov ax,1 ; underline cursor ; call setpos ; set cursor position and type ; screen roll back buffers mov al,crt_lins ; physical length of user area mul crt_cols ; physical width add ax,7 ; round up mov cl,3 shr ax,cl ; bytes/screen to paragraphs/screen mov si,ax ; save a copy in si mov bx,npages ; number of roll back screens wanted inc bx ; include current screen in count mul bx ; total number of screens wanted mov cx,ax ; save total wanted paragraphs in cx mov bx,0ffffh ; ask for all of memory, to get size mov ah,alloc ; allocate all of memory (must fail) int dos ; bx has # free paragraphs mov ax,bx ; ax has copy of number free paragraphs sub bx,26000D/16 ; space for Command.com copy #2 jc lclyin2 ; c = not enough for it cmp bx,si ; minimum roll back space left over? jle lclyin2 ; le = not even that much cmp bx,cx ; got vs wanted paras for roll back jle lclyin3 ; le = enough but not more than needed mov bx,cx ; limit to our actual needs jmp short lclyin3 ; ask for all we really want lclyin2:xor bx,bx ; use no space at all mov cx,bx ; remember this new request lclyin3:mov ah,alloc int dos mov tv_segs,PAR_GRN ; the green video plane holds it all mov tv_sego,0 ; and it starts at PAR_GRN:00 mov iniseg,ax ; (BDT) memory segment, window area mov inipara,bx ; save for later resizing of buffers cmp cx,bx ; paragraphs wanted vs delivered jae lclyin4 ; ae = enough mov ah,prstr mov dx,offset memerr ; say not enough memory to operate int dos mov flags.extflg,1 ; set Kermit exit flag lclyin4:call bufadj ; set roll back buffer parameters ; call vsinit ; init terminal emulator module MSZ ; mov bx,vtemu.att_ptr ; attributes pointer ; mov ah,dosattr ; startup video attributes ; and ah,not att_intensity ; emulation intensity to normal ; or ah,userbold ; mov [bx],ah ; set initial emulation attributes ret lclyini endp ; This is the terminal emulator. term proc near ; terminal mode entry point mov argadr,ax ; save argument ptr call argini ; init options from arg address call scrini ; init screen stuff or kbcodes,80h ; set need-to-init flg for kbd xtlator mov bx,portval ; port data structure address mov bx,[bx].flowc ; get flow control chars (bl=xoff) mov flowon,bh mov flowoff,bl ; save for later mov oldsp,sp ; remember stack for i/o failure, ; used by procedure endcon mov fairprn,0 ; set printer buffer flush counter lp: call prtchr ; char at port? jnc short lpinp ; nc = yes, go handle cmp flags.comflg,2 ; check if S-100 ports ja lpkbd ; yes, go do it the simple way push bx mov bx,portval ; port structure address cmp [bx].portrdy,0 ; is port ready for business? pop bx jne lpkbd ; ne = ready jmp endcon ; end the communications now lpkbd: mov fairness,0 ; say kbd was examined inc fairprn ; inc printer dump counter cmp fairprn,1000 ; been here enough times now? jb lpkbd1 ; b = no cmp flags.comflg,2 ; check if S-100 ports ja lpkbd1 ; yes, this will delay us too much call pntflsh ; flush printer buffer mov fairprn,0 ; reset for next time lpkbd1: call keybd ; call keyboard translator in msu jnc lp ; nc = no char or have processed it jmp short quit ; carry set = quit connect mode lpinp: and al,parmsk ; apply 8/7 bit parity mask call outtty ; print on terminal inc fairness ; say read port but not kbd, again cmp fairness,100 ; this many port reads before kbd? jb lp ; b = no, read port again jmp short lpkbd ; yes, let user have a chance too quit: mov ah,scbattr ; current emulator attributes mov savattr,ah ; save them here call pntflsh ; flush printer buffer call getpos ; get cursor position into dx mov cursor,dx ; save position mov al,1 ; underscore call csrtype ; turn on underline cursor cmp flags.vtflg,0 ; terminal type of none? je quit1 ; e = yes cmp flags.modflg,2 ; is modeline owned by remote host? je quit1 ; e = yes call clrmod ; clear it before storing screen quit1: call savescr ; save screen mov dh,byte ptr low_rgt+1 ; bottom line xor dl,dl ; left most column call setpos ; set cursor position mov dx,word ptr doscol ; set color back to dos values xchg dl,dh ; get the sequence right call setcol mov al,VID_NOR ; reset video port out VID_CMD,al mov al,yflags and al,not lclecho ; don't copy host's echo flag mov bx,argadr mov ah,[bx].flgs ; get user's flag settings and ah,lclecho ; clear all but local echo bit or [bx].flgs,al ; update flags in arg block ret term endp argini proc near ; read passed arguments mov bx,argadr ; base of argument block mov al,[bx].flgs ; get flags and al,capt+emheath+trnctl+lclecho+modoff mov yflags,al ; mask for allowable and save mov al,[bx].prt mov portno,al ; update port number mov crt_lins,ROWS ; init # of rows 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 argini1 ; e = yes, keep all 8 bits mov parmsk,07fh ; else keep lower 7 bits argini1:ret ; that's it argini endp scrini proc near ; init screen stuff mov dx,word ptr tercol ; set terminal color xchg dl,dh ; get the sequence right call setcol call clrmod ; clear mode line test yflags,modoff ; is mode line disabled? jnz scrin1 ; yes, skip it call modlin ; turn on mode line scrin1: cmp flags.vtflg,0 ; terminal type of None? ja scrin3 ; a = no, emulating ;some code? scrin3: in al,VID_CMD ; Get the current video status. mov savattr,al ; Save it. mov scbattr,al ; Here too mov dx,cursor ; use old cursor, if any call restscr ; restore screen, if any saved call setpos ; set cursor position or flags1,inited ; remember we've run already cmp flags.vtflg,0 ; current terminal type = None? je scrin13 ; e = yes, nothing to init cmp vtclear,2 ; screen need clearing? jae scrin10 ; ae = yes, do emulator reinit now cmp vtinited,inited ; inited emulator yet? je scrin11 ; e = yes scrin10:call vtinit ; init it now jmp short scrin13 scrin11: ; call ansrei ; reinit the emulator scrin13:mov ax,flags.vtflg ; current terminal type mov trmtyp,ax ; place to remember it til next time mov vtclear,0 ; say screen is updated ret scrini endp ; Routine to initialize VT102/52/Heath-19 terminal emulator. vtinit proc near mov holdscr,0 ; clear holdscreen mov ah,conout mov dl,ESCAPE ; Take the int dos ; Z-100 mov dl,'y' ; terminal int dos ; out of mov dl,'3' ; holdscreen int dos ; mode or vtinited,inited cmp flags.vtflg,0 ; doing emulation? je vtinix ; e = no mov bx,argadr ; address of argument block mov dl,[bx].flgs and dl,lclecho ; local echo flag and yflags,not lclecho or yflags,dl mov dl,[bx].baudb ; baud rate code in dl mov dh,[bx].parity ; parity code in bits mov cl,4 ; 0-3 of dh shl dh,cl or dh,07H ; just say 7 data bits test flags.remflg,d8bit ; eight bit display? jz vtini1 ; z = no inc dh ; set low four bits to value 8 vtini1: ; call ansini ; call startup routine vtinix: clc ret vtinit endp trnprs: push ax ; toggle ^ PrtSc screen to printer test flags1,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,prnhand ; file handle for Connect printing int dos pop bx jc trnpr1 ; c = printer not ready cmp al,0ffh ; Ready status? je trnpr2 ; e = Ready trnpr1: call vtbell ; Not Ready, complain jmp trnpr3 ; and ignore request trnpr2: xor flags1,prtscr ; flip the flag test yflags,modoff ; mode line off? jnz trnpr3 ; nz = yes call modlin ; else rewrite mode line call pntflsh ; print the last of printer buffer trnpr3: pop ax clc ; return carry clear (don't quit) ret ; Put the character in al to the screen. ; Monitor rom calls used in emulator mode for speed reasons. ; The Z-100 screen is very slow in the handling of esc E and esc J; ; if esc E or esc J and S-100 modem, trap these and do it our own way ; while polling port in order to avoid loosing characters at port. ; The esc sequencies esc x ?, esc y ? and esc y @ are trapped and defused ; as these would either lock up the keyboard or interfere with the function ; of the keys. outtty proc near cmp escflg,true ; Esc last time? jl outtt04 ; No, but maybe this time jz outtt01 ; Yes jmp outtt31 ; No, but earlier outtt01:cmp al,'=' ; Is it =? jnz outtt02 ; No, go on mov ansflgs,deckpam ; Yes, it is application keypad mode or vtemu.vtflgop,deckpam ; here too mov modbuf.m_pad,'A'; A for Application mov padflg,true ; Keypad mode changed jmp outtt03 outtt02:cmp al,'>' ; Is it >? jnz outtt1 ; No, go on mov ansflgs,false ; Yes, it is numeric keypad mode and vtemu.vtflgop,not deckpam mov modbuf.m_pad,'N'; N for Numeric mov padflg,true ; Keypad mode changed outtt03:mov escflg,false ; reset jmp outtt4 ; Go display it outtt04:cmp al,ESCAPE ; Esc now? jnz outtt05 ; No mov escflg,true outtt05:jmp outtt4 ; Go display it outtt1: inc escflg ; Count cmp escflg,true jnz outtt11 mov escflg,false ; reset outtt11:cmp al,ESCAPE ; Esc now? jnz outtt2 ; No, just go on mov escflg,true ; Yes, set escflg to 1 outtt2: cmp al,'x' ; Yes, set modes? jz outtt05 ; Yes, just deliver cmp al,'y' ; Reset modes? jz outtt05 ; Yes, just deliver mov escflg,false ; reset cmp flags.comflg,2 ; check if S-100 ports jle outtt4 ; no, go do it the simple way cmp al,'E' ; Is it E? jz outtt3 ; Yes, go handle cmp al,'J' ; Is it J? jnz outtt4 ; No, go write the character push ax ; Need this later jmp short outtt3a ; Have ESC J outtt3: push ax ; Yes, we have ESC E mov ah,conout ; break it up into smaller parts, mov dl,'H' ; first, home cursor (ESC was sent before) int dos mov dl,ESCAPE ; Send ESC again (first part of ESC j) int dos outtt3a: ; This is where we handle ESC J mov cx,1 ; No delay for sprtch call sprtch ; Go get possible char at port mov ah,conout mov dl,'j' ; Save cursor position (ESC was sent before) int dos mov ah,prstr mov dx,offset eeolstr ; Clear to the end of the current line int dos call getpos ; Get cursor position xor dl,dl ; Column 0 cmp dh,23 ; Line 23 = the 24th line? jae outtt3d ; Yes, we are at 23 or 24 (24th or 25th), done push dx ; Save cursor position outtt3b:pop dx ; Get cursor inc dh ; Next line cmp dh,24 ; Will this one be line 24, the 25th line jae outtt3c ; Yes, done push dx ; Save it again mov cx,1 ; No delay call sprtch ; Go get possible char at port pop dx ; Get cursor back push dx ; Save it again call poscur ; Set cursor to beginning this new line mov ah,prstr mov dx,offset eeolstr ; Clear to the end of the current line int dos jmp short outtt3b outtt3c:mov dx,offset precur; Set cursor to 'original' position int dos outtt3d:mov escflg,false ; reset jmp outtt5 outtt31:mov escflg,false ; reset cmp al,'?' ; key expansion? jz outtt32 ; yes, inhibit it cmp al,'@' ; event driven? jnz outtt4 ; no, just deliver outtt32:xor al,al ; put something harmless in outtt4: push ax ; Need it later test flags.remflg,d8bit ; keep 8 bits for displays? jnz outtt40 ; nz = yes, 8 bits if possible and al,7fh ; Strip parity outtt40:test yflags,emheath ; Are we using emulation? jnz outtt41 ; Yes, go on, do it fast ; No, use dos to allow term. device driver mov dl,al ; We need it here mov ah,conout ; Write char in dl ; This may loose int dos ; do it ; characters jmp outtt5 outtt41:mov ah,chr_write ; Write char in al ; This is faster ; call bios_confunc ; Do it fast call MTR_SCRT ; Do it very fast outtt5: pop ax ; Restore char test yflags,capt ; capturing output? jz outtt7 ; no, forget it cmp flowoff,0 ; Are we doing flow control je outtt6 ; No, just continue cmp caplft,1 ; yes, one more space left in capture buffer? jnz outtt6 ; no, give it the char push ax ; yes, send xoff first mov bx,portval mov ax,[bx].flowc ; ah gets xon al gets xoff call outpr1 cmp flags.comflg,2 ; check if S-100 ports jle outtt51 ; no, go do it the simple way mov cx,delaycount ; delay to ensure that, in spite of possible call sprtch ; slow link, xoff is in effect outtt51:pop ax ; get char back push ax ; save it again call captrtn ; give it the captured char mov bx,portval mov ax,[bx].flowc ; ah gets xon al gets xoff mov al,ah call outpr1 pop ax jmp outtt7 outtt6: call captrtn outtt7: test flags1,prtscr ; print screen? jz outtt8 ; no, keep going call pntchr ; queue char for printer jnc outtt8 ; nc = successful print push ax call beep ; else make a noise and call trnprs ; turn off printing pop ax outtt8: test padflg,true ; no, has keypad mode been changed? jz outtt9 ; no, skip it test yflags,modoff ; is mode line disabled? jnz outtt9 ; yes, skip it call dispad ; yes, display keypad mode mov padflg,false ; reset flag outtt9: ret outtty endp ; display the keypad mode information on the mode line dispad proc near mov ah,prstr ; print string mov dx,offset savcur ; save cursor position int dos mov dx,offset begrev ; reverse video int dos mov dx,offset padpos ; position cursor int dos mov dl,modbuf.m_pad ; this is it mov ah,conout int dos mov ah,prstr mov dx,offset endrev ; normal video int dos mov dx,offset precur ; reposition cursor int dos ret dispad endp ; general character out for emulator chrout: cmp flags.vtflg,0 ; emulating? je chrou5 ; e = no ; call anskbi ; say we had keyboard input cmp al,cr ; CR? jne chrou5 ; ne = no, just output it and return test vtemu.vtflgop,anslnm ; ANSI new-line mode set? jz chrou5 ; z = no, just send the cr cmp dupflg,0 ; full duplex? je chrou4 ; e = yes cmp al,trans.seol ; End of Line char? jne chrou5 ; ne = no chrou4: mov ah,trans.seol ; save eol char push ax ; save on stack mov trans.seol,lf ; make LF the eol char call outprt ; output a carriage-return mov al,lf ; followed by a line feed call outprt ; send the LF pop ax mov trans.seol,ah ; restore eol char ret chrou5: jmp outprt ; send the character in al out to the serial port; handle echoing. ; Can send an 8 bit char while displaying only 7 bits locally. outprt proc near prtbout label near ; label used in msz test yflags,lclecho ; echoing? jz outpr1 ; z = no, forget it push ax ; save char call outtty ; print it pop ax ; restore OUTPR1: mov ah,al ; outpr1 entry point used for no echo ; sending of char in al call outchr ; output to the port jc outpr3 ; c = failure ret OUTPR2: mov ah,al ; outpr2 entry point used for no echo ; no flow control sending of char call outch2 ; output to the port, no flow control jc outpr3 ; c = failure ret outpr3: jmp endcon ; failure, end connection outprt endp ; Toggle Mode Line trnmod proc near cmp flags.modflg,1 ; mode line enabled and owned by us? jne trnm1 ; ne = no, don't touch it test yflags,modoff ; mode line already off? jnz trnm2 ; nz = yes, go turn on or yflags,modoff ; say modeline is toggled off call clrmod ; clear mode line trnm1: clc ; clear c bit so don't exit Connect ret trnm2: cmp flags.vtflg,0 ; emulating a terminal? jne trnm3 ; ne = yes push dx ; scroll screen to save bottom line mov ah,prstr ; for terminal type none mov dx,offset crlf int dos pop dx trnm3: call modlin ; turn on modeline and yflags,not modoff ; say modeline is not toggled off clc ret trnmod endp modlin proc near ; turn on mode line push es mov al,trans.escchr mov modbuf.m_echr,' ' ; first char is initial space mov modbuf.m_hlp,' ' ; goes here too. cmp al,32 ; printable? jnb modl0 ; yes, keep going add al,40h ; made printable mov modbuf.m_echr,'^' ; note control char mov modbuf.m_hlp,'^' modl0: mov modbuf.m_echr+1,al ; fill in character mov modbuf.m_hlp+1,al mov bx,argadr ; get argument block mov al,[bx].baudb ; get baud bits mov si,offset unkbaud ; assume unknown baud cmp al,baudnsiz ; too big? jnb modl3 ; yes, use default shl al,1 ; each is 4 bytes long... shl al,1 mov ah,0 add ax,offset baudn cmp flags.comflg,2 ; com1/com2? jna modl2 ; yes, jump add ax,5*4 ; no, starts 5 rates higher modl2: mov si,ax modl3: mov cx,size m_baud ; length of baud space mov di,offset modbuf.m_baud push ds pop es cld rep movsb ; copy in baud rate mov al,[bx].parity ; get parity code shl al,1 ; each is 4 bytes long... shl al,1 mov ah,0 add ax,offset parnams ; names of parity settings mov si,ax mov cx,4 ; each is 4 long mov di,offset modbuf.m_par rep movsb mov si,offset remmsg ; assume remote echoing test yflags,lclecho ; echoing? jz modl4 ; no, keep going mov si,offset lclmsg modl4: mov cx,3 ; size of Rem & Lcl mov di,offset modbuf.m_echo rep movsb cmp flags.comflg,1 ; port 1 (port B)? mov al,'B' ; enter 'B' je modl5 ; yes, keep going cmp flags.comflg,3 ; port 3 (S-100 port 1) mov al,'3' ; enter '3' je modl5 ; yes, keep going cmp flags.comflg,4 ; port 4 (S-100 port 2) mov al,'4' ; enter '4' je modl5 ; yes, keep going mov al,'A' ; then must be port 2 (port A)! modl5: mov modbuf.m_prt,al ; fill in port number mov cx,3 ; size of PRN mov di,offset modbuf.m_prn test flags1,prtscr ; print screen? mov si,offset prmsg ; printer on msg jnz modl6 ; yes, prepare to display it add si,3 ; no, print blank modl6: rep movsb mov cx,10 ; size of leds mov di,offset modbuf.m_emul test yflags,emheath ; are we using Heath-19 emulation? mov si,offset noleds ; "None" message jz modl7 ; no, prepare to display it mov si,offset h19leds ; Heath-19 emulation modl7: rep movsb mov modbuf.m_pad,'N' ; N for Numeric test ansflgs,deckpam ; are we in keypad application mode? jz modl8 ; no, leave the blank in mov modbuf.m_pad,'A' ; A for Application modl8: mov cx,size modfrm ; this is size of mode line mov si,offset modbuf ; mode line image mov dx,offset modbuf call putmod pop es ret ; and return modlin endp ; Invoked by keyboard translator when an unknown keyboard verb is used as ; a string definition, such as {\ktest}. Enter with vtmacname pointing to ; uppercased verb name, asciiz, and vtmaclen set to its length. extmacro proc near jmp short vtmacro extmacro endp ; ; Reference Macro structure for db number of entries (mac names) ; is file table mcctab |-> db length of macroname, excl '$' ; mssset.asm each entry |-> db 'macroname','$' ; where these |-> dw segment:0 of definition string ; are stored. (offset part is always 0) ; Definition string in db length of ; buffer macbuf db 'string with trailing null' ; vtmacro proc far ; common code for macros vtsmac,vtrmac push bx ; and Product push cx push si push di push es mov ax,ds mov es,ax mov di,offset rdbuf+1 ; macro def buffer starts here mov si,vtmacname ; pointer to macro name mov cl,vtmaclen ; length of macro nametext xor ch,ch mov [di-1],cl ; counted string field cld rep movsb ; copy to rdbuf mov byte ptr [di],0 ; null terminator mov si,offset rdbuf+1 ; look for name-text separator mov cl,vtmaclen xor ch,ch vtmac1: lodsb cmp al,' ' ; space separator? je vtmac1a ; e = yes, stop here or al,al ; null terminator? jz vtmac1a ; e = yes, stop here loop vtmac1 inc si ; to do null lenght correctly vtmac1a:sub si,offset rdbuf+1+1 ; compute length of macro name mov cx,si mov vtmaclen,cl ; save a macro name length ; check for existence of macro mov bx,offset mcctab ; table of macro names mov cl,[bx] ; number of names in table xor ch,ch jcxz vtmacx ; z = empty table, do nothing inc bx ; point to length of first name vtmac2: mov al,[bx] ; length of this name xor ah,ah cmp al,vtmaclen ; length same as desired keyword? jne vtmac3 ; ne = no, search again mov si,bx inc si ; point at first char of name push cx ; save name counter push di ; save reg mov cl,vtmaclen ; length of name, excluding '$' xor ch,ch mov di,vtmacname ; point at desired macro name push es ; save reg push ds pop es ; make es use data segment cld repe cmpsb ; match strings pop es ; need current si below pop cx pop di ; recover saved regs je vtmac4 ; e = matched vtmac3: add bx,ax ; step to next name, add name length add bx,4 ; + count, dollar sign, def word ptr loop vtmac2 ; try next name vtmacx: pop es pop di pop si ; no macro, return to Connect mode pop cx pop bx ret vtmac4: cmp taklev,maxtak ; room in Take level? jge vtmacx ; ge = no, exit with no action inc taklev ; increment take level add takadr,size takinfo ; make a new Take entry/macro mov bx,takadr ; point to current macro structure mov ax,ds ; segment of rdbuf mov [bx].takbuf,ax ; segment of definition string struc mov cl,rdbuf ; length of whole string xor ch,ch mov [bx].takcnt,cx ; number of chars in definition mov [bx].takargc,0 ; our argument count mov [bx].takptr,offset rdbuf+1 ; where to read next command char mov [bx].taktyp,0ffh ; flag as a macro pop es pop di pop si pop cx pop bx jmp endcon ; exit Connect mode vtmacro endp ; Error recovery routine used when outchr reports unable to send character ; or when vtmacro requests exiting Connect mode. ; Exit Connect mode cleanly, despite layers of intermediate calls. endcon proc near mov kbdflg,'C' ; report 'C' to TERM's caller mov sp,oldsp ; recover startup stack pointer ; TERM caller's return address is now ; on the top of stack. A longjmp. jmp quit ; exit Connect mode cleanly endcon endp ; Clear all User Definable Keys, deallocate memory for their definitions udkclear proc near push ax push bx push cx push es mov cx,17 ; 17 entries xor bx,bx udkcle1:mov ax,udkseg[bx] ; segment of definition or ax,ax ; segment defined? jz udkcle2 ; z = no, try next key mov es,ax mov udkseg[bx],0 ; clear the entry mov ah,freemem ; release the memory int dos udkcle2:add bx,2 ; word index loop udkcle1 ; do all pop es pop cx pop bx pop ax clc ret udkclear endp ; Determine screen roll back buffer parameters depending on current screen ; dimensions and available memory. Each rollback screen line has its own ; segment (lines start on segment boundaries for rollback). bufadj proc near push bx push cx push dx mov lxtra,0 ; assume no storage for "extra" lines xor bh,bh ; (BDT) get bytes / line mov bl,crt_cols ; (BDT) physical line width add bx,7 ; (BDT) round up to paragraph boundary mov cl,3 ; (BDT) now convert to shr bx,cl ; (BDT) paragraphs / line mov ppl,bx ; (BDT) save this in buffer area mov ax,inipara ; (BDT) compute the number of lines xor dx,dx div bx ; (BDT) in the buffer mov lmax,ax ; max line capacity of the buffer mov linee,ax ; (BDT) save as number of total lines or ax,ax ; is this zero? je bufadj1 ; e = yes, no space at all xor bh,bh ; (BDT) get lines / screen mov bl,byte ptr low_rgt+1 ; (BDT) rows on user/host screen inc bx ; (BDT) adjust for counting from 0 mov lxtra,bx ; (BDT) save as "extra" lines sub lmax,bx ; (BDT) deduct "extra" lines req'd jg bufadj1 ; g = have some rollback space mov lmax,0 ; say none mov lxtra,0 ; say none of these too bufadj1:mov lcnt,0 ; (BDT) # of lines filled in buffer mov linef,0 ; (BDT) first filled in line mov linec,0 ; (BDT) last filled in line pop dx pop cx pop bx ret bufadj endp ; Routine to set cursor type. Pass bits for cursor type in al: ; bit 0 set = 1 => Cursor on cleared = 0 => Cursor off ; bit 1 set = 2 => Block cursor cleared = 0 => Underline cursor ; bit 2 set = 4 => Non blinking cursor cleared = 0 => Blinking cursor ; Thus, in decimal form ; 0 = No cursor, 1 = Blinking underline cursor , 3 = Blinking block cursor ; 4 = No cursor, 5 = No blink underline cursor , 6 = No blink block cursor csrtype proc near mov byte ptr lincur,al ; remember type set push ax push dx ; save the reg mov ah,prstr test al,cur_on ; any cursor at all? jz csrty3 ; z=no, go put it out mov dx,offset enacurs ; enable cursor int dos mov dx,offset enablnk ; assume blink int dos test al,cur_nob ; non blinking? jnz csrty1 ; nz=no to no blink, leave as is mov dx,offset disblnk ; set blink off int dos csrty1: mov dx,offset enaunde ; assume underline int dos test al,cur_blo ; block? jz csrty2 ; z=no, leave as is mov dx,offset enabloc ; set block int dos csrty2: jmp short csrty4 csrty3: mov dx,offset discurs ; disable cursor int dos csrty4: pop dx pop ax ret csrtype 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 ; dumpscr dumps sreen to file push ax push bx push cx push dx push di push si push es ; Open and prepare screen dump file mov dmphand,-1 ; preset illegal handle mov dx,offset dmpname ; name of disk file, from mssset mov ax,dx ; where isfile wants name ptr call isfile ; what kind of file is this? jc dmp1 ; c = no such file, create it test byte ptr filtst.dta+21,1fh ; file attributes, ok to write? jnz dmp2 ; nz = no, indicate open failure mov al,1 ; writing mov ah,open2 ; open existing file int dos jc dmp2 ; c = failure, indicate open failure mov dmphand,ax ; save file handle mov bx,ax ; need handle here mov cx,0 ; setup file pointer mov dx,0 ; to end of file mov al,2 ; seek the end mov ah,lseek int dos jc dmp2 ; failure, indicate open failure jmp short dmp3 ; success dmp1: mov ah,creat2 ; file did not exist mov cx,20h ; attributes, archive bit int dos mov dmphand,ax ; save file handle jnc dmp3 ; nc = ok dmp2: call beep mov ah,prstr ; print string mov dx,offset dmperr ; cannot open file int dos jmp short dmp8 ; Failure, exit dmp3: call rdset ; Set up for screen reading dmp4: call rdlne ; Read a screen line call endfix ; Fix end of line and srceen ; Write out the line dmp5: mov dx,offset line ; array to be written mov bx,dmphand ; need file handle mov ah,write2 ; write the line int dos jc dmp6 ; Go if trouble. cmp cx,ax ; Write as many bytes as requested? jnz dmp6 ; Go if trouble. cmp eos,1 ; End of screen? je dmp7 ; If yes, go. mov ax,int_cy ; Else get the line index and set the shl al,1 ; pointer to the next line of screen shl al,1 ; data. shl al,1 mov bh,al jmp short dmp4 ; Now loop back, do another line dmp6: call beep ; Error writing file mov ah,prstr ; print string mov dx,offset dmperr1 ; The message int dos dmp7: mov ah,close2 ; close the file now mov bx,dmphand ; file handle int dos mov al,vstate ; Restore the original video port out VID_CMD,al ; state. dmp8: pop es pop si pop di pop dx pop cx pop bx pop ax ret ; Done with screen: return. DUMPSCR ENDP ; Local routine rdset to set up for screen buffer reading. Modifies ax, bx ; and es and enables acces to video memory. RDSET: cld ; Clear direction indicator. mov eos,0 ; Initialize end of screen flag to NO mov lines,ROWS ; Assume 24 lines on the screen. mov ax,IPAGE_SEG ; The interrupt page mov es,ax ; Fetch the variable containing the mov es,es:[MTR_DS] ; status of the 25th line: cmp byte ptr es:[STATUS],0 ; 00= disabled, FF= enabled. je rdset1 inc lines ; Set number of lines on screen to 25. rdset1: in al,VID_CMD ; Get the current video status. mov vstate,al ; Save it. mov al,78h ; Enable access to the memory. out VID_CMD,al mov ax,PAR_GRN ; Address the green plane, which is mov es,ax ; where the characters are stored. mov int_cy,0 ; Start at line 0 on the screen. xor bh,bh ret ; Local routine rdlne to read a screen line. Enter with es pionting to ; the monitor interrup page. Modifies ax, bx, si and di. RDLNE: mov bl,COLUMNS-1 ; Offset of the last character. mov di,COLUMNS-1 ; Offset to the end of the line. xor si,si ; Show no non-spaces found yet. rdlne1: mov al,es:[bx+9*128] ; Get the character's font index. add al,' ' ; Then make it into the character. cmp al,' ' ; Is the character a space? jne rdlne2 ; If not, go. and si,si ; Any non-space found yet? jz rdlne3 ; If no, go. rdlne2: mov line[di],al ; Save the character. and si,si ; Non-space found yet? jnz rdlne3 ; If yes, just go. lea si,[di+1] ; Else keep the offset to the non-space. rdlne3: dec bl ; Go to next character. dec di ; Decrement the offset to the line. jge rdlne1 ; Repeat this sequence for all chars. ret ; Reached the end of line: ; Local routine to add cr and lf at the end of each line and ff at the ; end of each page. Modifies ax and cx. Returns with number of chars ; in line buffer in cx. endfix: mov byte ptr line[si],CR ; Put in a CR mov byte ptr line[si+1],LF ; Put in a LF lea cx,[si+2] ; Set up the counter. inc int_cy ; Up index to the next line and then mov ax,int_cy ; get it. cmp ax,lines ; Are we at the end of screen? jne endfix1 ; If not, go. mov byte ptr line[si+2],FF ; Else store form feed for end of page. inc cx ; Up length to print. mov eos,1 ; Turn on the end-of-screen flag. endfix1:ret ; Save the entire screen in a buffer so we can restore it. ; Saves regular (80x25) screens to memory buffer allocated dynamically from ; DOS. Save address is savadr+2:savadr (seg:offset). A memory buffer is ; allocated as required. savescr proc near push ax push bx push cx push dx push si push di push es mov ax,low_rgt ; text screen lower right (typ 23,79) add al,3 ; plus 1 col, cr, lf add ah,2 ; plus 1 row plus status line mul ah ; times rows = characters on screen inc ax ; plus the last one, ff mov dx,ax ; save number of screen bytes in dx mov ax,savadr+2 ; seg of saved memory, if any or ax,ax ; none? jnz savsc4 ; no, there is some ; allocate and use DOS memory for save savsc1: mov bx,dx ; bytes to do add bx,16 ; round up mov cl,4 shr bx,cl ; bytes/screen to paragraphs/screen mov ah,alloc ; allocate memory int dos ; bx has # free paragraphs jc savsc2 ; c = not enough for it, skip mov savadr+2,ax ; working seg address for restore jmp short savsc4 savsc2: mov savadr+2,0 ; then say no seg because no save jmp short savsc7 ; exit without saving screen ; save the screen savsc4: mov savadr,0 ; no offset for memory buffer mov cx,dx ; number of screen bytes call rdset ; Set up for screen reading savsc5: call rdlne ; Read screen line call endfix ; Add cr, lf and possibly ff mov ax,savadr+2 ; Reached the end of line: push es mov es,ax ; Segment for buffer mov si,offset line ; Array to be written mov di,savadr ; We are here in buffer cld rep movsb pop es mov savadr,di ; Save it for next line cmp eos,1 ; End of screen? je savsc6 ; If yes, go. mov ax,int_cy ; Else get the line index and set the shl al,1 ; pointer to the next line of screen shl al,1 ; data. shl al,1 mov bh,al jmp short savsc5 ; Now loop back, do another line savsc6: mov al,vstate ; Restore the original video port out VID_CMD,al ; state. savsc7: pop es pop di pop si pop dx pop cx pop bx pop ax ret savescr endp ; Restore screen from buffer (savadr+2:savadr, with number to write in savadr). ; Restores all screen lines. restscr proc near push ax push bx xor ax,ax ; upper left corner mov bx,low_rgt call atsclr ; blank screen mov bx,dx ; holds cursor position mov dx,ax ; upper left corner call poscur ; set it cmp savadr+2,0 ; saved anything yet? mov dx,ax ; restore it je restsc2 ; e = no push cx push bx ; this is in reality dx, cursor push si push di push es mov cx,savadr ; this many bytes to write sub cx,3 ; but skip last cr,lf and ff mov ax,savadr+2 ; get segment for buffer mov es,ax ; into es xor si,si ; offset zero for first char restsc1:mov al,byte ptr es:[si] ; get char push cx ; MTR_SCRT messes up ax, bx, cx, dx, push si ; si, di and es, so we assume this call MTR_DCRT ; one is as bad. pop si pop cx mov ax,savadr+2 ; get segment for buffer mov es,ax ; into es inc si ; next char loop restsc1 pop es pop di pop si pop dx pop cx restsc2:pop bx pop ax ret restscr endp ; Read cursor position ; DL = column, DH = row, both counted from 0,0 at upper left corner getpos proc near push bx push es mov bx,IPAGE_SEG ; the interrupt page mov es,bx mov es,word ptr es:MTR_DS ; find monitor data segment here mov dl,byte ptr es:MTR_HORP ; column 0 to 79 mov dh,byte ptr es:MTR_VERP ; row 0 to 24 pop es pop bx ret getpos endp ; Screen clearing routine atsclr. ; ; Call: ax/ coordinates of first screen location to be cleared. ; bx/ coordinates of last location to be cleared. ; Coord: ah = row [0-24], al = column [0-79]. Preserves all registers. ATSCLR PROC NEAR push ax push bx push cx push dx push si push di push bp push es push ds mov cx,IPAGE_SEG ; Get into es mov es,cx mov ds,es:[MTR_DS] ; Now get MTR_DS into ds and the mov bp,offset es:MTR_EDC ; offset to the dword into bp mov cx,ax ; Top left corner mov cl,ch ; Top line to cl xor ch,ch ; Top line now in cx push cx ; * First parameter mov cl,al ; Left column now in cx push cx ; ** Second parameter sub bh,ah ; Line count inc bh ; adjust sub bl,al ; Char count inc bl ; adjust atsclr1:push bx ; *** Third parameter in bl (and bh) call dword ptr ds:[bp] ; Do a line sub sp,2 ; -2 ; Point to first parameter, line pop cx ; 0 ; Get it inc cx ; Go to the next line push cx ; -2 ; Put it back into stack sub sp,4 ; -6 ; The next param, left column, is ok pop bx ; -4 ; But we will check on the line count dec bh ; which we sneaked into here jnz atsclr1 ; If more lines left, do it again add sp,4 ; 0 ; Don't waste time popping this junk pop ds pop es pop bp pop di pop si pop dx pop cx pop bx pop ax ret ATSCLR ENDP ; Routine to do close to VT100-style bell, no arguments vtbell proc near cmp belltype,1 ; visual bell? je vtbell1 ; e = yes call beep ret vtbell1: in al,VID_CMD ; Get the current video status. mov ah,al ; Save it. mov al,0f0h ; Make screen all white out VID_CMD,al ; Do it push ax mov ax,40 ; for 40 milliseconds call pcwait pop ax mov al,ah ; Get old status back out VID_CMD,al ; Do it ret vtbell endp comment @ ; This routine is called when we want to reverse everything on the screen ; from normal to reverse video, or vice versa. It is called only when ; the decscnm attribute is changed. Preserves all registers. ; Call: no arguments. ; This will work on graphics as well as text. However, this is a true ; reverser meaning that ALL 'dark bits' will be 'lit upp' all 'lit up' ; ones will be 'darkened'. This means for example that the reverse of ; yellow (green + red) on black (none) will be blue on white (all = ; blue + green + red). revscn proc near push ax push cx push si push di push ds push es in al,VID_CMD ; Get video port status push ax ; Save it mov al,7fh ; Turn off multiple access out VID_CMD,al ; and display mov ax,PAR_GRN ; Green first revscn0:mov ds,ax ; Set up mov es,ax ; all xor si,si ; the mov di,si ; pointers mov bx,8000h ; The whole plane mov cx,40 ; One line mov dx,9 ; 9 scan lines per char cld revscn1:lodsw xor ax,0ffffh stosw loop revscn1 ; A full scan line dec dx ; done jnz revscn2 ; A full char line? add si,7*128 ; Yes, skip the mov di,si ; 7 next lines sub bx,7*64 ; and adjust count mov dx,9 ; Prepare for next char line revscn2:sub bx,64 ; Plane done? jz revscn3 ; z = yes, plane done add si,48 ; no, skip the non displayed mov di,si ; last 48 mov cx,40 ; Prepare for next scan line jmp short revscn1 ; and go do it revscn3:mov ax,ds ; Have we done cmp ax,PAR_BLU ; the blue? jz revscn5 ; Yes, all done, almost sub ah,10h ; Go do next plane jmp short revscn0 revscn5:pop ax ; Restore video out VID_CMD,al ; status pop es pop ds pop di pop si pop cx pop ax ret revscn endp end comment @ ; This is revscn which reverses the color attributes of characters currently ; displayed on the video screen. It will only work on text and graphic ; characters. Takes no arguments, preserves all registers. REVSCN PROC NEAR push ax push bx push cx push dx push si push di push bp push es push ds in al,VID_CMD ; Read video state push ax ; Save it mov al,01111000b ; Mask current write bits, enable vram out VID_CMD,al ; Set up mov ax,IPAGE_SEG ; Interrupt page mov es,ax ; into es mov bp,offset es:MTR_DFC mov ds,es:[MTR_DS] ; Monitor data segment mov es,es:[MTR_DS] ; Monitor data segment xor cx,cx ; Char index 0 revscn1:push cx ; Preserve around call to mtr rom push es ; This too mov ax,cx ; Index here mov bl,COLUMNS div bl ; Line now in al and column in ah mov bh,al ; Line in bh mov bl,ah ; Parameter 1, column, in bl push bx ; * Parameter # 1 set xchg bh,bl ; Parameter 2, line, from bh to bl push bx ; ** Parameter # 2 set xchg bh,bl ; Get right order back mov ax,PAR_GRN ; Point to green plane mov es,ax shl bh,1 shl bh,1 shl bh,1 mov al,es:byte ptr [bx+9*128] ; Char index mov ah,es:byte ptr [bx+10*128] ; Char attributes push ax ; *** Third param, al holds char index mov dh,ah and dh,111b ; Foreground color mov dl,ah shr dl,1 shr dl,1 shr dl,1 and dl,111b ; Background color cmp cs:tempcol,dx ; New color or fresh start? jz revscn2 ; No, just skip all of this mov cs:tempcol,dx ; Remember color xchg dh,dl ; Reverse it call setcol ; Set the reversed color revscn2:mov ax,0 push ax ; **** Fourth, display it as is call dword ptr ds:[bp] ; Display char pop es ; Get these pop cx ; back inc cx cmp byte ptr es:[STATUS],0 ; Status line not on? jz revscn3 ; No, go do 24 lines cmp cx,COLUMNS * (ROWS + 1) ; < 80 * (24 + 1) = 2000? jb revscn1 ; Yes, go do next char revscn3:cmp cx,COLUMNS * ROWS ; < 80 * 24 = 1920? jb revscn1 ; Yes, go do next char pop cx ; No, all done, almost out VID_CMD,al ; Restore video mov cs:tempcol,0ffffh ; Reset for next time pop ds pop es pop bp pop di pop si pop dx pop cx pop bx pop ax ret tempcol dw 0ffffh ; Storage for the last set colors REVSCN ENDP ; Set cursor postion. Destroys dx. ; DL = column, DH = row, both counted from 0,0 at upper left corner setpos proc near jmp poscur setpos endp ; Set coloring attributes. ; Enter with AH holding current video attribute byte, ; BL holding ANSI color code (30-37 or 40-47) where 30's are foreground, ; 40's are background. ANSI colors are 1 = red, 2 = green, 4 = blue. ; Return new attribute byte in AH. setcolor proc near setcol0:cmp bl,30 ; ANSI color series? jb setcol7 ; b = no cmp bl,37 ; foreground set (30-37)? ja setcol4 ; a = no, try background set sub bl,30 ; take away the bias test bl,1 ; ANSI red? jz setcol1 ; z = no or ah,2 ; Z-100 red foreground bit setcol1:test bl,2 ; ANSI green? jz setcol2 ; z = no or ah,4 ; Z-100 green foreground bit setcol2:test bl,4 ; ANSI blue? jz setcol3 ; z = no or ah,1 ; Z-100 blue foreground bit setcol3:ret setcol4:cmp bl,40 ; background color set? jb setcol7 ; b = no cmp bl,47 ; background set is 40-47 ja setcol7 ; nb = no, not a color command sub bl,40 ; take away the bias test bl,1 ; ANSI red? jz setcol5 ; z = no or ah,10h ; Z-100 red background bit setcol5:test bl,2 ; ANSI green? jz setcol6 ; z = no or ah,20h ; Z-100 green background bit setcol6:test bl,4 ; ANSI blue? jz setcol7 ; z = no or ah,8h ; Z-100 blue background bit setcol7:ret setcolor endp ; Set screen color. Destroys dx. ; DH = foregroung color, DL = backgrond color per Z-100 standards. ; 0 = black, 1 = blue, 2 = green, 3 = cyan, 4 = red, 5 = magenta, ; 6 = yellow, 7 = white setcol proc near push ax push dx mov ah,conout mov dl,ESCAPE int dos mov dl,'m' int dos pop dx push dx mov dl,dh add dl,'0' int dos pop dx add dl,'0' int dos pop ax ret setcol endp ; Routine to do keyclick if flag is set, no arguments vclick proc near test vtemu.vtflgop,vskeyclick ; is keyclick flag on? jz vclick1 ; z = no, just return mov dl,keycli call keycom vclick1:ret vclick endp ;;; Action routines (verbs) for keyboard translator KEYBD in msuibm. ; These are invoked by a jump instruction. Return carry clear for normal ; processing, return carry set for invoking Quit (kbdflg has transfer char). uparrw: mov al,'A' ; cursor keys jmp short comarr dnarrw: mov al,'B' jmp short comarr rtarr: mov al,'C' test vtemu.vtflgop,vswdir ; writing left to right? jz comarr ; z = yes mov al,'D' ; reverse sense of keys jmp short comarr lfarr: mov al,'D' test vtemu.vtflgop,vswdir ; writing left to right? jz comarr ; z = yes mov al,'C' ; reverse sense of keys comarr: push ax ; save final char mov ttyact,0 ; network, group chars for packet test vtemu.vtflgop,decanm ; ANSI mode? jz comar2 ; z = no mov al,CSI ; CSI character test vtemu.vtflgop,decckm ; cursor key mode reset? jz comar1 ; z = yes mov al,SS3 ; SS3 character comar1: call out8bit ; send in 7 or 8 bit form jmp short comar3 comar2: mov al,escape ; do Heath/VT52 mode "ESC char" call prtbout comar3: pop ax ; recover final char mov ttyact,1 ; network, restore tty active flag call prtbout ret f0: mov al,'J' ; Z-100 function keys jmp short comf f1: mov al,'S' jmp short comf f2: mov al,'T' jmp short comf f3: mov al,'U' jmp short comf f4: mov al,'V' jmp short comf f5: mov al,'W' jmp short comf f6: mov al,'P' jmp short comf f7: mov al,'Q' jmp short comf f8: mov al,'R' jmp short comf f9: mov al,'I' jmp short comf0 f10: mov al,'J' jmp short comf0 f11: mov al,'K' jmp short comf0 f12: mov al,'L' jmp short comf0 sf0: mov al,'E' comf: mov ah,0 ; only one char jmp short comf_ sf1: mov al,'A' jmp short comf1 sf2: mov al,'B' jmp short comf1 sf3: mov al,'C' jmp short comf1 sf4: mov al,'D' jmp short comf1 sf5: mov al,'E' jmp short comf1 sf6: mov al,'F' jmp short comf1 sf7: mov al,'G' jmp short comf1 sf8: mov al,'H' jmp short comf1 sf9: mov al,'I' jmp short comf1 sf10: mov al,'J' jmp short comf1 sf11: mov al,'K' jmp short comf1 i_chr: cmp insert,'O' ; overwrite mode? mov insert,'O' jnz i_chr1 ; no, make it overwrite mov insert,'@' ; yes, make it insert i_chr1: mov al,insert jmp short comf d_chr: mov al,'N' jmp short comf i_line: mov al,'L' jmp short comf d_line: mov al,'M' jmp short comf comf0: mov ah,'0' ; second char is '0' jmp short comf_ comf1: mov ah,'1' ; second char is '1' comf_: push ax ; save final char mov ttyact,0 ; network, group chars for packet mov al,escape ; output ESC call prtbout pop ax ; get the saved char cmp ah,0 ; only one char? jz comf_1 push ax ; save it again xchg al,ah ; need ah first call prtbout pop ax ; get the saved char comf_1: mov ttyact,1 ; network, restore tty active flag call prtbout ret pf1: mov al,'P' ; keypad function keys PF1-4 jmp short compf pf2: mov al,'Q' jmp short compf pf3: mov al,'R' jmp short compf pf4: mov al,'S' compf: push ax ; save final char mov ttyact,0 ; network, group chars for packet test vtemu.vtflgop,decanm ; ansi mode? jz short compf1 ; z = no mov al,SS3 call out8bit ; send 7 or 8 bit version jmp short compf2 compf1: mov al,escape ; output ESC call prtbout compf2: pop ax ; get the saved char mov ttyact,1 ; network, restore tty active flag call prtbout ret kp0: mov al,'p' ; keypad numeric keys jmp short comkp kp1: mov al,'q' jmp short comkp kp2: mov al,'r' jmp short comkp kp3: mov al,'s' jmp short comkp kp4: mov al,'t' jmp short comkp kp5: mov al,'u' jmp short comkp kp6: mov al,'v' jmp short comkp kp7: mov al,'w' jmp short comkp kp8: mov al,'x' jmp short comkp kp9: mov al,'y' jmp short comkp kpminus:mov al,'m' jmp short comkp kpcoma: mov al,'l' jmp short comkp kpenter:mov al,'M' jmp short comkp kpdot: mov al,'n' comkp: test vtemu.vtflgop,deckpam ; keypad application mode active? jnz comkp1 ; nz = yes, use escape sequences sub al,40h ; deduct offset to numeric symbols push ax ; save final char jmp comkp3 ; and send that single char comkp1: push ax mov ttyact,0 ; network, group chars for packet test vtemu.vtflgop,decanm ; ANSI mode? jz comkp2 ; z = no mov al,SS3 ; SS3 character call out8bit ; send 7 or 8 bit version jmp comkp3 comkp2: mov al,escape ; output "ESC ?" call prtbout mov al,'?' call prtbout comkp3: pop ax ; recover final char mov ttyact,1 ; network, restore tty active flag call prtbout ; send it ret klogon proc near ; resume logging (if any) test flags.capflg,logses ; session logging enabled? jz klogn ; z = no, forget it or argadr.flgs,capt ; turn on capture flag or yflags,capt ; set local msy flag as well klogn: clc ret klogon endp klogof proc near ; suspend logging (if any) and argadr.flgs,not capt ; stop capturing and yflags,not capt ; reset local msy flag as well clc ret klogof endp snull proc near ; send a null byte xor al,al ; the null jmp prtbout ; send without logging and local echo snull endp ; output, no echo, 8-bit control chars as literals or "ESC char" form out8bit proc near mov ttyact,0 ; network, group chars for packet cmp flags.vtflg,ttvt320 ; VT320? jne out8bi1 ; ne = no cmp parmsk,7fh ; using parity? je out8bi1 ; e = yes test vtemu.vtflgop,vscntl ; doing 8-bit controls? jnz out8bi2 ; nz = yes, send 8-bit control char out8bi1:test al,80h ; in range for C1 controls? jz out8bi2 ; z = no cmp al,9fh ja out8bi2 ; a = no push ax mov al,escape ; send ESCAPE call prtbout pop ax sub al,40h ; compose second char out8bi2:mov ttyact,1 ; network, restore single char mode jmp prtbout ; send final char out8bit endp ; these commands invoke Quit cdos: mov al,'P' ; Push to DOS jmp short cmdcom cstatus:mov al,'S' ; Status jmp short cmdcom cquit: mov al,'C' ; Exit Connect mode jmp short cmdcom cquery: mov al,'?' ; Help jmp short cmdcom chang: mov al,'H' ; Hangup, drop DTR & RTS cmdcom: mov kbdflg,al ; pass char to msster.asm via kbdflg stc ; signal that Quit is needed ret ;SCROLL makes it possible to review the last screen (up to 26 lines). F11 ;invokes scroll and scrolling is done with BACK SPACE and LINE FEED keys. ;The RETURN key latches the screen in the new position, any other key restores ;to the original status. scroll proc near push ax push cx push dx push es mov ax,ipage_seg ; the interrupt page mov es,ax mov es,word ptr es:mtr_ds ; find monitor data segment here cmp byte ptr es:VRAM_SIZE,1 ; Must be 1 for 64k video chips jz scroll1 ; Yes, go on mov ah,prstr ; No, tell user, skip mov dx,offset vidmsg int dos jmp short scroll6 scroll1:mov dx,word ptr es:DISP_START ; get start address mov startad,dx ; save it scroll2:mov dx,word ptr es:DISP_START ; get start address sub dx,80 ; assume 1 line backwards cmp al,10 ; line feed ^J jnz scroll3 ; no, backwards add dx,160 ; yes, forward scroll3:mov word ptr es:DISP_START,dx ; set new start address mov dx,0ffh mov byte ptr es:DISP_UPDATE,dl ; request update mov ah,coninq int dos cmp al,8 ; if back space ^H, go scroll up jz scroll2 cmp al,10 ; if line feed ^J, go scroll down jz scroll2 cmp al,cr ; if carrage return, go latch it jz scroll4 mov dx,startad ; else, just go back mov word ptr es:DISP_START,dx ; set start address mov dx,0ffh mov byte ptr es:DISP_UPDATE,dl ; request update jmp short scroll6 ; scroll4: mov ax,word ptr es:DISP_START ; get start address mov cl,4 ; shift count shr ax,cl ; al now has latch value out 0dah,al ; initialize latch mov dx,1700h ; put cursor at beginning of last line call poscur test yflags,modoff ; is mode line disabled? jnz scroll5 ; yes, skip it call modlin ; enable and write modline jmp short scroll6 scroll5:call clrmod ; clear mode line scroll6:pop es pop dx pop cx pop ax ret scroll endp ; (BDT) new screen-scrolling routines. Single, circular buffer homwnd proc near ; "home" to start of the buffer push cx ; save registers mov cx,lxtra ; save this many lines call putcirc ; save them mov linec,0 ; reset the current pointer call getcirc ; now get the new screen pop cx ; restore registers clc ret homwnd endp endwnd proc near ; "end" to end of the buffer push cx ; save registers mov cx,lxtra ; save this many lines call putcirc ; save them mov cx,lcnt ; reset the current pointer mov linec,cx ; save the results call getcirc ; now get the new screen pop cx ; restore registers clc ret endwnd endp dnwpg proc near ; scroll down 1 page push cx ; save registers mov cx,lxtra ; save this many lines call putcirc ; save them mov cx,linec ; reset the current pointer add cx,lxtra ; to the next page cmp cx,lcnt ; did we go past the end? jbe dnwpg1 ; be = no, we're OK mov cx,lcnt ; yup, back up dnwpg1: mov linec,cx ; save the results call getcirc ; now get the new screen pop cx ; restore registers clc ret dnwpg endp dnone proc near ; scroll down 1 line push cx ; save registers mov cx,lxtra ; save this many lines call putcirc ; save them mov cx,linec ; reset the current pointer inc cx ; to the next line cmp cx,lcnt ; oops, did we go past the end? jbe dnone1 ; be = no, we're OK mov cx,lcnt ; yup, back up dnone1: mov linec,cx ; save the results call getcirc ; now get the new screen pop cx ; restore registers clc ret dnone endp upwpg proc near ; scroll up 1 page push cx ; save registers mov cx,lxtra ; save this many lines call putcirc ; save them mov cx,linec ; reset the current pointer sub cx,lxtra ; to the previous page cmp cx,0 ; oops, did we go past the end? jge upwpg1 ; ge = no, we're OK xor cx,cx ; yup, back up upwpg1: mov linec,cx ; save the results call getcirc ; now get the new screen pop cx ; restore registers clc ret upwpg endp upone proc near ; scroll up 1 line push cx ; save registers mov cx,lxtra ; save this many lines call putcirc ; save them mov cx,linec ; reset the current pointer dec cx ; to the previous line cmp cx,0 ; oops, did we go past the end? jge upone1 ; ge = no, we're OK xor cx,cx ; yup, back up upone1: mov linec,cx ; save the results call getcirc ; now get the new screen pop cx ; restore registers clc ret upone endp ; Put cx lines into the circular buffer. Characters are stored as a word ; containig the Z-100 font index (low) and the Z-100 attributes (high). ; Source segment is tv_segs which is set to point to the green video plane. ; Source offset for each char is calculated below based on the screen char ; index in si. The index starts at 0 and ends at COLUMNS * ROWS - 1 = 1919, ; corresponding to 1920 characters. putcirc proc near ; put lines in the circular buffer jcxz putcir9 ; z = no lines to save push es ; save ES for a tad xor si,si ; Screen char index mov ax,linef ; get the first line pointer add ax,linec ; add the current line counter dec ax ; get a running start sub si,COLUMNS ; Here too putcir1:inc ax ; increment the current line pointer add si,COLUMNS ; This many char per line cmp ax,linee ; fallen off the end of the buffer? jb putcir2 ; b = no, proceed sub ax,linee ; back up to the buffer start putcir2:push ax ; save the current line pointer mul ppl ; compute the paragraph offset add ax,iniseg ; add the initial segment mov es,ax ; now we have the segment pointer xor di,di ; initial buffer offset is 0 push cx ; save the number of lines push si ; Save index xor ch,ch ; get the number of characters to move mov cl,COLUMNS ; One row push ds ; get the offset of the screen mov ds,tv_segs ; get the segment of the screen mov ax,si ; Index here div cl ; Line now in al and column in ah mov bh,al ; Line in bh mov bl,ah ; Column in bl shl bh,1 shl bh,1 shl bh,1 putcir3:mov al,ds:byte ptr [bx+9*128] ; Char index mov ah,ds:byte ptr [bx+10*128] ; Char attributes stosw inc bl ; Next char loop putcir3 ; Go back for next char pop ds ; restore DS pop si ; Restore index pop cx ; restore the line count pop ax ; restore the buffer counter loop putcir1 ; go back for more pop es ; restore ES putcir9:ret ; Note, also used by getcirc below putcirc endp ; Get CX lines from the circular buffer, non destructivly. Destination ; segment is the green video plane and destination offset for each char ; is calculated below based on the screen char index in di. The index ; starts at 0 and ends at COLUMNS * ROWS - 1 = 1919, corresponding to ; 1920 characters. The call to MTR_DFC writes to the destination. getcirc proc near ; get lines from the circular buffer mov cx,lxtra ; restore this many lines jcxz putcir9 ; z = nothing to do push es ; save ES for a tad mov ax,IPAGE_SEG ; Interrupt page mov es,ax ; into es mov bp,offset es:MTR_DFC ; Need this pointer for our call mov es,es:[MTR_DS] ; Monitor data segment xor di,di ; Screen char index mov ax,linef ; get the first line pointer add ax,linec ; add the current line counter dec ax ; get a running start sub di,COLUMNS ; Here too getcir1:inc ax ; increment the current line pointer add di,COLUMNS ; This many char per line cmp ax,linee ; fallen off the end of the buffer? jb getcir2 ; b = no, proceed sub ax,linee ; back up to the buffer start getcir2:push ax ; save the current line pointer mul ppl ; compute the paragraph offset add ax,iniseg ; add the initial segment xor si,si ; initial offset is 0 push cx ; save the number of lines push di ; Save index xor ch,ch ; get the number of characters to move mov cl,COLUMNS ; One row push ds ; save DS for a tad push es ; Save MTR_DS mov ds,ax ; now we have the segment pointer mov ax,di ; Index here div cl ; Line now in al and column in ah mov bh,al ; Line in bh mov bl,ah ; Parameter 1, column, in bl push bx ; * Parameter # 1 set xchg bh,bl ; Parameter 2, line, from bh to bl push bx ; ** Parameter # 2 set xchg bh,bl ; Get right order back getcir3:mov bh,0 ; Column now in bx shl bx,1 ; 2 bytes per cell in buffer mov ax,word ptr ds:[di.bx] ; Get the char from buffer push ax ; *** Parameter # 3 set mov dh,ah and dh,111b ; Foreground color mov dl,ah shr dl,1 shr dl,1 shr dl,1 and dl,111b ; Background color cmp cs:tempcol,dx ; New color or fresh start? jz getcir4 ; No, just skip all of this mov cs:tempcol,dx ; Remember color call setcol ; Set the color getcir4:and ah,80h ; Reverse video? mov ax,0 ; Assume no jz getcir5 ; No, skip this mov ax,0ffffh ; Set up parameter # 4 getcir5:push ax ; **** Parameter # 4 set call dword ptr es:[bp] ; Display char pop es ; We need this for our call push es ; Save again sub sp,2 ; Point to first parameter pop bx ; Get it back inc bl ; Next char push bx ; * Parameter # 1 set sub sp,2 ; ** Parameter # 2 set, old value loop getcir3 add sp,6 pop ds ; restore DS pop di ; restore index pop cx ; restore the line count loop getcir1 ; go back for more mov cs:tempcol,0ffffh ; Restore for next time pop es ; restore ES getcir6:ret getcirc endp ; Screen dump entry from keyboad xlat dmpscn proc near ; dump screen to file call dumpscr ; do buffer to file clc ; do not exit Connect mode ret dmpscn endp code ends end