;******************************************************** ;* * ;* CRT DRIVER FOR 6845 CRT CONTROLLER AND SMC * ;* 8002 CHARACTER GENERATOR/ATTRIBUTES CHIP * ;* * ;******************************************************** ; ; ; OUTPUT CHARACTER PASSED IN C TO VIDEO DISPLAY ; CRTOUT: LD HL,(ESCVEC) LD A,H OR L ;TEST IF IN AN ESCAPE SEQUENCE JR NZ,CRT2 ;JUMP IF 'ESCVEC' IS NON-ZERO RES 7,C ;CONFINE CHARACTERS TO 0..127 RANGE LD A,C CP ' ' JR C,CRT3 ;JUMP IF A CONTROL CHARACTER CALL DISPLAY RET ; ; CRT2: LD A,C ; GET THE CHARACTER OR A ; NULL? RET Z ; YES, IGNORE LD DE,0 LD (ESCVEC),DE ;UNCONDITIONALLY CLEAR 'ESCVEC' JP (HL) ;THEN GO TO ROUTINE @HL ; ; ; CRT3: LD HL,CTLTAB LD BC,CTLSIZ/3 CALL SEARCH ;SEARCH FOR CONTROL CHARACTER IN TABLE RET NZ JP (HL) ; ; CTLTAB: DEFB 'G'-64 DEFB 'H'-64 DEFB 'I'-64 DEFB 'J'-64 DEFB 'K'-64 DEFB 'L'-64 DEFB 'M'-64 DEFB 'Q'-64 DEFB 'X'-64 DEFB 'Z'-64 DEFB '['-64 DEFB '^'-64 DEFB '_'-64 DEFW STUFF ;CTL-_ ... DISPLAY CONTROL CHARACTERS DEFW HOMEUP ;CTL-^ ... CURSOR HOME DEFW ESCAPE ;CTL-[ ... ESCAPE DEFW CLRALL ;CTL-Z ... CLEAR SCREEN DEFW CLREOL ;CTL-X ... CLEAR TO END OF LINE DEFW CLREOS ;CTL-Q ... CLEAR TO END OF SCREEN DEFW RETURN ;CTL-M ... CARRIAGE RETURN DEFW RIGHT ;CTL-L ... CURSOR RIGHT DEFW UPLINE ;CTL-K ... INVERSE LINEFEED/CURSOR UP DEFW DNLINE ;CTL-J ... LINEFEED/CURSOR DOWN DEFW HTAB ;CTL-I ... HORIZONTAL TAB DEFW LEFT ;CTL-H ... BACKSPACE/CURSOR LEFT DEFW BELL ;CTL-G ... AUDIBLE BELL CTLSIZ EQU $-CTLTAB ; ; ; ; ; DISPLAY: LD HL,(CURSOR) LD DE,CHRMEM ADD HL,DE ;GET POINTER TO CHARACTER IN DISPLAY EX DE,HL LD HL,4096 ADD HL,DE ;GET POINTER TO MATCHING ATTRIBUTE EX DE,HL LD A,(ATTRIB) LD (HL),C ;OUTPUT CHARACTER AND ATTRIBUTE LD (DE),A LD A,(COL) INC A ;INCREMENT COLUMN NUMBER CP 80 JR NC,DISP2 ;CHECK FOR AUTO NEWLINE IF AT END LD (COL),A ;ELSE STORE UPDATED COLUMN# LD HL,(CURSOR) INC HL RES 3,H ;BUMP CURSOR POINTER MODULO 2048 LD (CURSOR),HL CALL SETCSR ;MARK NEXT CURSOR POSITION RET ; DISP2: LD HL,CRTFLG BIT AUTONL,(HL) RET Z ;EXIT IF AUTO NEWLINE DISABLED XOR A LD (COL),A ;RESET COLUMN NUMBER AND DO LINEFEED CALL DNLINE RET ; ; ; ; ; BELL: LD A,2 ;TURN OFF DELAY IS 2/250 SECOND LD (BELTIM),A LD A,BUZZER+ON ;NOW START UP THE BELL OUT (PORT0),A RET ; ; ; ; ; ; ESCAPE: LD HL,ESCSEQ ;PROCESS SECOND CHARACTER OF ESCAPE LD (ESCVEC),HL ; SEQUENCE NEXT TIME RET ; ; STUFF: LD HL,DISPLAY LD (ESCVEC),HL ;SET LEAD-IN SEQUENCE STATE RET ; FOR CONTROL CHAR OUTPUT MODE ; ; ; HTAB: LD A,(COL) AND 00000111B LD C,A LD A,8 SUB C ;COMPUTE DISTANCE TO NEXT TAB STOP LD D,A LD E,0 JR CSRMOV ;ADVANCE COLUMN# AND CURSOR TO NEXT TAB ; LEFT: LD DE,0FF00H ;DECREMENT COLUMN# JR CSRMOV ; RIGHT: LD DE,0100H ;INCREMENT COLUMN# JR CSRMOV ; UP: LD DE,00FFH ;DECREMENT ROW# JR CSRMOV ; DOWN: LD DE,0001H ;INCREMENT ROW# CSRMOV: LD HL,(RC) ;GET CURRENT ROW# IN L AND COL# IN H LD A,L ADD A,E ;ADD -1,0,OR 1 TO ROW# CP 24 RET NC ;EXIT IF ROW OUT OF RANGE LD L,A LD A,H ADD A,D ;ADD -1,0 OR 1 TO COLUMN# CP 80 RET NC ;EXIT IF COLUMN OUT OF BOUNDS LD H,A GOTOXY: LD (RC),HL ;STORE NEW ROW/COLUMN VALUES LD B,0 LD C,H ;PUT COLUMN# INTO BC AS 16 BITS LD H,0 CALL MULT80 ;MULTILPY 16 BIT ROW# BY 80 ADD HL,BC ;HL=(ROW*80)+COL LD DE,(START) ADD HL,DE ;ADD CRTC START ADDRESS TO POINTER LD A,H AND 00000111B ;MASK OFF FOR MODULO 2048 ROLL-AROUND LD H,A LD (CURSOR),HL ;STORE NEW RELATIVE CURSOR POINTER SETCSR: LD A,(MOVECS) OR A ;TEST IF NEW-CURSOR FLAG HAS BEEN SET RET NZ ;EXIT NOW IF SO INC A ;ELSE GET A ONE LD (MOVECS),A ;SET FLAG FOR INTERRUPT ROUTINE LD A,11010111B ;AND ENABLE VSYNC INTERRUPT FROM CTC OUT (CTCA3),A LD A,1 OUT (CTCA3),A RET ; ; ; ZAPCSR: DI LD A,00000011B OUT (CTCA3),A ;DISABLE VSYNC INTERRUPT FROM CTCA3 EI XOR A LD (MOVECS),A ;RESET CURSOR-MOVE FLAG LD HL,(CURSOR) LD DE,ATTMEM ADD HL,DE ;POINT TO CURRENT CURSOR ATTRIBUTE BYTE LD A,(HL) BIT 7,A ;TEST IF CURSOR HAS BEEN TURNED ON YET RET Z ; AND EXIT IF NOT XOR 10010000B ;ELSE RESET BIT 7 AND INVERT BIT 4 OF LD (HL),A ; CURSOR BYTE IF VSYNC HAS CHANGED THEM RET ; ; ; MULT80: ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL LD D,H LD E,L ;DE=ROW*16 ADD HL,HL ADD HL,HL ;HL=ROW*64 ADD HL,DE ;HL=(ROW*64)+(ROW*16) RET ; ; ; UPLINE: LD A,(ROW) OR A JR NZ,UP ;DO CURSOR-UP IF NOT ON TOP LINE LD DE,-80 ;ELSE SCROLL SCREEN DOWN LD BC,0 JR LFEED ; ; DNLINE: LD A,(ROW) CP 23 JR NZ,DOWN ;DO CURSOR-DOWN IF NOT ON BOTTOM ROW LD DE,80 ;ELSE SCROLL SCREEN UP LD BC,23*80 LFEED: LD HL,CRTFLG BIT NOSCRL,(HL) RET NZ ;EXIT IF SCROLL IS DISABLED LD (NEWLIN),BC ;STORE RELATIVE ADDRESS OF NEW LINE LD HL,(START) ADD HL,DE ;ADD +80/-80 TO 6845 START ADDRESS REG LD A,H AND 00000111B ;DO MODULO 2048 ROLL-AROUND LD H,A LD (START),HL ;STORE NEW STARTING ADDRESS LD HL,(RC) CALL GOTOXY ;COMPUTE NEW CURSOR AND ARM INTERRUPT LD HL,(START) ;NOW DO ACTUAL LINE FEED LD A,12 OUT (CRTADD),A ;SELECT 6845 REGSITER #12 LD A,H OUT (CRTDAT),A ;OUTPUT MSB OF START ADDRESS LD A,13 OUT (CRTADD),A ;SELECT 6845 REGISTER #13 LD A,L OUT (CRTDAT),A ;OUTPUT LSB OF START ADDRESS LD DE,(NEWLIN) ADD HL,DE ;GET RELATIVE ADDRESS OF NEW BLANK LINE LD A,H AND 00000111B ;MAKE SURE TO ROLL-AROUND MOD 2048 LD H,A LD BC,80 CALL CLRLINE ;CLEAR NEW BOTTOM LINE ON SCREN RET ; ; ; ; RETURN: LD HL,(RC) LD H,0 CALL GOTOXY ;RESET COLUMN# TO ZERO RET ; ; ; CLRLINE: LD A,00000011B ; GET CTC RESET OUT (CTCA3),A ; TURN OFF VSYNC INTERRUPT LD DE,CHRMEM ADD HL,DE EX DE,HL LD HL,4096 ADD HL,DE EX DE,HL LD A,(BLANK) LD (HL),A ;STORE A BLANK AT START OF CHAR LINE LD A,(ATTRIB) LD (DE),A ;STORE ATTRIBUTE AT START OF ATTR LINE DEC BC LD A,B OR C ;DECREMENT BYTECOUNT AND TEST IF=0 JR Z,CLRLNX ;EXIT IF DONE ALERADY PUSH DE ;ELSE SAVE LINE POINTER AND BYTECOUNT PUSH BC LD D,H LD E,L INC DE LDIR ;FILL CHARACTER LINE WITH SPACES POP BC POP HL ;RESTORE POINTER AND BYTECOUNT LD D,H LD E,L INC DE LDIR ;FILL ATTRIBUTE LINE WITH ATTRIB BYTE CLRLNX: LD A,(MOVECS) ;GET VSYNC SETUP FLAG OR A ;WANTED A VSYNC INTERRUPT? RET Z ;NO LD A,11010111B ;YES, GET INTERRUPT ENABLE OUT (CTCA3),A ;AND SEND IT LD A,1 OUT (CTCA3),A ;LOAD TIME CONSTANT TOO RET ; ; ; CLREOS: LD A,23 LD HL,ROW SUB (HL) ;COMPUTE NUMBER OF ROWS TO SCREEN-END LD H,0 LD L,A CALL MULT80 ;MULTIPLY BY 80 GIVING RESULT IN HL EX DE,HL JR CLR2 ; CLREOL: LD DE,0 CLR2: LD A,80 LD HL,COL SUB (HL) ;COMPUTE NUMBER OF COLUMNS TO LINE-END LD H,0 LD L,A ADD HL,DE ;SUM IS TOTAL CHARACTERS TO ERASE LD B,H LD C,L LD HL,(CURSOR) CALL CLRLINE ;GO FILL DISPLAY WITH SPACES/ATTRIBUTES CALL SETCSR ;PUT CURSOR BACK IN ORIGINAL SPOT RET ; ; ; CLRALL: LD HL,CHRMEM LD DE,CHRMEM+1 LD BC,2047 LD A,(BLANK) LD (HL),A LDIR ;FILL CHARACTER MEMORY WITH SPACES LD HL,ATTMEM LD DE,ATTMEM+1 LD BC,2047 LD A,(ATTRIB) LD (HL),A LDIR ;FILL ATTRIBUTE MEMORY WITH NULL BYTES HOMEUP: LD HL,0 CALL GOTOXY ;RESET ROW/COLUMN NUMBERS TO ZERO RET ; ; ; ; ; COMPRESS: PUSH BC PUSH DE PUSH HL PUSH BC LD BC,CHRMEM ADD HL,BC EX DE,HL ADD HL,BC EX DE,HL POP BC LDIR ;COMPRESS CONTENTS OF CHARACTER MEMORY CALL ZAPCSR POP HL POP DE LD BC,ATTMEM ADD HL,BC EX DE,HL ADD HL,BC EX DE,HL POP BC LDIR ;COMPRESS CONTENTS OF ATTRIBUTE MEMORY RET ; ; ; ; EXPAND: PUSH BC PUSH DE PUSH HL PUSH BC LD BC,CHRMEM ADD HL,BC EX DE,HL ADD HL,BC EX DE,HL POP BC LDDR ;EXPAND CONTENTS OF CHARACTER MEMORY CALL ZAPCSR POP HL POP DE LD BC,ATTMEM ADD HL,BC EX DE,HL ADD HL,BC EX DE,HL POP BC LDDR ;EXPAND CONTENTS OF ATTRIBUTE MEMORY RET ; ; ; DELLINE: CALL RETURN ;DO CARRIAGE RETURN LD A,23 LD HL,ROW SUB (HL) ;COMPUTE # OF ROWS TO END OF SCREEN JP Z,CLREOL LD H,0 LD L,A CALL MULT80 ;MULTIPLY BY 80 LD B,H LD C,L ;RESULT IS BYTECOUNT FOR BLOCK MOVE LD DE,(CURSOR) LD HL,80 ADD HL,DE CALL COMPRESS ;COMPRESS SCREEN TO DELETE LINE LD HL,(START) LD DE,23*80 ADD HL,DE ;GET RELATIVE START OF LAST LINE LD A,H AND 00000111B LD H,A LD BC,80 CALL CLRLINE ;CLEAR BOTTOM LINE CALL SETCSR ;RE-DISPLAY THE CURSOR RET ; ; ; INSLINE: CALL RETURN ;DO CARRIAGE RETURN LD A,23 LD HL,ROW SUB (HL) ;COMPUTE # OF ROWS TO END OF SCREEN JP Z,CLREOL LD H,0 LD L,A CALL MULT80 ;MULTIPLY BY 80 LD B,H LD C,L ;RESULT IS BYTECOUNT FOR BLOCK MOVE LD HL,(CURSOR) ADD HL,BC DEC HL EX DE,HL LD HL,80 ADD HL,DE EX DE,HL CALL EXPAND ;EXPAND SCREEN TO MAKE NEW LINE CALL CLREOL ;CLEAR NEW LINE RET ; ; ; DELCHAR: LD HL,COL LD A,79 SUB (HL) ;COMPUTE NUMBER OF COLUMNS LEFT IN LINE JP Z,CLREOL LD B,0 LD C,A ;USE RESULT FOR LDIR BYTECOUNT PUSH BC LD HL,(CURSOR) LD D,H ;DE POINTS TO CHAR AT CURSOR LOCATION LD E,L INC HL ;HL POINTS ONE BYTE AHEAD OF THAT CALL COMPRESS POP BC LD HL,(CURSOR) ADD HL,BC LD BC,1 CALL CLRLINE ;PUT BLANK AT END OF LINE CALL SETCSR ;REPLACE DESTROYED CURSOR RET ; ; ; ; INSCHAR: LD HL,COL LD A,79 SUB (HL) ;COMPUTE NUMBER OF COLUMNS LEFT IN LINE JP Z,CLREOL LD B,0 LD C,A ;USE RESULT FOR LDDR BYTECOUNT LD HL,(CURSOR) ADD HL,BC LD D,H ;DE POINTS TO CHAR AT END OF LINE LD E,L DEC HL ;HL POINTS ONE BYTE BEFORE THAT CALL EXPAND LD HL,(CURSOR) LD BC,1 CALL CLRLINE ;PUT A BLANK AT CURSOR LOCATION CALL SETCSR ;REPLACE CURSOR RET ; ; ; ESCSEQ: LD A,C ;PUT LEAD-IN CHARACTER IN ACC LD HL,ESCTAB LD BC,ESCSIZ/3 CALL SEARCH ;SEARCH FOR SECOND CHAR OF ESCAPE SEQ RET NZ ; IN TABLE AND EXIT IF NO MATCH JP (HL) ;GO TO LEAD-IN ROUTINE ; ; ESCTAB: DEFB '=' ;CURSOR ADDRESSING DEFB 'Q' ;INSERT CHARACTER DEFB 'W' ;DELETE CHARACTER DEFB 'E' ;INSERT LINE DEFB 'R' ;DELETE LINE DEFB '*' ;CLEAR SCREEN DEFB ':' ;CLEAR SCREEN DEFB 'T' ;CLEAR TO END OF LINE DEFB 't' ;CLEAR TO END OF LINE DEFB 'Y' ;CLEAR TO END OF SCREEN DEFB 'y' ;CLEAR TO END OF SCREEN DEFB 'G' ;SET ATTRIBUTE DEFB 'M' ;SET GRAPHICS MODE DEFB '.' ;SET PARAMETER BYTE DEFW SETPARM DEFW SETMODE DEFW SETATTR DEFW CLREOS DEFW CLREOS DEFW CLREOL DEFW CLREOL DEFW CLRALL DEFW CLRALL DEFW DELLINE DEFW INSLINE DEFW DELCHAR DEFW INSCHAR DEFW SETRC ESCSIZ EQU $-ESCTAB ; ; ; ; SETRC: LD HL,SETROW LD (ESCVEC),HL RET ; ; ; SETROW: LD A,C ;ARRIVE HERE ON THIRD CHARACTER SUB ' ' ; OF CURSOR POSITIONING SEQUENCE RET C SETR2: SUB 24 JR NC,SETR2 ;MAKE SURE ROW# IS BETWEEN 0 AND 23 ADD A,24 LD (ROWTMP),A ;SAVE TEMPORARY ROW# LD HL,SETCOL LD (ESCVEC),HL ;GO TO 'SETCOL' ON NEXT CHARACTER RET ; ; ; SETCOL: LD A,C ;ARRIVE HERE ON FOURTH CHARACTER SUB ' ' ; OF ESC,'=',ROW,COL SEQUENCE RET C SETC2: SUB 80 JR NC,SETC2 ;MAKE SURE COL# IS BETWEEN 0 AND 79 ADD A,80 LD H,A ;PUT COLUMN# INTO H LD A,(ROWTMP) LD L,A ;PUT ROW# INTO L CALL GOTOXY ;GO COMPUTE RELATIVE CURSOR POINTER RET ; ; ; ; SETATTR: LD HL,SATTR2 LD (ESCVEC),HL RET ; ; ; SATTR2: LD A,C CALL ASCHEX ;CONVERT THIRD CHAR IN SEQUENCE TO HEX RET C ;EXIT IF OUT OF RANGE LD B,0 LD C,A LD HL,BLANK LD (HL),' ' ;USE ASCII SPACE FOR BLANKS LD A,00000011B ;USE ALPHANUMERIC ATTRIBUTE MODE BIT 3,C ;TEST IF ALPHA OR GRAPHICS MODE JR Z,SATTR3 LD (HL),0 ;SWITCH TO ZEROS FOR BLANKS AND LOAD LD A,(GRMODE) ; A WITH SELECTED GRAPHICS MODE BITS SATTR3: LD HL,BITTAB RES 3,C ADD HL,BC ;INDEX INTO BIT TABLE FOR ATTRIBUTES OR (HL) ;MERGE MODE AND ATTRIBUTE BITS LD (ATTRIB),A ;STORE NEW ATTRIBUTE BYTE RET ; ; ; BITTAB: DEFB 0 DEFB UNDLINE DEFB BLINK DEFB BLINK+UNDLINE DEFB REVERSE DEFB REVERSE+UNDLINE DEFB REVERSE+BLINK DEFB REVERSE+BLINK+UNDLINE ; ; ; ; SETMODE: LD HL,SMODE2 LD (ESCVEC),HL RET ; ; ; SMODE2: LD A,C AND 00000011B LD (GRMODE),A ;STORE BITS FOR GRAPHICS MODE FIELD RET ; OF ATTRIBUTE BYTE ; ; ; SETPARM: LD HL,SPARM2 LD (ESCVEC),HL RET ; ; SPARM2: LD A,C CALL ASCHEX RET C LD C,A AND 00000111B INC A ;TRANSFORM CODE TO NUMBER IN RANGE 1..8 LD B,A XOR A SCF SPARM3: RLA DJNZ SPARM3 ;DERRIVE BIT POSITION FROM CODE BYTE LD HL,CRTFLG BIT 3,C ;TEST IF PARAM BIT IS TO BE SET/RESET JR Z,SPARM4 OR (HL) ;SET PARAMETER BIT @HL LD (HL),A RET ; SPARM4: CPL AND (HL) ;RESET PARAMETER BIT @HL LD (HL),A RET ; ; ;