;******************************************************** ;* * ;* MEMORY-MAPPED CRT OUTPUT DRIVER * ;* * ;* Russell Smith 18-August-1980 * ;* * ;******************************************************** ; ; CRTBAS EQU CRTMEM.SHR.8 ;STARTING PAGE# OF 3K CRT SPACE CRTTOP EQU CRTMEM+3072.SHR.8 ;ENDING PAGE# OF CRT SPACE ; ; CRTOUT: PUSH HL PUSH DE PUSH BC RES 7,A LD C,A DI ;KEEP THE WOLVES AWAY FOR A WHILE LD (SPSAVE),SP LD SP,TMPSTK+32 ;POINT SP TO TOP OF LOCAL STACK IN A,(BITDAT) SET 7,A ;SELECT ROM/CRT MEMORY BANK OUT (BITDAT),A ; ; FIRST REMOVE THE OLD CURSOR CHARACTER FROM THE SCREEN ; LD HL,CHRSAV ;GET CHARACTER NOW OVERLAYED BY CURSOR LD B,(HL) LD HL,(CURSOR) ;LOAD HL WITH CURSOR POINTER LD A,H AND 00001111B ;A LITTLE INSURANCE THAT HL CAN'T OR CRTBAS ; EVER POINT OUTSIDE THE CRT MEMORY LD H,A LD (HL),B ;REMOVE CURSOR BY RESTORING CHARACTER ; ; PROCESS CHARACTER PASSED IN C ; CALL OUTCH ; ; NOW STORE A NEW CURSOR CHARACTER AT THE CURSOR LOCATION ; LD A,(HL) ;GET CHARACTER AT NEW CURSOR LOCATION LD (CHRSAV),A ;SAVE FOR NEXT TIME 'CRTOUT' IS CALLED CP ' ' ;TEST IF CHARACTER IS A SPACE SET 7,A ;THEN TURN ON BIT 7 TO ENABLE BLINK JR NZ,CRT2-$ ;JUMP IF CHARACTER IS NON-BLANK LD A,(CSRCHR) ; ELSE GET CHARACTER USED FOR CURSOR CRT2: LD (HL),A ;STORE CHARACTER IN A AS CURSOR MARK LD (CURSOR),HL ;SAVE HL AS CURSOR POINTER LD SP,(SPSAVE) IN A,(BITDAT) RES 7,A ;SWITCH BACK THE LOWER 16K OF RAM OUT (BITDAT),A EI ;INTERRUPTS ARE SAFE AGAIN POP BC POP DE POP HL RET ; ; ; OUTCH: LD DE,LEADIN LD A,(DE) ;GET LEAD-IN SEQUENCE STATE OR A JP NZ,MULTI ;JUMP IF IN A LEAD-IN SEQUENCE LD A,C ; ELSE PROCESS CHARACTER IN C CP ' ' JR C,CONTRL-$ ;JUMP IF A CONTROL CHARACTER DISPLA: LD (HL),C ; ELSE STORE DISPLAYABLE CHARACTER INC HL ; AND ADVANCE POINTER TO NEXT COLUMN LD A,L AND 01111111B ;EXTRACT COLUMN# FROM HL CP 80 RET C ;EXIT IF NOT PAST COLUMN 79 CALL RETURN ; ELSE DO AUTOMATIC CARRIAGE RETURN CALL LFEED ; AND LINEFEED RET ; ; ; CONTRL: PUSH HL LD HL,CTLTAB ;SEARCH FOR CONTROL CHARACTER LD BC,CTLSIZ/3 ; HANDLING SUBROUTINE IN TABLE CALL SEARCH POP HL RET NZ ;EXIT IF NOT IMPLEMENTED PUSH BC RET ;DO SNEAKY JUMP TO PRESERVE REGISTERS CTLTAB: DEFB '_'-64 DEFB '^'-64 DEFB '['-64 DEFB 'Z'-64 DEFB 'X'-64 DEFB 'Q'-64 DEFB 'M'-64 DEFB 'L'-64 DEFB 'K'-64 DEFB 'J'-64 DEFB 'I'-64 DEFB 'H'-64 DEFB 'G'-64 DEFW BELL ;CTL-G IS THE BELL DEFW BAKSPC ;CTL-H IS CURSOR LEFT DEFW TAB ;CTL-I IS TAB DEFW LFEED ;CTL-J IS CURSOR DOWN DEFW UPCSR ;CTL-K IS CURSOR UP DEFW FORSPC ;CTL-L IS CURSOR RIGHT DEFW RETURN ;CTL-M IS CARRIAGE RETURN DEFW CLREOS ;CTL-Q IS CLEAR TO END-OF-SCREEN DEFW CLREOL ;CTL-X IS CLEAR TO END-OF-LINE DEFW CLRSCN ;CTL-Z IS CLEAR SCREEN DEFW ESCAPE ;CTL-[ IS ESCAPE DEFW HOMEUP ;CTL-^ IS HOME UP DEFW STUFF ;CTL-_ IS DISPLAY CONTROL CHARS CTLSIZ EQU $-CTLTAB ; ; ESCAPE: LD A,1 LD (DE),A ;SET LEAD-IN SEQUENCE STATE RET ; FOR XY CURSOR POSITIONING MODE ; ; STUFF: LD A,4 LD (DE),A ;SET LEAD-IN SEQUENCE STATE RET ; FOR CONTROL CHAR OUTPUT MODE ; ; BAKSPC LD A,L ;CHECK FOR LEFT MARGIN AND 01111111B RET Z ;ABORT IF IN LEFTMOST COLUMN DEC HL ;BACK UP CURSOR POINTER RET ; ; FORSPC: LD A,L ;CHECK FOR RIGHTMOST COLUNM AND 01111111B CP 79 RET NC ;DO NOTHING IF ALREADY THERE INC HL RET ;ELSE ADVANCE THE CURSOR POINTER ; ; TAB: LD DE,8 ;TABS ARE EVERY 8 COLUMNS LD A,L ;GET COLUMN COMPONENT OF AND 01111000B ; PREVIOUS TAB POSITION ADD A,E CP 80 ;EXIT IF NEXT TAB COLUMN WOULD RET NC ; BE PAST THE RIGHT MARGIN LD A,L AND 11111000B ;ELSE INCREMENT THE CURSOR LD L,A ; POINTER FOR REAL ADD HL,DE RET ; ; BELL: IN A,(BITDAT) SET 5,A ;TOGGLE BIT 5 OF SYSTEM PIO TO OUT (BITDAT),A ; TRIGGER BELL HARDWARE TO SOUND RES 5,A OUT (BITDAT),A RET ; ; RETURN: LD A,L AND 10000000B LD L,A ;MOVE CURSOR POINTER BACK RET ; TO START OF LINE ; ; CLRSCN: LD HL,CRTMEM PUSH HL LD DE,CRTMEM+1 LD BC,24*128 LD (HL),' ' LDIR ;FILL CRT MEMORY WITH SPACES POP HL ;POINT TO HOME CURSOR POSITION LD A,23 LD (BASE),A ;MAKE BASE LINE# BE 23 AND OUT (SCROLL),A ; STORE IN SCROLL REGISTER RET ; ; CLREOL: PUSH HL ;SAVE CURSOR POINTER LD A,L AND 01111111B ;GET COLUMN# COMPONENT OF LD C,A ; CURSOR POINTER INTO C LD A,80 ;CALCULATE HOW MANY CHARACTERS SUB C ; REMAIN ON CURRENT LINE LD B,A CALL CLR ;CLEAR REST OF LINE @ HL POP HL RET ; ; CLREOS: CALL CLREOL ;CLEAR REMAINDER OF CURRENT ROW PUSH HL LD A,(BASE) LD C,A ;COPY BASE SCREEN ROW# TO C CLRS1: LD A,L RLA LD A,H RLA ;GET ROW# COMPONENT OF HL INTO A AND 00011111B CP C ;SEE IF HL IS AT BOTTOM ROW OF SCREEN JR Z,CLRS2-$ ; AND LEAVE CLEAR LOOP IF SO CALL DNCSR ;ELSE POINT HL TO NEXT ROW DOWN CALL CLRLIN ; AND FILL THAT LINE WITH SPACES JR CLRS1-$ CLRS2: POP HL ;RESTORE ORIGINAL CURSOR POINTER RET ; ; UPCSR: LD DE,-128 ;SUBTRACT 1 FROM ROW# COMPONENT ADD HL,DE ; OF CURSOR POINTER IN HL LD A,H CP CRTBAS ;CHECK FOR UNDERFLOW OF POINTER RET NC LD H,CRTTOP-1 ;WRAP CURSOR AROUND MODULO 3K RET ; ; DNCSR: LD DE,128 ;ADD 1 TO ROW# COMPONENT ADD HL,DE ; OF CURSOR POINTER IN HL LD A,H CP CRTTOP ;CHECK FOR OVERFLOW OF POINTER RET C LD H,CRTBAS ;RESET POINTER MODULO 128*24 RET ; ; ; LFEED: LD A,L RLA LD A,H RLA ;EXTRACT ROW# COMPONENT OF HL AND 00011111B LD C,A ;COPY ROW# INTO C FOR SCROLL TEST CALL DNCSR ;MOVE CURSOR TO NEXT ROW DOWN LD A,(BASE) ;TEST IF CURSOR WAS ON BOTTOM ROW CP C ; OF SCREEN BEFORE MOVING DOWN RET NZ ;EXIT IF NOT AT BOTTOM PUSH HL ;ELSE PREP TO SCROLL SCREEN UP CALL CLRLIN ;FILL NEW BOTTOM LINE WITH SPACES ADD HL,HL LD A,H ;GET ROW# COMPONENT OF HL INTO A AND 00011111B LD (BASE),A ;STORE NEW BASE LINE# OUT (SCROLL),A ;NOW SCROLL UP NEW BLANK BOTTOM LINE POP HL RET ; ; CLRLIN: LD A,L AND 10000000B ;POINT HL TO FIRST COLUMN OF ROW LD L,A LD B,80 CLR: LD (HL),' ' ;STORE ASCII SPACES AT ADDRESS IN HL INC HL ; AND INCREMENT HL DJNZ CLR-$ ;REPEAT NUMBER OF TIMES GIVEN BY B RET ; ; HOMEUP: LD C,' ' ;FAKE-OUT CURSOR ADDRESSING ROUTINE JR SETROW-$ ; TO DO HOMEUP ALMOST FOR FREE ; ; MULTI: EX DE,HL ;UNCONDITIONALLY RESET THE LEAD-IN LD (HL),0 ; STATE TO ZERO BEFORE GOING ON EX DE,HL CP 1 JR NZ,M2TST-$ SETXY: LD A,C ;GET SECOND CHAR OF SEQUENCE CP '=' RET NZ ;ABORT SEQUENCE IF NOT '=' LD A,2 LD (DE),A ;MAKE LEADIN=2 NEXT TIME RET M2TST: CP 2 JR NZ,M3TST-$ LD A,3 LD (DE),A ;MAKE LEADIN=3 NEXT TIME SETROW: LD A,(BASE) ;ARRIVE HERE ON THIRD CHARACTER ADD A,C ; OF ESC,'=',ROW,COL SEQUENCE SUB ' '-1 SETR2: SUB 24 JR NC,SETR2-$ ;MAKE SURE ROW# IS BETWEEN 0 AND 23 ADD A,24 OR CRTMEM.SHR.7 ;MERGE IN MSB'S OF CRT MEMORY LD H,A LD L,0 SRL H RR L RET M3TST: CP 3 JR NZ,M4TST-$ SETCOL: LD A,C ;ARRIVE HERE ON FOURTH CHARACTER SUB ' ' ; OF ESC,'=',ROW,COL SEQUENCE SETC2: SUB 80 JR NC,SETC2-$ ;MAKE SURE COL# IS BETWEEN 0 AND 79 ADD A,80 OR L ;MERGE IN COL# WITH L LD L,A RET M4TST: CALL DISPLA ;DISPLAY THE CONTROL CHARACTER RET ; PASSED IN C ; ; ; ;