;SSTERM VERSION 2.00 - SPLIT SCREEN TERMINAL PROGRAM (3/22/87) ; ;TERMINAL PROGRAM FOR USE WITH REAL TIME CONFERANCE,C.B. LIVEWIRE OR ANY OTHER ;FULL DUPLEX APPLICATIONS WHERE YOU WISH TO KEEP YOUR KEYBOARD TEXT SEPERATE ;FROM THE TEXT RECEIVED FROM THE MODEM. ; ;PROGRAM WRITTEN BY W.MUNSON.... IF YOU FIND ANY BUGS IN THE PROGRAM OR IF YOU ;NEED ASSISTANCE IN CUSTOMIZING IT FOR YOUR USE, CONTACT ME BY E-MAIL ON GEnie ;OR ON THE HEATH/ZENITH BBS. (716) 424-2576. ; ;NOTE:THIS PROGRAM IS BEING RELEASED AS PUBLIC DOMAIN AND MAY BE DISTRIBUTED ;TO ALL WHO WISH TO USE IT. ; ;THIS VERSION IS WRITTEN FOR A COLUMBIA DATA PRODUCTS M64 OR M64-1 ;CP/M SYSTEM. ALSO KNOWN AS 'CONKEY-64' OR 'SHOEBOX'- USING A DIABLO 3200 ;AS A TERMINAL (MODIFIED HAZELTINE 1500). ; ; ; ; ; ; ;***************************************************************************** ; ; ;THIS SECTION CONTAINS ALL OF THE ADDRESSES AND CONTROL WORDS USED TO ;COMMAND THE UARTS... THESE ARE THE STANDARD COMMANDS USED WITH THE 8251A. MDMPRT EQU 58H ;this is the address of the modem communication port STAPRT EQU 59H ;this is the address of the modem status port CONDAT EQU 40H ;this is the address of the console data port CONSTA EQU 41H ;this is the address of the console status port ; URTRCV EQU 02H ;this is the status mask to see if a char is received URTSND EQU 01H ;this is the status mask to see if aurt is rdy to send MODEMK EQU 4EH ;uart mode setup word MODEGO EQU 37H ;default modem initialization word DTROFF EQU 05H ;word to turn off dtr MDMRST EQU 40H ;modem reset word MDMATN EQU 00H ;gets the attention of the uart ; ;***************************************************************************** ; YES EQU 0FFH NO EQU 0H CR EQU 13 ;ascii code for carrage return LF EQU 10 ;ascii code for line feed BKSP EQU 8 ;ascii code for backspace DEL EQU 0FFH ;ascii code for delete character ESC EQU 27 ;ascii code for escape key TAB EQU 9 ;ascii code for tab character ; ;THIS JUMP IS TO THE START OF THE ACTUAL PROGRAM ORG 100H ;start assembly at beginning of the tpa ;THIS SECTION INITIALIZES THE MODEM USART (8251A) INIT: MVI A,MDMATN ;load word to get uart's attention OUT STAPRT OUT STAPRT OUT STAPRT MVI A,MDMRST ;load reset command OUT STAPRT MVI A,MODEMK ; mode mask OUT STAPRT MVI A,MODEGO ;enable transmitter and receiver OUT STAPRT JMP START ;jump to the program area ; ;HERE IS THE SECTION WHICH DEFINES THE TERMINAL CONTROL COMMANDS. ; ;YOU MUST BE ABLE TO ADDRESS THE CURSOR OF YOUR TERMINAL. ;THE FORMAT OF THE STRING IS - FIRST BYTE IS THE NUMBER OF CHARACTERS IN ;THE STRING THEN THE REMAINING BYTES ARE THE STRING ITSELF. ; ORG 140H CLRLNE: EQU $ DB 2,14,15 ;string to clear to end of line ;string can be 80 spaces if not supported by ;your terminal ; ORG 200H CURADR: EQU $ DB 2,14,17 ;string sent before cursor address information ; ORG 210H OFFSET: DB 00H ;value of the offset added to cursor addresses ; COLROW: DB YES ;send coloum before row for cursor address? ; NEEDLF: DB NO ;does your terminal need line feeds? if it ;does then set this bit to yes ; ORG 220H CLRSCN: EQU $ DB 2,14,28 ;string sent to clear screen-can be 24 ;carrage returns ; ORG 240H ALTON: EQU $ DB 2,14,31 ;string to turn on the alternate video mode ;can be 1,0 if not supported by your terminal ORG 250H ALTOFF: EQU $ DB 2,14,25 ;string to turn off the alternate video mode ;can be 1,0 if not supported by your terminal ; ORG 260H SCRLUP: EQU $ DB 1,CR ;scroll up string should cause one line to ;be inserted at the bottom of the screen ;when cursor is positioned at bottom of screen ; ORG 270H NAME: EQU $ ;string to describe the operating system DB 43 ;and terminal type DB 'for "CONKEY-64" with DIABLO 3200 terminal',CR,LF ; ;**************************************************************************** ; ;THIS SECTION CONTAINS THE CALLS TO SERVICE THE USARTS. DO NOT CHANGE THE ;STARTING ADDRESSES OF THEM ORG 370H INCDAT: IN CONDAT ;get char from console usart RET ; ORG 380H OUTCDT: OUT CONDAT ;send char to console usart RET ; ORG 390H INCSTA: IN CONSTA ;get status from console usart for input ANI URTRCV ;mask status word for char ready in uart RET ; ORG 398H ; OTCSTA: IN CONSTA ;get status from console usart for output ANI URTSND ;mask status word for char ready in uart RET ; ; ORG 3A0H INMDAT: IN MDMPRT ;get char from modem usart RET ; ORG 3B0H OUTMDT: OUT MDMPRT ;send char to modem usart RET ; ORG 3C0H INMSTA: IN STAPRT ;get status from modem usart ANI URTRCV ;mask status word for char ready in uart RET ; ORG 3C8H ; OTMSTA: IN STAPRT ;get status from modem usart ANI URTSND ;mask status word for char ready in uart RET ; ; ORG 3D0H OUTMST: OUT STAPRT ;send command to modem status port RET ; ;THIS JUMP LOCATION IS FOR RESETING THE TERMINAL MODE IF NEEDED. ;THE ROUTINE CANNOT BE MORE THAN 20H BYTES LONG ORG 3E0H RESET: JMP 0H ;no special commands needed ; ; ;***************************************************************************** ;HERE IS THE END OF THE USER SPECIFIC SECTION ******************************** ;***************************************************************************** ; ; ORG 400H ;THIS IS THE LOGO PRINTED AT THE BEGINNING OF THE PROGRAM INTRO: EQU $ DB 55,CR,LF,CR,LF,CR,LF DB 'SSTERM Version 2.00',CR,LF ; ;THIS IS THE SIGN-ON HELP MESSAGE STRING ORG 480H HELPM: DB 31 ; DB 'type ESC + ? for instructions',CR,LF ; ORG 500H ;THIS IS THE HELP MESSAGE TEXT HLPMSG: EQU $ DB 89D,'COMMANDS ARE: D-DISCONNECT MODEM X-EXIT TO CP/M ESC-BACK' DB ' TO SSTERM',CR,LF,'ENTER YOUR COMMAND?' ; ; ORG 600H ;starting location for buffer ;THIS SECTION SETS ASIDE 200H BYTES FOR THE KEYBOARD BUFFER KEYBUF: EQU $ DS 200H ;sets aside 160 bytes for buffer ; ;THIS SECTION SET ASIDE 100H BYTES FOR THE MODEM BUFFER ORG 800H MDMBUF: EQU $ ;set to starting address of modem buffer DS 100H ;sets aside 50h bytes for modem buffer ; ; ;THIS SECTION SETS ASIDE 10H BYTES FOR TEMPORARY STRING ASSEMBLY ORG 0900H TMPBUF: EQU $ ;this is the area used to assemble strings DS 10H ;this sets aside 10h bytes for temp buffer ; ORG 0910H ;THIS SECTION CONTAINS ALL THE POINTERS FOR THE PROGRAM TOPCOL: DB 0 ;set to left edge of screen BOTCOL: DB 0 ;set to left edge of screen BOTROW: DB 22 ;set to 2nd from bottom row of screen KEYPNT: DB 0 ;points to last byte in keyboard buffer LASCHR: DW OUTBUF ;address of last char in print buffer LASPRT: DW OUTBUF ;address of last char printed MDMLAS: DW MDMBUF ;address of last char in modem buffer MDMPNT: DW MDMBUF ;address of last char outputed to modem OLDSP: DW 0H ;this loc stores the old stack pointer value ; ;THIS SECTION IS RESERVED FOR THE PROGRAM STACK AREA ; ; ;HERE IS THE START OF THE ACTUAL PROGRAM ORG 1000H ; ; ;THIS SECTION CLEARS THE SCREEN AND PRINTS THE PROGRAM LOGO START: LXI H,0 ;clear hl DAD SP ;get value of stack pointer SHLD OLDSP ;save the stackpointer value LXI SP,0FFFH ;load value of program stack LXI D,CLRSCN ;load de with address of clear screen string LDAX D ;load number of bytes in string into a INX D ;move address pointer to start of string MOV B,A ;move number of bytes in b CALL LDCBUF ;call routine to load info into console buffer CALL NULLS LXI D,INTRO ;load de with address of program logo string LDAX D ;load number of bytes in string into a INX D ;move address pointer to start of string MOV B,A ;move number of bytes in b CALL LDCBUF ;call routine to load info into console buffer CALL NULLS LXI D,NAME ;load de with address of system name string LDAX D ;load number of bytes in string into a INX D ;move address pointer to start of string MOV B,A ;move number of bytes in b CALL LDCBUF ;call routine to load info into console buffer CALL NULLS LXI D,HELPM ;load de with address of help logo string LDAX D ;load number of bytes in string into a INX D ;move address pointer to start of string MOV B,A ;move number of bytes in b CALL LDCBUF ;call routine to load info into console buffer CALL NULLS CALL POSCUR ;position cursor at proper place CALL NULLS ;insert some nulls ; ;THIS IS THE MAIN LOOP CONTROLLING THE PROGRAM UARTCK: CALL INCSTA ;get status of the console uart ; ani urtrcv ;MASK STATUS WORD FOR CHAR READY IN UART CNZ CONRCV ;call the input from console routine ; CALL OTCSTA ;get status of the console uart ; ani urtsnd ;MASK STATUS WORD FOR READY TO SEND CNZ PRTCHR ;call output to console from buffer routine ; CALL INMSTA ;get status of modem uart ; ani urtrcv ;MASK STATUS WORD FOR CHAR READY IN UART CNZ MDMRCV ;call input from modem uart routine ; CALL OTMSTA ;get status of modem uart ; ani urtsnd ;MASK STATUS WORD FOR READY TO SEND CNZ OUTCHR ;call routine to output to modem from buffer ; JMP UARTCK ;go back and try again ; ; ; ; ;THIS ROUTINE LOADS STRING INTO THE CONSOLE OUTPUT BUFFER ;ON ENTRY: DE=STARTING ADDRESS OF THE STRING ; B=NUMBER OF BYTES IN THE STRING ; ;LASCHR=POINTER TO THE ADDRESS OF THE LAST CHAR IN THE BUFFER ; LDCBUF: PUSH D ;store de on the stack (address of string) PUSH B ;store bc on stack (no. of char in string) LDAX D ;get char from string into a LHLD LASCHR ;load address of last char in buffer in hl PUSH H ;store it for move POP B ;get it into bc STAX B ;store char at end of buffer INX H ;move pointer to new location SHLD LASCHR ;store new pointer address MOV A,H ;move msb of address to a CPI 0D0H ;see if next location would be d000h JNZ CONT ;continue past this if not there yet LXI H,OUTBUF ;load address of start of console buffer SHLD LASCHR ;start storing print at beginning of buffer ;so that ccp isnt overrun CONT: POP B ;get char in string count DCR B ;update count of char left to be printed MOV A,B ;move to a for eos check CPI 0H ;see if we are done POP D ;get string pointer RZ ;return if done INX D ;move to next char address JMP LDCBUF ;go back and do it again ; ;THIS ROUTINE LOADS STRING INTO THE MODEM OUTPUT BUFFER ;ON ENTRY: DE=STARTING ADDRESS OF THE STRING ; B=NUMBER OF BYTES IN THE STRING ; ;MDMLAS=POINTER TO THE ADDRESS OF THE LAST CHAR IN THE BUFFER ; LDMBUF: PUSH D ;store de on the stack (address of string) PUSH B ;store bc on stack (no. of char in string) LDAX D ;get char from string into a LHLD MDMLAS ;load address of last char in buffer in hl PUSH H ;store it for move POP B ;get it into bc STAX B ;store char at end of buffer INX H ;move pointer to new location SHLD MDMLAS ;store new pointer address POP B ;get char in string count DCR B ;update count of char left to be printed MOV A,B ;move to a for eos check CPI 0H ;see if we are done POP D ;get string pointer RZ ;return if done INX D ;move to next char address JMP LDMBUF ;go back and do it again ; ;THIS ROUTINE IS CALLED WHEN THE CONSOLE UART IS READY FOR ANOTHER CHARACTER ; ;LASCHR=POINTER TO THE ADDRESS OF THE LAST CHAR IN THE BUFFER ;LASPRT=POINTER TO THE ADDRESS OF THE LAST CHAR PRINTED ; ;THERE IS NO INFORMATION PASSED AT ENTRY TO ROUTINE ; PRTCHR: LHLD LASCHR ;load hl with adress of the last char in buffr XCHG ;move it to de LHLD LASPRT ;load hl with address of the last chr printed MOV A,H ;load first byte in a SUB D ;compare to d MOV B,A ;store it in b MOV A,L ;load second bte in a SUB E ;compare with e ORA B ;equals zero if both numbers match CPI 0H ;set zero flag if both numbers match RZ ;return if no print ready for output ; ;THIS SECTION GETS THE CHAR FROM THE BUFFER AND OUTPUTS IT TO THE UART LHLD LASPRT ;load address of the last char printed PUSH H ; POP D ;get address into de LDAX D ;get the char into reg a INX H ;inc pointer SHLD LASPRT ;save new location in pointer CALL OUTCDT ;output it to the console uart LHLD LASPRT ;get location pointer MOV A,H ; CPI 0D0H ;see if it is up to d000h JNZ CONT1 ;bypass this code if it is not LXI H,OUTBUF ;load address of output buffer SHLD LASPRT ; CONT1: LHLD LASCHR ;load hl with adress of the last char in buffr XCHG ;move it to de LHLD LASPRT ;load hl with address of the last chr printed MOV A,H ;load first byte in a SUB D ;compare to d MOV B,A ;store it in b MOV A,L ;load second bte in a SUB E ;compare with e ORA B ;equals zero if both numbers match CPI 0H ;set zero flag if both numbers match RNZ ;return if not the last char in buffer ;THIS SECTION RETURNS BOTH POINTERS TO THE BEGINNING OF THE BUFFER LXI H,OUTBUF ;load address of ouput buffer in hl SHLD LASCHR ;reset laschr SHLD LASPRT ;reset lasprt RET ; ;THIS ROUTINE IS CALLED WHEN THE MODEM UART IS READY FOR A CHARACTER ; ;MDMLAS=LAST CHARACTER IN THE MODEM BUFFER ;MDMPNT=LAST CHARACTER PRINTED FROM THE MODEM BUFFER ; ;THERE IS NO INFORMATION PASSED AT ENTRY TO THE ROUTINE ; OUTCHR: LHLD MDMLAS ;load hl with adress of the last char in buffr XCHG ;move it to de LHLD MDMPNT ;load hl with address of the last chr printed MOV A,H ;load first byte in a SUB D ;compare to d MOV B,A ;store it in b MOV A,L ;load second bte in a SUB E ;compare with e ORA B ;equals zero if both numbers match CPI 0H ;set zreo flag if both numbers match RZ ;return if no print ready for output ; ;THIS SECTION GETS THE CHAR FROM THE BUFFER AND OUTPUTS IT TO THE UART LHLD MDMPNT ;load address of the last char printed PUSH H ; POP D ;get address into de LDAX D ;get the char into reg a INX H ;inc SHLD MDMPNT ;store new pointer CALL OUTMDT ;output it to the modem port LHLD MDMPNT ;get las char pointer XCHG ;move it to de LHLD MDMLAS ;load hl with address of the last chr printed MOV A,H ;load first byte in a SUB D ;compare to d MOV B,A ;store it in b MOV A,L ;load second bte in a SUB E ;compare with e ORA B ;equals zreo if both numbers match CPI 0 ;set zreo flag if both numbers match RNZ ;return if not the last char in buffer ;THIS SECTION RETURNS BOTH POINTERS TO THE BEGINNING OF THE BUFFER LXI H,MDMBUF ;load address of ouput buffer in hl SHLD MDMLAS ;reset mdmlas SHLD MDMPNT ;reset mdmpnt RET ; ;THIS ROUTINE POSITIONS THE CURSOR TO THE CURRENT PRINT POSITION ON THE 20TH ;ROW OF THE SCREEN. POSCUR: LXI D,CURADR ;load cursor address pointer into de LDAX D ;load number of bytes in string into a INX D ;move address pointer to start of string MOV B,A ;move number of bytes into b CALL LDCBUF ;call routine to load info into cursor buffer ; LOOP1: LDA COLROW ;load col before row flag ORA A ;set zero flag JZ LOOP2 ;bypass this section LDA OFFSET ;load offset into a MOV B,A ;store it in b LDA TOPCOL ;load a with coloum info ADD B ;add offset to topcol STA TMPBUF ;store it in the temp string buffer MVI A,20 ;load a with row 20 info ADD B ;add offset to row info STA TMPBUF+1 ;store in next location of temp string buffer JMP LOOP3 ; LOOP2: LDA OFFSET ;load offset into a MOV B,A ;store it in b MVI A,20 ;load a with row 20 info ADD B ;add offset to row info STA TMPBUF ;store it in temp string buffer LDA TOPCOL ;load a with col info ADD B ;add it to topcol STA TMPBUF+1 ;store in next location in temp string buffer ; LOOP3: LXI D,TMPBUF ;load de with address of temp string buffer MVI B,2 ;load number of char into b CALL LDCBUF ;call routine to load info into cursor buffer RET ; ; ;THIS ROUTINE GETS THE CHARACTER FROM THE MODEM UART AND PROCESSES IT. MDMRCV: CALL INMDAT ;get character from modem uart MOV C,A ;store it in reg c PUSH B ;store it on the stack CPI CR ;set zero flag if it is a cr JZ ISCR ;if it is a carrage return then goto 'iscr' ; LDA NEEDLF ;load linefeeds flag into a ORA A ;set zero flag JZ LOOP4 ;bpass this area if no lf's needed MOV A,C ;put char back in a CPI LF ;set zero flag if it is a lf JZ ISCR ;if it is a line feed then goto 'iscr' ; LOOP4: MOV A,C ;put char back in a CPI BKSP ;set zero flag if it is a back space JZ BACKSP ;if it is a back space then goto 'backsp' MOV A,C ;put char back in a CPI DEL ;set zero flag if it is a delete character JZ BACKSP ;if it is a delete then goto 'backsp' MOV A,C ;put char back in a CPI TAB ;check to see if it is a tab JZ MAKTAB ;jump to tab routine ; ;THE CHAR MUST NOT REQUIRE SPECIAL HANDLING SO JUST PRINT IT CALL POSCUR ;position cursor CALL NULLS ;insert some nulls POP B ;get char from stack MOV A,C ;get it into a STA TMPBUF ;load it into temp string buffer LXI D,TMPBUF ;load temp buffer address into de MVI B,1 ;number of characters into b CALL LDCBUF ;call the load console buffer routine LDA TOPCOL ;load col info INR A ;move pointer to next location STA TOPCOL ;if not then store it CPI 80 ;set zero flag if is 80th col JZ IS80TH ;if it is make a carrrage return RET ;now return to main loop ; ;THIS ROUTINE CLEARS THE BOTTOM OF THE SCREEN IF THERE IS ANY PRINT IN THE ;KEYBOARD BUFFER. CLRBOT: LDA KEYPNT ;load keyboard string pointer into a CPI 0 ;set zero flag if no char in string RZ ;if zero then bottom of screen already clear LXI D,CURADR ;load cursor address pointer into de LDAX D ;load number of bytes in string into a INX D ;move address pointer to start of string MOV B,A ;move number of bytes into b CALL LDCBUF ;call routine to load info into cursor buffer ; LDA COLROW ;load col before row pointer into a ORA A ;set zero flag JZ LOOP5 ;if set then bypass this section LDA OFFSET ;load offset into a MOV B,A ;store it in b MVI A,0 ;load a with coloum info ADD B ;add it to col info STA TMPBUF ;store it in the temp string buffer MVI A,22 ;load a with row 22 info ADD B ;add it ot row info STA TMPBUF+1 ;store in next location of temp string buffer JMP LOOP6 ;bypass next section ; LOOP5: LDA OFFSET ;load offset into a MOV B,A ;store it in b MVI A,22 ;load a with row 22 info ADD B ;add it to row info STA TMPBUF ;store it in temp string buffer MVI A,0 ;load a with col info ADD B ;add offset to col STA TMPBUF+1 ;store in next location in temp string buffer ; LOOP6: LXI D,TMPBUF ;load de with address of temp string buffer MVI B,2 ;load number of char into b CALL LDCBUF ;call routine to load info into cursor buffer CALL NULLS ;insert some nulls ; LXI D,CLRLNE ;load cursor address pointer into de LDAX D ;load number of bytes in string into a INX D ;move address pointer to start of string MOV B,A ;move number of bytes into b CALL LDCBUF ;call routine to load info into cursor buffer CALL NULLS ;insert some nulls ; LXI D,CURADR ;load cursor address pointer into de LDAX D ;load number of bytes in string into a INX D ;move address pointer to start of string MOV B,A ;move number of bytes into b CALL LDCBUF ;call routine to load info into cursor buffer ; LDA COLROW ;load col before row flag into a ORA A ;set zero flag JZ LOOP7 ;bypass this section LDA OFFSET ;load offset into a MOV B,A ;store it in b MVI A,0 ;load a with coloum info ADD B ;add it to col STA TMPBUF ;store it in the temp string buffer MVI A,23 ;load a with row 23 info ADD B ;add offset to row STA TMPBUF+1 ;store in next location of temp string buffer JMP LOOP8 ;bypass this section ; LOOP7: LDA OFFSET ;load offset into a MOV B,A ;store it in b MVI A,23 ;load a with row 23 info ADD B ;add it to row STA TMPBUF ;store it in temp string buffer MVI A,0 ;load a with col info ADD B ;add it to col STA TMPBUF+1 ;store in next location in temp string buffer ; LOOP8: LXI D,TMPBUF ;load de with address of temp string buffer MVI B,2 ;load number of char into b CALL LDCBUF ;call routine to load info into cursor buffer CALL NULLS ;insert some nulls ; LXI D,CLRLNE ;load cursor address pointer into de LDAX D ;load number of bytes in string into a INX D ;move address pointer to start of string MOV B,A ;move number of bytes into b CALL LDCBUF ;call routine to load info into cursor buffer CALL NULLS ;insert some nulls RET ;return from routine ; ;THIS ROUTINE SCROLLS THE SCREEN BY ONE LINE SCROLL: LXI D,CURADR ;load cursor address pointer into de LDAX D ;load number of bytes in string into a INX D ;move address pointer to start of string MOV B,A ;move number of bytes into b CALL LDCBUF ;call routine to load info into cursor buffer ; LDA COLROW ;load col before row flag into a ORA A ;set zero flag JZ LOOP9 ;if no then bypass this section LDA OFFSET ;load offset into a MOV B,A ;store it in b MVI A,0 ;load a with coloum info ADD B ;add it to col STA TMPBUF ;store it in the temp string buffer MVI A,23 ;load a with row 23 info ADD B ;add it to row STA TMPBUF+1 ;store in next location of temp string buffer JMP LOOP10 ;bypass this next section ; LOOP9: LDA OFFSET ;load offset into a MOV B,A ;store it in b MVI A,23 ;load a with row 23 info ADD B ;add offset to row STA TMPBUF ;store it in temp string buffer MVI A,0 ;load a with col info ADD B ;add it to col STA TMPBUF+1 ;store in next location in temp string buffer ; LOOP10: LXI D,TMPBUF ;load de with address of temp string buffer MVI B,2 ;load number of char into b CALL LDCBUF ;call routine to load info into cursor buffer CALL NULLS ;insert some nulls ; LXI D,SCRLUP ;load scroll up pointer into de LDAX D ;load number of bytes in string into a INX D ;move address pointer to start of string MOV B,A ;move number of bytes into b CALL LDCBUF ;call routine to load info into cursor buffer CALL NULLS ;insert some nulls RET ;scroll done so return from routine ; ;THIS ROUTINE REPRINTS THE KEYBOARD STRING AT THE BOTTOM OF THE SCREEN PSTRNG: CALL ONALT ;turn on alt vid mode ; LXI D,CURADR ;load cursor address pointer into de LDAX D ;load number of bytes in string into a INX D ;move address pointer to start of string MOV B,A ;move number of bytes into b CALL LDCBUF ;call routine to load info into cursor buffer ; ; LDA COLROW ;load col before row flag into a ORA A ;set zero flag JZ LOOP11 ;if no then bpass this section LDA OFFSET ;load offset into a MOV B,A ;store it in b MVI A,0 ;load a with coloum info ADD B ;add it to col STA TMPBUF ;store it in the temp string buffer MVI A,22 ;load a with row 22 info ADD B ;add it to row STA TMPBUF+1 ;store in next location of temp string buffer JMP LOOP12 ;bypass this section ; LOOP11: LDA OFFSET ;load offset into a MOV B,A ;store it in b MVI A,22 ;load a with row 22 info ADD B ;add it to row STA TMPBUF ;store it in temp string buffer MVI A,0 ;load a with col info ADD B ;add it to col STA TMPBUF+1 ;store in next location in temp string buffer ; LOOP12: LXI D,TMPBUF ;load de with address of temp string buffer MVI B,2 ;load number of char into b CALL LDCBUF ;call routine to load info into cursor buffer CALL NULLS ;insert some nulls ; ;THIS SECTION PRINTS THE KEYBOARD STRING LXI D,KEYBUF ;load keyboard buffer pointer into de LDA KEYPNT ;load number of characters in string into a MOV B,A ;move it to b CALL LDCBUF ;load it into the console buffer CALL NULLS ;insert some nulls ; CALL OFFALT ;turn off alt vid mode CALL NULLS ;insert some nulls ; RET ;and you are done ; ;THIS ROUTINE HANDLES THE SCROLLING OF THE SCREEN AFTER A CR OR LF ISCR: LDA KEYPNT ;load keyboard string pointer CPI 0 ;set zero flag if no char in string CNZ CLRBOT ;clear bottom of screen if needed CALL SCROLL ;scroll the screen one line LDA KEYPNT ;load keyboard string pointer CPI 0 ;set zero flag if no char in string CNZ PSTRNG ;print keyboard string if needed POP B ;this is to keep the pushes and pops even MVI A,0 ;load a with 0 STA TOPCOL ;clear top col RET ;return to routine ; ;THIS ROUTINE MAKES A BACKSPACE BACKSP: LDA TOPCOL ;get col info into a DCR A ;back up one space STA TOPCOL ;store it MVI A,20H ;load ascii space char into a STA TMPBUF ;store it in the temp string buffer LXI D,TMPBUF ;load de with temp string buffer address MVI B,1 ;load b with number of chars CALL LDCBUF ;load it into the console buffer CALL POSCUR ;reposition cursor to the space CALL NULLS ;insert some nulls POP B ;this keeps the pushes and pops even RET ;return to routine ; ;THIS ROUTINE SIMULATES A CARRAGE RETURN IF THE PRINT REACHES ;THE 80TH COLOUM ON THE SCREEN IS80TH: LDA KEYPNT ;load keyboard string pointer CPI 0 ;set zero flag if no char in string CNZ CLRBOT ;clear bottom of screen if needed CALL NULLS ;insert some nulls CALL SCROLL ;scroll the screen one line CALL NULLS ;insert some nulls LDA KEYPNT ;load keyboard string pointer CPI 0 ;set zero flag if no char in string CNZ PSTRNG ;print keyboard string if needed MVI A,0 ;load a with 0 STA TOPCOL ;clear top col RET ;return to routne ; ;THIS ROUTINE GET A CHAR FROM THE CONSOLE UART CONRCV: CALL INCDAT ;get char from console uart MOV C,A ;store it in c PUSH B ;store it on stack CPI CR ;set zero flag if it is a cr JZ MAKECR ;goto carrage return routine MOV A,C ;get char from storage CPI ESC ;set zero flag if it is an escape key JZ ISESC ;goto escape routine CALL POSPNT ;position cursor for print CALL ONALT ;turn on alternate video POP B ;get char from stack PUSH B ;store it again MOV A,C ;get char into a STA TMPBUF ;load it to the temp string buffer LXI D,TMPBUF ;load temp string buffer's address to de MVI B,1 ;number of chars CALL LDMBUF ;call load modem buffer routine POP B ;get char from stack MOV A,C ;get char again CPI BKSP ;compare it to a back space char JZ MAKEBS ;goto make backspace routine PUSH B ;save it again MOV A,C ;move it to a STA TMPBUF ;load it to the temp string buffer LXI D,TMPBUF ;load temp string buffer's address to de MVI B,1 ;number of chars CALL LDCBUF ;send char to the screen CALL OFFALT ;turn off altvideo mode LXI H,KEYBUF ;load keybuf address into hl MVI D,0 ;clear d LDA KEYPNT ;load keyboard pointer into a MOV E,A ;move it to e DAD D ;add pointer to address PUSH H ;move address into de POP D ; POP B ;get char from stack MOV A,C ;move char into reg a STAX D ;store it at the end of the keyboard string LDA KEYPNT ;load keyboard string pointer INR A ;move pointer to next location STA KEYPNT ;store in keboard pointer LDA BOTCOL ;get botcol pointer INR A ;inc to next location STA BOTCOL ;also in bottom col pointer CPI 80 ;set zero flag if it is the 80th col JZ MAKE80 ;jump to routine to print on next line RET ;and back again ;THIS ROUTINE POSITIONS CURSOR FOR THE NEXT CHAR FROM THE KEYBOARD POSPNT: LXI D,CURADR ;load cursor address pointer into de LDAX D ;load number of bytes in string into a INX D ;move address pointer to start of string MOV B,A ;move number of bytes into b CALL LDCBUF ;call routine to load info into cursor buffer ; LDA COLROW ;load col before row flag into a ORA A ;set zero flag JZ LOOP13 ;if no then bypass this section LDA OFFSET ;load offset into a MOV B,A ;store it in b LDA BOTCOL ;load a with coloum info ADD B ;add offset to topcol STA TMPBUF ;store it in the temp string buffer LDA BOTROW ;load a with row info ADD B ;add offset to row info STA TMPBUF+1 ;store in next location of temp string buffer JMP LOOP14 ;bypass this section ; LOOP13: LDA OFFSET ;load offset into a MOV B,A ;store it in b LDA BOTROW ;load a with row info ADD B ;add offset to row info STA TMPBUF ;store it in temp string buffer LDA BOTCOL ;load a with col info ADD B ;add it to topcol STA TMPBUF+1 ;store in next location in temp string buffer ; LOOP14: LXI D,TMPBUF ;load de with address of temp string buffer MVI B,2 ;load number of char into b CALL LDCBUF ;call routine to load info into cursor buffer CALL NULLS ;insert some nulls RET ; ; ;THIS ROUTINE TURNS ON THE ALTERNATE VIDEO MODE ONALT: LXI D,ALTON ;load alternate video pointer into de LDAX D ;load number of bytes in string into a INX D ;move address pointer to start of string MOV B,A ;move number of bytes into b CALL LDCBUF ;call routine to load info into cursor buffer CALL NULLS ;insert some nulls RET ;thats all folks ; OFFALT: LXI D,ALTOFF ;load alternate video pointer into de LDAX D ;load number of bytes in string into a INX D ;move address pointer to start of string MOV B,A ;move number of bytes into b CALL LDCBUF ;call routine to load info into cursor buffer CALL NULLS ;insert some nulls RET ;thats all folks ; ;THIS ROUTINE CLEARS THE SCREEN BOTTOM AND THE KEYBOARD BUFFER AND THE COL AND ;ROW POINTERS AND ALSO SENDS A CARRAGE RETURN TO THE MODEM BUFFER MAKECR: CALL CLRBOT ;this call clears the bottom of the screen ; POP B ;get char from stack MVI A,CR ;move a cr into a STA TMPBUF ;load it into temp string buffer MVI A,0H ;load a line feed into a STA TMPBUF+1 ;store it in buffer LXI D,TMPBUF ;load temp buffer address into de MVI B,2 ;load number of char into b CALL LDMBUF ;load it into the modem buffer ; MVI A,0 ;load zero into a STA KEYPNT ;clear the keyboard string pointer MVI A,0 ;load zero into a STA BOTCOL ;reset the col pointer MVI A,22 ;load 22 into a STA BOTROW ;load 22 into the row pointer RET ; ; ;THIS ROUTINE POSITIONS CURSOR TO THE NEXT LINE AFTER THE 80TH CHAR FROM KBRD MAKE80: MVI A,0 ;load zero into a STA BOTCOL ;store it in col pointer MVI A,23 ;load 23 into a STA BOTROW ;store it in row pointer CALL POSPNT ;position cursor to next line RET ;all done ; ;THIS ROUTINE HANDLES A TAB CHAR FROM THE MODEM MAKTAB: LDA TOPCOL ;get current col info ANI 0F8H ;and off lower three bits to get next ADI 08H ;tab location and add 8 to number MOV B,A ;store it in b CPI 80 ;check to see if new pos is >80 JP IS80TH ;if more than 80 then go MOV A,B ;get back in a STA TOPCOL ;store new col info POP B ;this keeps pushes and pops even RET ; ; ;THIS ROUTINE HANDLES ESCAPE ROUTINES ISESC: POP B ;keeps pushes and pops even CALL CLRBOT ;clear bottom of screen MVI A,0 ; STA BOTCOL ;clear bottom col pointer MVI A,22 ; STA BOTROW ;set row to 22 CALL POSPNT ;position print location ; CLRBUF: CALL OTCSTA ;get console status CNZ PRTCHR ;send it one if it is ready CALL INCSTA ;get console status JNZ SPLFCT ;go see if it is one of the special char JMP CLRBUF ;loop back again ; SPLFCT: CALL INCDAT ;get data from console MOV B,A ;save it in b CPI 'D' ;see if it is a 'd' JZ DISCON ;goto disconnect routine CPI 'd' ; JZ DISCON ; MOV A,B ; CPI 'X' ;see if it is a 'x' JZ EXIT ;jump to exit routine CPI 'x' ; JZ EXIT ; MOV A,B ; CPI ESC ;check to see if second char is a esc JZ 100H ;restart program without dropping line ; CALL CLRBOT ;clear bottom of screen MVI A,0 ;load zero into a for col info STA BOTCOL ;store col info MVI A,22 ;load 22 into a for row info STA BOTROW ;store row info CALL POSPNT ;position cursor CALL NULLS ;send some nulls LXI D,HLPMSG ;load pointer to help message LDAX D ; INX D ; MOV B,A ; CALL LDCBUF ;load it into buffer JMP CLRBUF ;go wait for char ; ;THIS ROUTINE EXITS PROGRAM TO CPM EXIT: LHLD OLDSP ;get old stack value into hl SPHL ;store old stack pointer value in sp JMP RESET ;jump to termminal reset routine ; ; ;THIS ROUTINE DISCONNECTS MODEM DISCON: CALL OTMSTA ;get status of modem port JZ DISCON ; MVI A,DTROFF ;load dtr off word CALL OUTMST ;turn off dtr LXI B,0FFFFH ;load loop count into bc LOOP: DCX B ;decriment bc MOV A,B ;move b into a ORA C ;or it with c CPI 0H ;see if results are zero JNZ LOOP ;loop again ; JMP INIT ; ;THIS ROUTINE INSERTS 3 NULLS INTO THE CONSOLE BUFFER TO ALLOW THE TERMINAL ;TO CATCH UP WITH THE COMMANDS NULLS: MVI A,0 ;load null char into a STA TMPBUF ;store in first location of tmp buffer STA TMPBUF+1 ;and next STA TMPBUF+2 ;and in the third LXI D,TMPBUF ;load address of temp buffer MVI B,3 ;number of char in b CALL LDCBUF ;and load them in buffer RET ;and your done ; ;THIS ROUTINE MAKES A BACKSPACE IN THE KEYBOARD TEXT MAKEBS: LDA BOTROW ;get row info CPI 23 ;check to see if it is in row 23 JZ BS23 ;jump to backspace on 23 routine BS: CALL POSPNT ;position cursor to last print loaction MVI A,' ' ;load space char into a STA TMPBUF ;store in temp buffer LXI D,TMPBUF ;load temp buffer pointer into de MVI B,1 ;load number of char into b CALL LDCBUF ;and load it into the buffer LDA BOTCOL ;get col info DCR A ;dec it by one STA BOTCOL ;store new value CALL POSPNT ;reposition curcor CALL OFFALT ;turn off alt vid mode RET ; BS23: LDA BOTCOL ;get col info CPI 0 ;if in first col then is zero JNZ BS ;go back if not in first position MVI A,22 ; STA BOTROW ; MVI A,80 ; STA BOTCOL JMP BS ; ; ;THIS EQUATE SETS UP THE CONSOLE OUTPUT BUFFER TO BE THE REST OF THE ;SYSTEM MEMORY OUTBUF: EQU $ DB 0 END