*** TITLÅ 'ICRT -- INTELLIGENÔ CRÔ DRIVEÒ FOÒ THÅ VB³ VIDEÏ BOARD' * * "ICRT"; Rev 0; Written by Ben L Gee; Dec 9, 1979 * * ICRT is a driver for the SSM VB3 video board. ICRT will allow * the VB3 to replace most any intelligent crt terminal. * * This software has been used successfully with UCSD Pascal and * MicroPro Wordstar. * $-MACRO * MACLIB Z80 ;Z80 PEOPLE SHOULD USE THIS MACRO LIBRARY. MACLIB I8080 ;8080 PEOPLE MUST USE THIS ONE. *** DEFINE SOME SYSTEM EQUATES. * ROM EQU 0F000H ;BEGINNING OF ROMMABLE CODE FALSE EQU 0 TRUE EQU NOT FALSE *** MOST PEOPLE WILL BE ABLE TO USE ONE OF THE FOLLOWING STANDARD * CONFIGURATIONS. IF NOT THEN YOU MUST WRITE YOUR OWN. REFER TO * THE VB3 USER'S GUIDE FOR THE NEEDED INFORMATION. * TO CHOOSE A CONFIGURATION SIMPLE REMOVE THE "*" FROM COL 1. * MACLIB X64X16 ;64x16, NON-INTERLACED (SAME AS VB1). * MACLIB X80X24 ;80x24, INTERLACED (TV STANDARDS). * MACLIB X80X33 ;SAME AS 80x24 BUT MORE LINES. * MACLIB X80X38 ;STILL MORE LINES. * MACLIB X80X51 ;EXAMPLE OF LOTS OF LINES. * MACLIB X132X28 ;EXAMPLE OF A WIDE SCREEN. MACLIB X ;CUSTOM CONFIGURATION. NORMAL EQU 3 ;NORMAL ATTRIBUTE REVERSE EQU 4 BLANK EQU 8 UNDERLINE EQU 16 BLINK EQU 32 STRIKE$THRU EQU 64 REDUCE EQU 128 MAX$ESC$SEQ EQU 32 ;MAX SIZE OF A ESCAPE SEQUENCE IF NCOLS=20 CODE EQU 0 ENDIF IF NCOLS=32 CODE EQU 1 ENDIF IF NCOLS=40 CODE EQU 2 ENDIF IF NCOLS=64 CODE EQU 3 ENDIF IF NCOLS=72 CODE EQU 4 ENDIF IF NCOLS=80 CODE EQU 5 ENDIF IF NCOLS=96 CODE EQU 6 ENDIF IF NCOLS=132 CODE EQU 7 ENDIF PAGE *** DEFINE SOME ASCII VALUES * BS EQU 08H ;BACK SPACE HT EQU 09H ;HORIZONTAL TAB LF EQU 0AH ;LINE FEED VT EQU 0BH ;VERTICAL TAB CR EQU 0DH ;CURSOR RETURN ESC EQU 1BH ;ESCAPE CHAR ICH EQU 40H ;INSERT CHAR CUU EQU 41H ;CURSOR UP CUD EQU 42H ;CURSOR DOWN CUF EQU 43H ;CURSOR FORWARD CUB EQU 44H ;CURSOR BACKWARD CNL EQU 45H ;CURSOR NEXT LINE CPL EQU 46H ;CURSOR PRECEDING LINE CHA EQU 47H ;CURSOR HORIZONTAL ABSOLUTE CUP EQU 48H ;CURSOR POSITION CHT EQU 49H ;CURSOR HORIZONTAL TAB ED EQU 4AH ;ERASE IN DISPLAY EL EQU 4BH ;ERASE IN LINE IL EQU 4CH ;INSERT LINE DL EQU 4DH ;DELETE LINE DCH EQU 50H ;DELETE CHAR SU EQU 53H ;SCROLL UP SD EQU 54H ;SCROLL DOWN CTC EQU 57H ;CURSOR TAB CONTROL CVT EQU 59H ;CURSOR VERTICAL TAB CBT EQU 5AH ;CURSOR BACKWARD TAB CVA EQU 5BH ;CURSOR VERTICAL ABSOLUTE SGR EQU 6DH ;SELECT GRAPHIC RENDITION PAGE *** DEFINE SOME USEFUL MACROS * * CMPD REGP ;DOES A 16 BIT COMPARE ON HL-REGP * * MXI REGP,ROW,COL ;SETS THE 16 BIT REGISTER REG TO THE VALUE * ; ROW*256+COL CMPD MACRO REGP LOCAL CMPD1 MOV A,H CMP REGP JRNZ CMPD1 MOV A,L CMP REGP+1 CMPD1: ENDM MXI MACRO REGP,ROW,COL LOCAL X,Y X SET ROW Y SET COL LXI REGP,X*256+Y ENDM PAGE *** VIDEO DRIVER SUBROUTINES * * ENTRIES POINTS ARE: * * VBINIT - TO INITALIZE THE HARDWARE AND SOFTWARE * VBIN - TO GET A KEYSTROKE FROM THE KEYBOARD * VBOUT - TO OUTPUT A CHAR TO THE VIDEO * VBSTAT - TO STATUS THE KEYBOARD * * CALLING SEQUENCES: * * CALL VBINIT * * CALL VBIN * STA KEYSTROKE ;RESULT IN REG A * * * MVI C,DATA ;OUTPUT CHAR IN REG C * MOV C,A * CALL VBOUT * * CALL VBSTAT ;RETURNS REG A = 0 IF * ;NO KEYSTROKE AVAILABLE, ELSE * ;RETURNS REG A = 0FFH. * JMP VBINIT JMP VBIN JMP VBOUT JMP VBSTAT VBINIT: OUT KSTAT ;ENABLE THE VB3 BOARD. MVI A,NORMAL STA ATTRIBUTE ;SET DEFAULT ATTRIBUTE MVI A,NROWS-1 STA LASTROW ;INITALIZE LASTROW TO NROWS-1. XRA A STA ESC$MODE ;NOT IN ESCAPE MODE CALL CTC5 ;CLEAR ALL HORIZONTAL TAB STOPS CALL CTC6 ;CLEAR ALL VERTICAL TAB STOPS LXI H,0 CALL EEOS ;CLEAR THE SCREEN CALL CURON ;PUT THE CURSOR ON THE SCREEN ; INITALIZE ALL OF THE CONTROL REGISTERS OUT VTAC+14 OUT VTAC+10 ;RESET THE VTAC MVI A,HCOUNT-1 OUT VTAC+0 MVI A,(INTERLACED*128)+0111$100B OUT VTAC+1 IF CRT5027 OR NOT INTERLACED MVI A,(SCANR-1)*8+CODE ELSE MVI A,(SCANR-2)*8+CODE ENDIF OUT VTAC+2 MVI A,SKEW*64+NROWS-1 OUT VTAC+3 IF INTERLACED MVI A,(SCANF-513)/2 ELSE MVI A,(SCANF-256)/2 ENDIF OUT VTAC+4 MVI A,(SCANF-NROWS*SCANR)/4+8 OUT VTAC+5 ;TRY TO CENTER THE DATA ONTO THE SCREEN MVI A,NROWS-1 OUT VTAC+6 OUT VTAC+14 ;START TIMING CHAIN. OUT KDATA ;DISABLE THE VB3 BOARD RET VBSTAT: IN KSTAT ;STATUS THE KEYBOARD CMA ANI 1 RZ ;RETURN A ZERO IF NO DATA MVI A,0FFH RET ;ELSE RETURN A 0FFH. VBIN: CALL VBSTAT ;RETURN THE NEXT KEY JRZ VBIN ;WAIT UNTIL ONE IS AVAILABLE IN KDATA ;GET IT RET ; AND RETURN. ; VBOUT IS THE MAIN DISPLAY DRIVER FOR THE VB3 BOARD VBOUT: PUSH H ;FIRST, SAVE ALL REGISTERS PUSH D PUSH B OUT KSTAT ;AND ENABLE THE VB3 BOARD. CALL CUROFF ;THEN, TURN OFF THE CURSOR CALL PROCESS ;AND PROCESS THE CHAR. CALL CURON ;NOW, TURN THE CURSOR BACK ON OUT KDATA ;DISABLE THE VB3 BOARD. POP B ;AND RESTORE THE REGISTERS. POP D POP H RET ; ON ENTRY, REG HL = LOGICAL CURSOR ADDRESS AND REG C = DATA. PROCESS: LDA ESC$MODE ;SEE IF WE RECEIVED AN ESC CHAR. ORA A JNZ PROCESS$ESC$SEQ ;JIF WE ARE IN A ESCAPE SEQUENCE MOV A,C ;MOVE THE DATA TO REG A. CPI 80H ;CHECK FOR RANGE OF 80 TO FF JNC PROCESS$ESC ;IT IS A ESC SEQUENCE IF > 7FH CPI ESC ;CHECK FOR CONTROL CHARS. JZ DO$ESC ;IF MATCH, THE DO CONTROL CHAR. CPI CR JZ DO$CR CPI LF JZ DO$LF CPI HT JZ DO$HT CPI BS JZ DO$BS CPI VT JZ DO$VT CPI ' ' RC ;SKIP OTHER CONTROL CHARS JMP DO$DATA ;MUST BE A DATA CHAR DO$ESC: MVI A,1 STA ESC$MODE ;WE ARE NOW READING A ESC SEQ XRA A STA ESC$COUNTER ;INIT THE CTR FOR THE SEQUENCE STA ESC$POINTER RET PROCESS$ESC: CALL DO$ESC PROCESS$ESC$SEQ: LDA ESC$COUNTER CPI MAX$ESC$SEQ ;CHECK FOR BUFFER OVERFLOW JZ ABORT$ESC XCHG ;SAVE HL MOV L,A ;INDEX INTO BUFFER GOES TO HL MVI H,0 INR A STA ESC$COUNTER ;INCREMENT POINTER MOV A,C ;GET DATA ANI 7FH ;7 BITS ONLY LXI B,ESC$SEQ ;GET BASE OF BUFFER DAD B ;COMPUTE CURRENT CELL MOV M,A ;SAVE DATA XCHG ;RESTORE HL CPI '@' ;NOT A TERMINATOR IF < 40H RC MOV C,A ;SAVE THE DATA XRA A STA ESC$MODE ;ESC SEQ DONE, NOW PROCESS IT MOV A,C ;GET THE DATA AGAIN CPI ICH JZ DO$ICH ;JIF INSERT CHAR CPI CUU JZ DO$CUU ;JIF CURSOR UP CPI CUD JZ DO$CUD ;JIF CURSOR DOWN CPI CUF JZ DO$CUF ;JIF CURSOR FORWARD CPI CUB JZ DO$CUB ;JIF CURSOR BACK CPI CNL JZ DO$CNL ;JIF CURSOR NEXT LINE CPI CPL JZ DO$CPL ;JIF CURSOR PRECEDING LINE CPI CHA JZ DO$CHA ;JIF CURSOR HORIZONTAL ABSOLUTE CPI CUP JZ DO$CUP ;JIF CURSOR POSITION CPI CHT JZ DO$CHT ;JIF CURSOR HORIZONTAL TAB CPI ED JZ DO$ED ;JIF ERASE IN DISPLAY CPI EL JZ DO$EL ;JIF ERASE IN LINE CPI IL JZ DO$IL ;JIF INSERT LINE CPI DL JZ DO$DL ;JIF DELETE LINE CPI DCH JZ DO$DCH ;JIF DELETE CHAR CPI SU JZ DO$SU ;JIF SCROLL UP CPI SD JZ DO$SD ;JIF SCROLL DOWN CPI CTC JZ DO$CTC ;JIF CURSOR TAB CONTROL CPI CVT JZ DO$CVT ;JIF CURSOR VERTICAL TAB CPI CBT JZ DO$CBT ;JIF CURSOR BACKWARD TAB CPI CVA JZ DO$CVA ;JIF CURSOR VERTICAL ABSOLUTE CPI SGR JZ DO$SGR ;JIF SELECT GRAPHIC RENDITION CPI 7FH JZ DO$DEL RET ;NONE OF THE ABOVE, SO SKIP IT. DO$ICH: MVI A,1 ;INSERT CHARACTER CALL GET1P RZ MOV B,A ICH1: PUSH B CALL INSERT$CHAR POP B DJNZ ICH1 RET DO$CUU: MVI A,1 ;CURSOR UP CALL GET1P ;GET A PARAMETER, 1 IS DEFAULT RZ ;IF VALUE IS ZERO, THEN DONE. MOV B,A CUU1: PUSH B ;REPEAT TILL COUNT IS ZERO CALL UP POP B DJNZ CUU1 RET DO$CUD: MVI A,1 ;CURSOR DOWN CALL GET1P RZ MOV B,A CUD1: PUSH B CALL DOWN POP B DJNZ CUD1 RET DO$CUF: MVI A,1 CALL GET1P RZ MOV B,A CUF1: PUSH B CALL RIGHT POP B DJNZ CUF1 RET DO$CUB: MVI A,1 CALL GET1P RZ MOV B,A CUB1: PUSH B CALL LEFT POP B DJNZ CUB1 RET DO$CNL: MVI A,1 ;CURSOR NEXT LINE CALL GET1P RZ MOV B,A CNL1: PUSH B CALL NEXTLINE POP B DJNZ CNL1 RET DO$CPL: MVI A,1 ;CURSOR PRECEDING LINE CALL GET1P RZ MOV B,A CPL1: PUSH B CALL PREVLINE POP B DJNZ CPL1 RET DO$CHA: MVI A,1 ;CURSOR HORIZONTAL ABSOLUTE CALL GET1P DCR A CPI NCOLS RNC MOV L,A ;PUT THE CURSOR ON THAT COLUMN RET DO$CUP: CALL DO$CHA ;CURSOR POSITION (GOTO XY) JMP DO$CVA DO$CHT: MVI A,1 ;CURSOR HORIZONTAL TABULATION CALL GET1P RZ MOV B,A CHT1: PUSH B CALL DO$HT POP B DJNZ CHT1 RET DO$ED: MVI A,0 ;ERASE IN DISPLAY CALL GET1P JZ EEOS PUSH H CPI 1 JRNZ ED1 XCHG MXI H,0,0 MXI B,NORMAL,' ' CALL FILLS ;ERASE FROM START TO CURSOR JR ED2 ED1: CPI 2 JRNZ ED2 LXI H,0 CALL EEOS ;ERASE ALL OF DISPLAY ED2: POP H ;RESTORE CURSOR ADDRESS RET DO$EL: MVI A,0 ;ERASE IN LINE CALL GET1P JZ EEOL ;ERASE FROM CURSOR TO END OF LINE PUSH H CPI 1 JRNZ EL1 XCHG MOV H,D MVI L,0 MXI B,NORMAL,' ' CALL FILLS ;ERASE FROM THE START OF LINE TO CURSOR JR EL2 EL1: CPI 2 JRNZ EL2 MVI L,0 CALL EEOL ;ERASE THE ENTIRE LINE EL2: POP H RET DO$IL: MVI A,1 ;INSERT LINE CALL GET1P RZ MOV B,A IL1: PUSH B CALL INSERT$LINE POP B DJNZ IL1 RET DO$DL: MVI A,1 ;DELETE LINE CALL GET1P RZ MOV B,A DL1: PUSH B CALL DELETE$LINE POP B DJNZ DL1 RET DO$DCH: MVI A,1 ;DELETE CHARACTER CALL GET1P RZ MOV B,A DCH1: PUSH B CALL DELETE$CHAR POP B DJNZ DCH1 RET DO$SU: MVI A,1 ;SCROLL UP CALL GET1P RZ MOV B,A SU1: PUSH B CALL ROLLUP POP B DJNZ SU1 RET DO$SD: MVI A,1 ;SCROLL DOWN CALL GET1P RZ MOV B,A SD1: PUSH B CALL ROLLDOWN POP B DJNZ SD1 RET DO$CTC: XRA A ;CURSOR TAB CONTROL CTC$A: CALL GET1P INR A RZ MOV C,A PUSH H CALL PROCESS$CTC POP H MVI A,255 JR CTC$A PROCESS$CTC: DCR C JRZ CTC0 DCR C JRZ CTC1 DCR C JRZ CTC2 DCR C JRZ CTC3 DCR C JRZ CTC4 DCR C JRZ CTC5 DCR C JRZ CTC6 RET CTC0: MVI H,0 LXI D,HTABS DAD D MVI M,255 RET CTC1: MOV L,H MVI H,0 LXI D,VTABS DAD D MVI M,255 RET CTC2: MVI H,0 LXI D,HTABS DAD D MVI M,0 RET CTC3: MOV L,H MVI H,0 LXI D,VTABS DAD D MVI M,0 RET CTC4: CTC5: LXI H,HTABS MVI B,NCOLS CTC5$A: MVI M,0 INX H DJNZ CTC5$A RET CTC6: LXI H,VTABS MVI B,NROWS CTC6$A: MVI M,0 INX H DJNZ CTC6$A RET DO$CVT: MVI A,1 ;CURSOR VERTICAL TABULATION CALL GET1P RZ MOV B,A CVT1: PUSH B CALL DO$VT POP B DJNZ CVT1 RET DO$CBT: MVI A,1 ;CURSOR BACKWARD TABULATION CALL GET1P RZ MOV B,A CBT1: PUSH B CALL DO$BT POP B DJNZ CBT1 RET DO$CVA: MVI A,1 ;CURSOR VERTICAL ABSOLUTE CALL GET1P DCR A CPI NROWS RNC MOV H,A RET DO$SGR: XRA A ;SELECT GRAPHIC RENDITION SGR$A: CALL GET1P MOV C,A LDA ATTRIBUTE INR C RZ CALL PROCESS$SGR STA ATTRIBUTE MVI A,255 JMP SGR$A PROCESS$SGR: DCR C JRZ SGR0 DCR C DCR C JRZ SGR2 DCR C DCR C JRZ SGR4 DCR C JRZ SGR5 DCR C DCR C JRZ SGR7 DCR C JRZ SGR8 DCR C JRZ SGR9 DCR C JRZ SGR10 DCR C JRZ SGR11 DCR C JRZ SGR12 DCR C JRZ SGR13 RET SGR0: MVI A,3 RET SGR2: ORI REDUCE RET SGR4: ORI UNDERLINE RET SGR5: ORI BLINK RET SGR7: ORI REVERSE RET SGR8: ORI BLANK RET SGR9: ORI STRIKE$THRU RET SGR10: ORI 3 RET SGR11: ANI 0FCH ORI 2 RET SGR12: ANI 0FCH ORI 1 RET SGR13: ANI 0FCH RET DO$DEL: PUSH H LXI H,VIDEO LXI B,NROWS*NCOLS DO$DEL1: MOV M,L INX H DCX B MOV A,C ORA B JRNZ DO$DEL1 POP H RET GET1P: MOV D,A ;SAVE THE DEFAULT VALUE MVI E,0 ;ZERO THE ACCUMULATOR LXI B,ESC$SEQ-1 ;POINT TO THE ESC STRING PUSH H ;SAVE THE CURSOR ADDRESS MORE: NO$GOOD: LDA ESC$POINTER INR A ;COMPUTE THE INDEX FOR THE NEXT BYTE LXI H,ESC$COUNTER CMP M ;SEE IF THERE IS ANY MORE JRZ NO$MORE ;JIF NONE STA ESC$POINTER ;UPDATE THE POINTER MOV L,A MVI H,0 DAD B ;POINT TO THE NEXT CHAR TO COME OUT MOV A,M ;GET IT CPI ';' ;CHECK FOR A SEPERATER JRZ NO$MORE ;JIF NUMBER IS DONE SUI '0' JRC NO$GOOD CPI 10 JRNC NO$GOOD ;JIF CHAR IS NOT FROM 0 TO 9 MOV D,A ;SAVE THE VALUE MOV A,E ;MULTIPLY THE ACCUMULATED VALUE BY 10 ADD A ;*2 MOV E,A ADD A ;*4 ADD A ;*8 ADD E ;*10 DONE! ADD D ;ADD IN NEW DIGIT MOV E,A ;RETURN IT TO THE ACCUMULATOR MOV D,A ;WIPE OUT OLD VALUE JR MORE ;GO FOR THE NEXT DIGIT NO$MORE: MOV A,D ;GET THE VALUE ORA A ;SET FLAGS POP H ;RESTORE CURSOR ADDRESS RET ABORT$ESC: XRA A STA ESC$MODE ;RESET THE ESCAPE FLAG RET ; PUT A DATA CHAR ON THE SCREEN AND ADVANCE THE CURSOR. PUT$CHAR: PUSH H ;SAVE THE LOGICAL CURSOR ADDRESS. CALL GETBA ;GET THE PHYSICAL CURSOR ADDRESS. LXI D,OFFSET MOV M,C ;PUT THE DATA THERE. DAD D ;COMPUTE THE ADDRESS OF THE GOVERNING ATTRIBUTE MOV M,B ;PUT THE ATTRIBUTE HERE. POP H ;GET THE LOGICAL CURSOR ADDRESS BACK. RET DO$DATA: LDA ATTRIBUTE ;GET THE CURRENT ATTRIBUTE MOV B,A ;SET IT UP FOR PUT$CHAR. CALL PUT$CHAR CALL RIGHT ;MOVE THE CURSOR RIGHT. RNZ ;DONE IF THE CURSOR DIDN'T WRAP AROUND. * JMP NEXTLINE ;ELSE, WE MUST MOVE THE CURSOR TO THE NEXT LINE ; PUT THE CURSOR ON COLUMN 1 OF THE NEXT LINE. SCROLL THE SCREEN ; IF THE CURSOR WAS ON THE LAST LINE. NEXTLINE: MVI L,0 ;PUT THE CURSOR ON COL 1 OF THE NEXT LINE * JMP DO$LF ;AND DO A LINE FEED. ; MOVE THE CURSOR DOWN ONE LINE. SCROLL THE SCREEN ; IF THE CURSOR WAS ON THE LAST LINE. DO$LF: CALL DOWN RNZ MVI H,NROWS-1 PUSH H CALL ROLLUP LXI H,(NROWS-1)*256 CALL EEOL POP H RET ; MOVE THE CURSOR TO COL 1 OF THE CURRENT LINE. DO$CR: MVI L,0 RET ; BACK THE CURSOR BY ONE POSITION. DO$BS: CALL LEFT CZ UP PUSH H CALL GETBA MVI M,' ' POP H RET ; DO A HORIZONTAL TABULATION DO$HT: MOV C,L ;SAVE THE COLUMN NUMBER LXI D,HTABS ;POINT TO THE HORIZ TAB TABLE DO$HT1: CALL RIGHT ;MOVE RIGHT PUSH H XRA A ;GET A ZERO MOV H,A DAD D ;POINT TO HTABS[COL] ORA M ;SEE IF TRUE POP H RNZ ;DONE IF FOUND A TAB STOP MOV A,L CMP C RZ ;DONE IF NO TAB STOPS JR DO$HT1 ;CONTINUE LOOKING FOR TAB STOPS ; DO A VERTICAL TABULATION DO$VT: MOV C,H ;SAVE THE ROW NUMBER LXI D,VTABS ;POINT TO THE VERTICAL TAB TABLE DO$VT1: CALL DOWN ;MOVE DOWN PUSH H XRA A ;GET A ZERO MOV L,H MOV H,A DAD D ;POINT TO VTABS[ROW] ORA M ;SEE IF TRUE POP H RNZ ;DONE IF FOUND A TAB STOP MOV A,H CMP C RZ ;DONE IF NO TAB STOPS JR DO$VT1 ;CONTINUE LOOKING FOR TAB STOPS ; DO A BACKWARD TABULATION DO$BT: MOV C,L ;SAVE THE COLUMN NUMBER LXI D,HTABS ;POINT TO THE HORIZ TAB TABLE DO$BT1: CALL LEFT ;MOVE LEFT PUSH H XRA A ;GET A ZERO MOV H,A DAD D ;POINT TO HTABS[COL] ORA M ;SEE IF TRUE POP H RNZ ;DONE IF FOUND A TAB STOP MOV A,L CMP C RZ ;DONE IF NO TAB STOPS JR DO$BT1 ;CONTINUE LOOKING FOR TAB STOPS ; MOVE THE CURSOR UP. UP: MOV A,H DCR H ORA A RNZ MVI H,NROWS-1 RET ; MOVE THE CURSOR DOWN. DOWN: INR H MVI A,NROWS CMP H RNZ MVI H,0 RET ; MOVE THE CURSOR LEFT. LEFT: MOV A,L DCR L ORA A RNZ MVI L,NCOLS-1 RET ; MOVE THE CURSOR RIGHT. RIGHT: INR L MVI A,NCOLS CMP L RNZ MVI L,0 RET ; MOVE THE CURSOR TO THE BEGINNING OF THE PREVIOUS LINE PREVLINE: MVI L,0 CALL UP RNZ MVI H,0 PUSH H CALL ROLLDOWN LXI H,0 CALL EEOL POP H RET ; ERASE FROM THE CURSOR POSITION TO THE END OF THE SCREEN. EEOS: MXI D,NROWS-1,NCOLS-1 MXI B,NORMAL,' ' JR FILLS ; ERASE FROM THE CURSOR TO THE END OF THE CURRENT LINE. EEOL: MOV D,H MVI E,NCOLS-1 MXI B,NORMAL,' ' JR FILLS ; FILL THE SCREEN WITH THE DATA IN REG C, THE ATTRIBUTE IN REG B ; FROM X,Y LOCATION HL TO DE. FILLS: PUSH H CALL GETBA ;GET ADDR OF START XCHG CALL GETBA ;GET ADDR OF FINI CMPD D ;COMPARE FINI-START XCHG JRNC FILLS1 ;JIF AREA TO FILL DOES NOT WRAP PUSH D ;SAVE FINI ADDR PUSH B LXI D,VIDEO + NROWS * ((NCOLS + 15) AND 0FFF0H) - 1 CALL FILLS2 ;FILL FROM START TO END OF SCREEN POP B POP D LXI H,VIDEO ;FILL FROM START OF SCREEN TO FINI ADDR FILLS1: CALL FILLS2 ;FILL THE SCREEN POP H RET FILLS2: PUSH B PUSH H PUSH D CALL FILL ;FILL IN THE DATA POP H POP D LXI B,OFFSET DAD B XCHG DAD B POP B MOV C,B CALL FILL ;FILL IN THE ATTRIBUTES RET FILL: MOV M,C INX H CMPD D JRC FILL JRZ FILL RET ; SCROLL THE SCREEN UP BY ONE LINE. ROLLUP: LDA LASTROW INR A CPI NROWS JRNZ ROLLUP1 XRA A ROLLUP1: OUT VTAC+6 STA LASTROW RET ; SCROLL THE SCREEN DOWN ONE LINE ROLLDOWN: LDA LASTROW ORA A JRNZ ROLLDOWN1 MVI A,NROWS ROLLDOWN1: DCR A OUT VTAC+6 STA LASTROW RET ; TURN THE CURSOR ON. ; THE LOGICAL ADDRESS OF THE CURSOR MUST BE IN REG HL. CURON: SHLD CURADR MOV A,L OUT VTAC+12 LDA LASTROW INR A ADD H CPI NROWS JRC CURON1 SUI NROWS CURON1: OUT VTAC+13 RET ; TURN THE CURSOR OFF. ; THE LOGICAL ADDRESS OF THE CURSOR IS RETURNED IN REG HL. CUROFF: LHLD CURADR MVI A,0FFH OUT VTAC+12 RET ; THE INTERNAL DESCRIPTION OF THE NEXT FOUR PROCEDURES ARE ; THEIR PASCAL COUNTERPARTS. THE PROCEDURES WERE FIRST WRITTEN ; IN PASCAL AND THEN TRANSLATED INTO ASSEMBLY. IN EACH CASE I ; HAVE ASSUMED THAT THE FOLLOWING DECLARATIONS HAVE BEEN MADE. ; CONST ; NCOLS = 80; (* OR WHATEVER *) ; NROWS = 24; (* OR WHATEVER *) ; ; TYPE ; COLS = 0..NCOLS-1; ; ROWS = 0..NROWS-1; ; LINE = RECORD OF ; COL : ARRAY[COLS] OF CHAR ; END; ; SCREEN = ARRAY [ROWS] OF LINE; ; ; VAR ; R : ROWS; (* THE CURRENT CURSOR ROW ADDRESS *) ; C : COLS; (* THE CURRENT CURSOR COLUMN ADDRESS *) ; ROW : SCREEN; (* THIS IS THE VB3 MEMORY MAPPED SCREEN *) ; RI : ROWS; (* A COUNTER FOR ROWS *) ; CI : COLS; (* A COUNTER FOR COLUMNS *) ; BLANK_LINE : LINE; (* ASSUMED TO BE A BLANK LINE *) ; TO REFERENCE A CHARACTER ON THE SCREEN, SAY: ; ; ROW[RI].COL[CI] ; ; FOR SOME VALUES OF RI AND CI. ; ; TO REFERENCE A ENTIRE LINE OF THE SCREEN, SAY: ; ; ROW[RI] ; ; FOR SOME VALUE OF RI. ; PROCEDURE INSERT$LINE; ; BEGIN ; FOR RI := NROWS-1 TO R+1 DO ; ROW[RI] := ROW[RI-1]; ; ROW[R] := BLANK_LINE; ; END; INSERT$LINE: PUSH H MOV C,H INR C MXI H,NROWS-1,0 MXI D,NROWS-1,0 IL$LOOP: MOV A,H CMP C JRC IL$EXIT DCR H CALL MOVE$LINE DCR D JR IL$LOOP IL$EXIT: CALL EEOL POP H RET ; PROCEDURE DELETE$LINE; ; BEGIN ; FOR RI := R TO NROWS-2 DO ; ROW[RI] := ROW[RI+1]; ; ROW[NROWS-1] := BLANK_LINE; ; END; DELETE$LINE: PUSH H MVI L,0 MOV D,H MOV E,L DL$LOOP: MVI A,NROWS-2 CMP D JRC DL$EXIT INR H CALL MOVE$LINE INR D JR DL$LOOP DL$EXIT: CALL EEOL POP H RET ; PROCEDURE INSERT$CHAR; ; BEGIN ; FOR CI := NCOLS-1 DOWNTO C+1 DO ; ROW[R].COL[CI] := ROW[R].COL[CI-1]; ; ROW[R].COL[C] := ' '; ; END; INSERT$CHAR: PUSH H MOV C,L INR C MVI L,NCOLS-1 MOV D,H MOV E,L ICH$LOOP: MOV A,L CMP C JRC ICH$EXIT DCR L CALL MOVE$CHAR DCR E JR ICH$LOOP ICH$EXIT: MXI B,NORMAL,' ' CALL PUT$CHAR POP H RET ; PROCEDURE DELETE$CHAR; ; BEGIN ; FOR CI := C TO NCOLS-2 DO ; ROW[R].COL[CI] := ROW[R].COL[CI+1]; ; ROW[R].COL[NCOLS-1] := ' '; ; END; DELETE$CHAR: PUSH H MOV D,H MOV E,L DCH$LOOP: MVI A,NCOLS-2 CMP E JRC DCH$EXIT INR L CALL MOVE$CHAR INR E JR DCH$LOOP DCH$EXIT: MXI B,NORMAL,' ' CALL PUT$CHAR POP H RET MOVE$LINE: PUSH H PUSH D PUSH B LXI B,OFFSET CALL GETBA PUSH H DAD B XCHG CALL GETBA PUSH H DAD B XCHG LXI B,NCOLS LDIR POP D POP H LXI B,NCOLS LDIR POP B POP D POP H RET MOVE$CHAR: PUSH H PUSH D PUSH B CALL GETBA XCHG CALL GETBA LDAX D MOV M,A LXI B,OFFSET DAD B XCHG DAD B MOV A,M STAX D POP B POP D POP H RET ; CONVERT A LOGICAL ADDRESS TO A PHYSICAL ADDRESS. ; ON ENTRY, HL CONTAINS THE LOGICAL ADDRESS. ; ON EXIT, HL CONTAINS THE PHYSICAL ADDRESS. ; A LOGICAL ADDRESS IS IN THE FORM (ROW, COLUMN) WITH ROW IN REG H AND COLUMN ; IN REG L. ROW MUST BE IN THE RANGE OF 0 TO NROWS-1 AND COLUMN MUST BE IN ; THE RANGE OF 0 TO NCOLS-1. ; A PHYSICAL ADDRESS IS THE ACTUAL MEMORY ADDRESS IN THE VIDEO MEMORY. GETBA: PUSH B LDA LASTROW INR A ADD H CPI NROWS JRC GETBA1 SUI NROWS GETBA1: MOV C,A MVI B,0 MOV A,L LXI H,MAPPER DAD B DAD B MOV C,A MOV A,M INX H MOV H,M MOV L,A DAD B POP B RET MAPPER: J SET (NCOLS+15) AND 0FFF0H I SET 0 REPT NROWS DW VIDEO+J*I I SET I+1 ENDM ENDROM EQU $ ORG VIDEO+NCOLS*NROWS ATTRIBUTE: DS 1 ;THE CURRENT SCREEN ATTRIBUTE CURADR: DS 2 ;THE LOGICAL CURSOR ADDRESS LASTROW: DS 1 ;THE LAST ROW DISPLAYED ON THE SCREEN ESC$MODE: DS 1 ;BOOLEAN, TRUE IF RECEIVING AN ESCAPE SEQUENCE ESC$COUNTER: DS 1 ;INDEX INTO ESC$SEQ ESC$POINTER: DS 1 ;SAME AS ABOVE EXCEPT USED FOR READING ESC$SEQ: DS MAX$ESC$SEQ ;HOLDS THE ESCAPE SEQUENCE HTABS: DS NCOLS ;USED FOR SETTING HORIZONTAL TABS VTABS: DS NROWS ;SAME FOR VERTICAL TABS ENDRAM EQU $ ORG ENDROM ;THIS ADDRESS WILL APPEAR ON THE CONSOLE AFTER ; THE ASSEMBLY. END ROM