.TITLE RMDRIV .IDENT /1.2/ .PSECT DRIVER,OVR,I,LCL ; ; COPYRIGHT (C) 1978 ; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. ; ; ; VERSION: 1.2 ; AUTHOR: ALAN GROUPE ; DATE: 8-DEC-78 ; MODIFICATIONS: ; ; AG046 CHANGE TO SINGLE LONG QIO ; .PAGE .SBTTL DESCRIPTION ; THIS SEGMENT IS THE DISPLAY DRIVER THAT HANDLES ALL OUTPUT TO THE ; TERMINAL. IT MAINTAINS A COPY OF THE CURRENT SCREEN IMAGE IN A ; MEMORY BUFFER CALLED $SCRN. WHEN THE PAGE SEGMENTS WANT TO WRITE ; SOMETHING TO THE SCREEN, THEY MOVE THE CHARACTERS TO THE SCREEN ; BUFFER USING THE MACROS "MVN" AND "OUTC". THESE MACROS COMPARE THE ; NEW CHARACTERS TO THE ONES THEY ARE OVERWRITING AND IF THEY ARE ; DIFFERENT, MOVE THEM TO THE BUFFER AND SET THE HIGH BIT OF EACH. ; ; THE DRIVER ONLY OUTPUTS TO THE TERMINAL THOSE CHARACTERS WITH THEIR ; HIGH BIT SET. IT DOES, HOWEVER, SEND TO THE TERMINAL OLD CHARACTERS ; (THOSE ALREADY ON THE SCREEN) BETWEEN BLOCKS OF NEW CHARACTERS, IF ; SENDING THESE OLD CHARS WOULD REQUIRE FEWER CHARACTERS THAN A DIRECT ; CURSOR ADDRESSING COMMAND. THIS ALGORITHM ALLOWS A MINIMAL AMOUNT OF ; TERMINAL OUTPUT WITHOUT INTRODUCING THE LARGE AMOUNT OF OVERHEAD OF ; A MORE SOPHISTICATED ALGORITHM. .PAGE .SBTTL MCALLS AND MACROS .MCALL QIOW$,DIR$,WSIG$S,WTSE$S ;AG046 ;**-1 ; ; LOCAL MACROS ; .MACRO CHECK,SS ; CHECK IF NEW CHARACTER BITB #200,SS .ENDM .MACRO FLAG,DD ; FLAG CHARACTER AS BEING NEW BISB #200,DD .ENDM .MACRO UNFLAG,DD ; REMOVE FLAG (FLAG AS BEING OLD) BICB #200,DD .ENDM ;AG046 .MACRO PUTC CHAR,?A ; PUT CHARACTER TO OUTPUT BUFFER ;AG046 CMP R5,#BUFFER+BUFL-1 ;AG046 BLT A ;AG046 CALL OUTPUT ;AG046 A: MOVB CHAR,(R5)+ ;AG046 .ENDM ;AG046 .PAGE .SBTTL DATA AREAS ; ; LOCAL STORAGE ; LINE: .WORD 0 ; LINE # WE ARE WORKING ON (0 IS TOP LINE) CURY: .WORD 0 ; LINE # ON WHICH CURSOR RESIDES LINEB: .WORD 0 ; MEMORY ADDRESS OF BEGINNING OF CURRENT LINE LOOPCT: .WORD 0 ; FOR LOOPING THROUGH LINES BUFL=256. ; LENGTH OF IO BUFFER ;AG046 BUFFER: .BLKB BUFL ; OUTPUT BUFFER ;AG046 ;**-6 ; ; DIRECTIVES ; OUT: QIOW$ IO.WVB,$DLUN,$QIOF,,,, ;AG046 .PAGE ;**-1 .SBTTL CURSOR HOME ROUTINE ; ;+ ; $HOME - ROUTINE THAT SENDS THE CURSOR TO THE HOME POSITION ; ; IT DOES THIS BY OUTPUTTING TO THE TERMINAL THE STRING .HOSTR ; FOUND IN THE TERMINAL CHARACTERISTICS SEGMENT. ; ; IF THERE IS NO WAY TO GET THE CURSOR TO THE HOME POSITION (EITHER WITH ; DIRECT CURSOR ADDRESSING OR WITH A COMBINATION OF REVERSE LINE FEEDS, ; ETC.) THE LENGTH OF .HOSTR (FIRST BYTE) SHOULD BE ZERO. HOME WILL ; RETURN WITH THE CARRY BIT SET. ;- $HOME:: MOVB $HOSTR,R0 ; LENGTH OF HOME STRING BEQ HOMLES ; IF ZERO, CAN'T DO IT MOV #$QIOF,OUT+Q.IOEF MOV R0,OUT+Q.IOPL+2 ; MOVE LENGTH IN DPB MOV #$HOSTR+1,OUT+Q.IOPL ; ADDRESS OF STRING DIR$ #OUT ; SEND OUT THE STRING CLC ; RETURN STATUS OK WTSE$S #$QIOF ; WAIT FOR IT RETURN HOMLES: SEC ; RETURN ERROR STATUS RETURN .PAGE .PAGE .SBTTL CLEAR SCREEN ROUTINE ; ;+ ; $CLEAR - ROUTINE THAT CLEARS THE SCREEN ; ; IT DOES THIS BY OUTPUTTING TO THE TERMINAL THE STRING .CSSTR ; FOUND IN THE TERMINAL CHARACTERISTICS SEGMENT. ; ; IF THE TERMINAL DOES NOT HAVE ANY SPECIAL WAY TO CLEAR THE SCREEN, ; MULTIPLE LINE FEEDS WILL DO. IF THE LENGTH OF .CSSTR IS ZERO, AS ; WITH A PRINTING DEVICE, NOTHING IS DONE. ;- $CLEAR::MOVB $CSSTR,R0 ; LENGTH OF CLEAR SCREEN STRING BEQ 10$ ; IF ZERO, RETURN MOV #$QIOF,OUT+Q.IOEF MOV R0,OUT+Q.IOPL+2 MOV #$CSSTR+1,OUT+Q.IOPL DIR$ #OUT ; SEND OUT THE STRING MOV #$SCRN,R0 ; NOW WE HAVE TO SET IN MEMORY SCREEN MOV #$ESCRN,R1 ; TO CORRESPOND 1$: CMP R0,R1 ; WITH SCREEN IMAGE BHIS 10$ MOVB #' ,(R0)+ ; MOVE SPACES INTO SCREEN BUFFER BR 1$ 10$: WTSE$S #$QIOF RETURN .PAGE .SBTTL DSPLY ; ;+ ; $DSPLY - SUBROUTINE TO UPDATE A TERMINAL SCREEN FROM THE IN MEMORY TERMINAL ; IMAGE ; ; DSPLY ONLY OUTPUTS CHARACTERS THAT HAVE CHANGED SINCE THE LAST ; INVOCATION. HOWEVER, IF IT IS SHORTER TO PRINT SOME OLD CHARACTERS ; THAN TO OUTPUT A CURSOR ADDRESSING COMMAND, THE OLD CHARACTERS ARE ; PRINTED. ;- ; $DSPLY::MOV #BUFFER,R5 ; START OF OUTPUT BUFFER ;AG046 MOV R5,OUT+Q.IOPL ; INIT QIO DPB FOR SCREEN OUTPUT ;AG046 MOVB $HOSTR,R0 ; LENGTH OF HOME CURSOR STRING ;AG046 BEQ 10$ ; IS NONE, START WHERE YOU ARE ;AG046 MOV #$HOSTR+1,R1 ; ADDRESS OF HOME CURSOR STRING ;AG046 1$: PUTC (R1)+ ; MOVE TO BUFFER ;AG046 SOB R0,1$ ;AG046 10$: CLR CURY ; CURSOR AT TOP LINE ;**-1 CLR LINE ; START WORKING AT TOP LINE MOV #$SCRN,R2 MOV $LINES,LOOPCT ; DO FULL SCREEN NLINE: MOV R2,LINEB ; BEGINNING OF CURRENT LINE MOV R2,R1 ; BEGINNING OF CURRENT BLOCK OF CHARS MOV R2,R0 ; MOVING POINTER ADD $WIDTH,R2 ; BEGINNING OF NEXT LINE ;AG046 ; ;**-2 ; FIRST WASTE OLD CHARS. IF NONE, OK ; OLD: CMP R2,R0 ; CHECK FOR END OF LINE BLOS EOL ; END OF LINE PROCESSING CHECK (R0)+ ; SEE IF CHAR IS FLAGGED AS NEW BEQ OLD ; NO, WASTE ANOTHER DEC R0 ; POINTING TO FIRST NEW CHAR MOV R0,R3 SUB R1,R3 ; R3 HOLDS # OF CHARS SKIPPED ADD LINE,R3 SUB CURY,R3 ; ADD IN # LINES TO MOVE DOWN TSTB $CASTR ; IF NO CURSOR ADDRESSING DO MANUALLY BEQ MANUAL CMPB $CASTR,R3 ; WHICH ROUTE SHORTER BHI MANUAL ; USE OLD CHARS AUTO: MOV R0,R3 SUB LINEB,R3 ; OFFSET INTO LINE ADD $XBIA,R3 ; ADD BIAS MOVB X$POS,R4 ; POSITION IN .CASTR TST $DEC ; DECIMAL ADDRESS BEQ 3$ ; NO - OLD FASHIONED BINARY MOV R0,-(SP) ; SAVE REGS FOR CONVERT CALL MOV R1,-(SP) MOV R2,-(SP) MOV R4,R0 ADD #$CASTR,R0 ; ADDRESS TO CONVERT INTO MOV R3,R1 ; VALUE TO CONVERT MOV #15012,R2 ; 3 DIGIT NO ZERO SUPPRESS CALL $CBTA ; CONVERT BINARY TO ASCII BR 5$ 3$: MOVB R3,$CASTR(R4) ; NOW IN X COORDINATE 5$: MOV LINE,R3 ; NOW DO Y COORDINATE ADD $YBIA,R3 MOV Y$POS,R4 TST $DEC ; SAME BEQ 7$ MOV R4,R0 ADD #$CASTR,R0 ; ADDRESS TO CONVERT TO MOV R3,R1 ; Y COORDINATE MOV #15012,R2 CALL $CBTA MOV (SP)+,R2 ; RESTORE ORIGINAL REGS MOV (SP)+,R1 MOV (SP)+,R0 BR 8$ 7$: MOVB R3,$CASTR(R4) 8$: MOVB $CASTR,R3 ; MOVE CURSOR ADDRESS MOV #$CASTR+1,R4 ; STRING INTO OUTPUT 10$: PUTC (R4)+ ; BUFFER ;AG046 SOB R3,10$ ;**-1 MOV LINE,CURY ; UPDATE CURSOR POINTER BR NEW ; PROCESS THE NEW CHARACTERS ; MOVE CURSOR TO NEW ADDRESS MANUALLY MANUAL: MOV LINE,R3 SUB CURY,R3 ; # OF LINES TO MOVE DOWN BEQ 15$ ; ON CURRENT LINE ALREADY 10$: PUTC #12 ; MOVE LINE FEEDS INTO OUTPUT BUFFER ;AG046 INC CURY ; UPDATE CURSOR POINTER ;**-1 SOB R3,10$ 15$: MOV R0,R3 SUB R1,R3 ; # OF CHARS TO MOVE OVER BEQ NEW ; COULD ONLY BE FOR BEGINNING OF LINE 25$: PUTC (R1)+ ; MOVE IN THE OLD CHARS ;AG046 SOB R3,25$ ;**-1 ; MOVE THE BLOCK OF NEW CHARS TO THE OUTPUT BUFFER NEW: UNFLAG (R0) ; NO LONGER NEW PUTC (R0)+ ; MOVE INTO BUFFER ;AG046 CMP R2,R0 ; AT END OF LINE ;**-1 BLOS EOL ; PROCESS END OF LINE CHECK (R0) ; IS NEXT CHAR NEW BNE NEW ; YES MOV R0,R1 ; END OF GROUP, MOVE CURSOR POINTER UP BR OLD ; END OF LINE PROCESSING EOL: PUTC #15 ; RETURN TO BEGINNING OF LINE ;AG046 INC LINE ; ON NEXT LINE ;AG046 DEC LOOPCT ; ONE LESS LINE TO DO ;AG046 BEQ 10$ ; ALL DONE ;AG046 JMP NLINE ; DO NEXT LINE ;AG046 ;AG046 10$: MOVB $HOSTR,R0 ; LENGTH OF HOME STRING ;AG046 BEQ 20$ ; NONE ;AG046 MOV #$HOSTR+1,R1 ; ADDRESAS OF STRING ;AG046 15$: PUTC (R1)+ ; PUT CURSOR HOME FOR AESTHETICS ;AG046 SOB R0,15$ ;AG046 20$: CALLR OUTPUT ; FLUSH LEFTOVER BUFFER ;AG046 ;AG046 ; OUTPUT - OUTPUT CONTENTS OF BUFFER ;AG046 ;AG046 OUTPUT: SUB #BUFFER,R5 ; GET LENGTH OF BUFFER ;AG046 BEQ DONE ; EMPTY - RETURN ;AG046 MOV R5,OUT+Q.IOPL+2 ; FILL QIO DPB ;AG046 MOV #BUFFER,R5 ; RESET BUFFER POINTER ;AG046 5$: DIR$ #OUT ; OUTPUT BUFFER ;AG046 BCC DONE ; OK ;AG046 CMP $DSW,#IE.UPN ; OUT OF POOL ;AG046 BNE DONE ; NO - IGNORE ;AG046 WSIG$S ; WAIT FOR SOMETHING ;AG046 BR 5$ ; AND TRY AGAIN ;AG046 DONE: RETURN ;AG046 .END ;**-27