.NLIST TTM,CND .TITLE SCROLL - GT40 SCROLLER .SBTTL GENERAL PARAMETER DEFINITIONS .ENABL AMA .MCALL GRAPHIC GRAPHIC ; ; REGISTER DEFINITIONS R0=%0 R1=%1 R2=%2 R3=%3 R4=%4 R5=%5 SP=%6 PC=%7 PSW=177776 ; PROCESSOR STATUS WORD ; ; DEVICE REGISTERS ; IS.GT=175610 ; GT40 INPUT STATUS REGISTER IB.GT=175612 ; GT40 INPUT BUFFER REGISTER OS.GT=175614 ; GT40 OUTPUT STATUS REGISTER OB.GT=175616 ; GT40 OUTPUT BUFFER REGISTER ; IS.KB=177560 ; KEYBOARD INPUT STATUS REGISTER IB.KB=177562 ; KEYBOARD INPUT BUFFER REGISTER ; ; SCREEN AND SCROLLING PARAMETERS ; .RADIX 10 LNS.SC=31 ; NUMBER OF LINES LST.SC=23 ; Y POSITION OF LAST LINE (RASTER UNITS) FST.SC=LNS.SC*24-1 ; Y POSITION OF FIRST LINE (RASTER UNITS) CHR.SC=72 ; NUMBER OF CHARACTERS PER LINE LSZ.SC=CHR.SC+8 ; BYTES PER LINE DST.SC=24 ; VERTICAL DISTANCE BETWEEN CHARACTERS .PAGE .SBTTL SPECIAL CHARACTERS .RADIX 8 ; CR.CH=15 ; CARRIAGE RETURN LF.CH=12 ; LINE FEED EOS.CH=37 ; CLEAR SCREEN CRS.CH=137 ; CURSOR IS UNDERSCORE BEL.CH=7 ; BEL.CH SP.CH=40 ; SPACE RUB.CH=177 ; RUBOUT SO.CH=16 ; SHIFT-OUT SI.CH=17 ; SHIFT-IN .PAGE .SBTTL INTERRUPT VECTORS .=4 .WORD $BSINT,000 ; BUS ERROR, LEVEL 0 .=60 KB$VEC: .WORD $KBINT,200 ; KEYBOARD INTERRUPT, LEVEL 4 .=300 DL$VEC: .WORD $DLINT,340 ; DL-11 INTERRUPT, LEVEL 7 .=330 .WORD $TMINT,340 ; TIME-OUT INTERRUPT, LEVEL 7 .PAGE .SBTTL LOCAL MACROS ; .MACRO CALL ..ROUT ; MACRO TO CALL A ROUTINE JSR PC,..ROUT ; VIA THE PC .ENDM ; .MACRO RETURN ; MACRO TO DO A RETURN RTS PC ; VIA THE PC .ENDM ; .MACRO SAVREG ; MACRO TO SAVE REGISTERS MOV #340,@#PSW ; NO INTERRUPTS DURING SAVE CALL $SAVRG ; PLACE THEM ON THE STACK CLR @#PSW ; RE-ENABLE INTERRUPTS .ENDM ; .MACRO RESREG ; MACRO TO RESTORE REGISTERS MOV #340,@#PSW ; NO INTERRUPTS DURING RESTORE CALL $RESRG ; GET THEM FROM STACK CLR @#PSW ; RE-ENABLE INTERRUPTS .ENDM ; .MACRO PUSH .. ; MACRO TO MOV ..,-(SP) ; PUSH ONTO STACK .ENDM ; .MACRO POP .. ; MACRO TO POP MOV (SP)+,.. ; OFF STACK .ENDM ; .MACRO SOB ..R,..DEST ; MACRO TO SIMULATE SOB INSTRUCTION DEC ..R ; DECREMENT THE REGISTER BGT ..DEST ; BRANCH BACK IF GREATER .ENDM .PAGE .=1000 ; ; MAINLINE, RESUME ADDRESS IS 1000 (OCTAL) ; $START: RESET ; RESET ; FIX THINGS RESET ; MOV #37776,SP ; SET STACK TO TOP OF CORE CALL $CDINI ; INTIALIZE CDF, START DISPLAY MOV #100,@#IS.KB ; ENABLE KEYBOARD INTERRUPTS MOV #100,@#IS.GT ; ENABLE DL-11 INTERRUPTS MOV #FIRST.,@#DPC ; START THE DISPLAY ST.NUL: WAIT ; WAIT FOR INTERRUPT BR ST.NUL ; WAIT FOR NEXT INTERRUPT .PAGE .SBTTL CHARACTER DISPLAY FILE INITIALIZATION ; THIS SUBROUTINE INITIALIZES THE CHARACTER ; DISPLAY FILE, AND CREATES CHARACTER POINTERS ; $CDINI: SAVREG ; SAVE THE REGISTERS MOV #FST.SC,R2 ; Y POSITION OF TOP LINE MOV #LNS.SC,R0 ; NUMBER OF LINES MOV #CDF.+2,R1 ; R1 IS CDF. POINTER CD.1: TST (R1)+ ; POINT PAST POINT WORD CLR (R1)+ ; CLEAR X POSITION MOV R2,(R1)+ ; INSERT Y POSITION SUB #DST.SC,R2 ; UPDATE Y POSITION TST (R1)+ ; POINT PAST CHAR. INST. MOV #CHR.SC/2,R3 ; NUMBER OF WORDS PER LINE CD.2: CLR (R1)+ ; BLANK OUT THE LINE SOB R3,CD.2 ; LOOP FOR ALL WORDS SOB R0,CD.1 ; LOOP FOR ALL LINES CLR CDF.X ; RESET CURSOR CLR DL$CNT ; CLEAR CHARACTER COUNT MOV #CDF.+10.+,DL$PNT MOV DL$PNT,DL$ST ; POINTERS RESREG ; RESTORE THE THE REGISTERS RETURN ; AND RETURN .PAGE .SBTTL BUS ERROR INTERRUPT ROUTINES ; TIME-OUT INTERRUPT ROUTINE ; ; RESTART THE DISPLAY IMMEDIATELY ; $TMINT: BIT #100,@#DSR ; IS THIS A SHIFT INTERRUPT ? BNE TM.OUT ; NO, IT IS A TIME-OUT MOV #1,@#DPC ; IF SHIFT THEN RESUME DISPLAY RTI ; AND RETURN FROM INTERRUPT ; TM.OUT: MOV #FIRST.,@#DPC ; IF TIME-OUT, THEN RE-START RTI ; AND RETURN FROM INTERRUPT ; ; $BSINT - BUS ERROR ; MOST LIKELY ODD ADDRESS REFERENCE ; $BSINT: INC @#DSR ; IN THE EVENT OF AN ODD ADDRESS BR $BSINT ; ERROR, BECOME NOISY .PAGE .SBTTL KEYBOARD INTERRUPT ROUTINE ; ; THIS ROUTINE INPUTS ONE CHARACTER FROM THE LK40 ; KEYBOARD AND SENDS IT TO THE 10. IF THE CHARACTER ; IS "EOS.CH" (ASCII 37) THE CHARACTER DISPLAY FILE ; IS CLEARED ; $KBINT: SAVREG ; SAVE THE REGISTERS MOVB @#IB.KB,R0 ; GET THE KEYBOARD CHARACTER BIC #177600,R0 ; CLEAR THE TOP BYTE AND PARITY CMP R0,#EOS.CH ; CLEAR SCREEN ? BNE KB.SND ; NO SEND THE CHARACTER CALL $CDINI ; YES - INITIALIZE THE SCREEN BR KB.RET ; AND RETURN FROM INTERRUPT KB.SND: TSTB @#OS.GT ; IS THE 10 READY BPL KB.SND ; WAIT IF NOT READY MOVB R0,@#OB.GT ; SEND THE CHARACTER KB.RET: RESREG ; RESTORE THE REGISTERS RTI ; RETURN FROM INTERRUPT .PAGE .SBTTL DL-11 INTERRUPT ROUTINE ; THIS ROUTINE INPUTS ONE CHARACTER FROM THE 10 ; AND ADDS IT TO THE DISPLAY FILE. IF NECESSARY ; THE DISPLAY FILE IS SCROLLED ; DL$ST: .WORD 0 ; POINTER TO START OF LINE DL$CNT: .WORD 0 ; CHARACTER COUNT DL$PNT: .WORD 0 ; CHARACTER POINTER ; $DLINT: SAVREG ; SAVE THE REGISTERS MOVB @#IB.GT,R0 ; GET THE CHARACTER BIC #177600,R0 ; CLEAR TOP BYTE AND PARITY CMP R0,#BEL.CH ; IS THIS A BELL ? BNE DL.NOB ; NO SO CONTINUE INC @#DSR ; YES SO RING BR DL.RET ; AND RETURN DL.NOB: CMP R0,#CR.CH ; CARRIAGE RETURN ? BEQ DL.RET ; YES, SO IGNORE CMP R0,#RUB.CH ; FILLER ? BEQ DL.RET ; YES, SO IGNORE IT CMP R0,#LF.CH ; LINE FEED ? BNE DL.CHR ; NO, SO PRINT CHARACTER CALL $SCROL ; , SO SCROLL BR DL.RET ; AND RETURN ; DL.CHR: CMP DL$CNT,#CHR.SC ; ENOUGH ROOM ON LINE ? BGE DL.RET ; NO, SO IGNORE CMP R0,#40 ; PRINTABLE CHARACTER ? BLT DL.RET ; NO, SO IGNORE MOVB R0,@DL$PNT ; INSERT THE CHARACTER INC DL$PNT ; INCREMENT POINTER INC DL$CNT ; INCREMENT CHARACTER COUNT ADD #14.,CDF.X ; MOVE CURSOR DL.RET: RESREG ; RESTORE THE REGISTERS RTI ; RETURN FROM INTERRUPT .PAGE .SBTTL SCROLLING ROUTINE ; THIS ROUTINE IS CALLED WHENEVER THE 10 ; OUTPUTS A LINE FEED. EVERY LINE IS ; SHIFTED UP ONE POSITION, AND THE BOTTOM ; LINE BECOMES AVAILABLE FOR OUTPUT ; $SCROL: MOV #LNS.SC,R0 ; NUMBER OF LINES MOV #CDF.+2,R1 ; CDF. POINTER SC.LUP: ADD #DST.SC,4(R1) ; SHIFT LINE UP CMP 4(R1),#FST.SC ; IS THIS LINE AVAILABLE BLE SC.SNT ; NO, CONTINUE SHIFTING MOV #LST.SC,4(R1) ; MAKE THIS THE LAST LINE MOV R1,DL$PNT ; GET POINTER ADD #8.,DL$PNT ; AND FIX IT UP MOV DL$PNT,DL$ST ; AND START POINTER CLR DL$CNT ; CLEAR CHARACTER COUNT CLR CDF.X ; RESET CURSOR MOV DL$PNT,R2 ; POINTER TO LINE MOV #CHR.SC/2,R3 ; NUMBER OF WORDS PER LINE SC.1: CLR (R2)+ ; BLANK OUT LINE SOB R3,SC.1 ; LOOP FOR ALL WORDS ; SC.SNT: ADD #LSZ.SC,R1 ; POINT TO NEXT LINE SOB R0,SC.LUP ; LOOP FOR ALL LINES RETURN ; RETURN .PAGE .SBTTL UTILITY ROUTINES ; $SAVRG: POP SA$RET ; SAVE RETURN ADDRESS PUSH R0 ; PUSH R1 ; PUSH R2 ; PUSH ALL REGISTERS PUSH R3 ; ONTO THE STACK PUSH R4 ; PUSH R5 ; JMP @SA$RET ; SP & PC NOT SAVED SA$RET: .WORD 0 ; TEMPORARY STORAGE ; $RESRG: POP RE$RET ; SAVE RETURN ADDRESS POP R5 ; POP R4 ; POP R3 ; POP ALL REGISTERS POP R2 ; OFF THE STACK POP R1 ; POP R0 ; JMP @RE$RET ; SP & PC NOT RESTORED RE$RET: .WORD 0 ; TEMPORARY STORAGE .PAGE .SBTTL SCROLL DISPLAY FILES ; FIRST DISPLAY FILE ; FIRST.: STATSA ! SINOF ! ITAL0 ! LPDARK ; LOAD STATUS A, NO INTERRUPTS ; NORMAL FONT ; L.P. HITS NOT BRIGHTENED CHAR ; CHARACTER MODE .BYTE ,0 ; SHIFT IN FI.END: DJMP,CDF. ; ONTO CHARACTER DISPLAY FILE .PAGE ; CHARACTER DISPLAY FILE ; CDF.: STATSA!ITAL0 ; NO ITALICS .REPT .WORD POINT!INT4!BLKOFF .WORD 0, 0 CHAR .BLKB .ENDR ; POINT!INT4!BLKON CDF.X: .WORD 0, CHAR!BLKON .BYTE , 0 CD.END: DJMP,FIRST. ; LOOP THROUGH DISPLAY FILE ; ; ; .END $START