.NLIST TTM,CND .TITLE GIDUS GT40 INTERACTIVE DISPLAY UTILITY SYSTEM .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 SWR=177570 ; SWITCH REGISTER PSW=177776 ; PROCESSOR STATUS WORD STACK=37700 ; LOWER STACK BOUND ; ; 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 ; LKS.CL=177546 ; CLOCK STATUS REGISTER ; ; SCREEN AND SCROLLING PARAMETERS ; .RADIX 10 LST.SC=23 ; Y POSITION OF LAST LINE (RASTER UNITS) CHR.SC=72 ; NUMBER OF CHARACTERS PER LINE LSZ.SC=CHR.SC+8 ; NUMBER OF 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 ; BELL LFT.CH=10 ; LEFT ARROW (BACK SPACE) RT.CH=30 ; RIGHT ARROW (CTRL X) UP.CH=32 ; UP ARROW (CTRL Z) DWN.CH=13 ; DOWN ARROW (VT) HME.CH=35 ; HOME UP (GIDUS COMMAND) SP.CH=40 ; SPACE RUB.CH=177 ; RUBOUT SO.CH=16 ; SHIFT-OUT SI.CH=17 ; SHIFT-IN CMD.CH=1 ; COMMAND SIGNAL (^A) ADD.CH=2 ; ADD FILE SIGNAL (^B) .PAGE .SBTTL DISPLAY RESTART ; ; ALLOW DISPLAY RE-START FROM 0 ; .=0 ; ; RE-START THE DISPLAY FILE IF TEMPORARY ; DJMP LANDS HERE ; DJMP,FIRST. .PAGE .SBTTL INTERRUPT VECTORS .=4 .WORD $BSINT,000 ; BUS ERROR, LEVEL 0 .=60 KB$VEC: .WORD $KBINT,200 ; KEYBOARD INTERRUPT, LEVEL 4 .=100 .WORD $CLINT,300 ; CLOCK INTERRUPT, LEVEL 6 .=300 DL$VEC: .WORD $DLINT,340 ; DL-11 INTERRUPT, LEVEL 7 .=320 .WORD $STINT,200 ; STOP INTERRUPT, LEVEL 4 .WORD $LPINT,200 ; L.P. INTERRUPT, LEVEL 4 .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 JSR R0,$SAVRG ; SAVE THE REGISTERS .ENDM ; .MACRO RESREG ; MACRO TO RESTORE REGISTERS JSR R0,$RESRG ; RESTORE THE REGISTERS .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 ; .MACRO ENABLE ..DN ; MACRO TO ENABLE A DISPLAY FILE MOV #..DN,R5 ; GET DISPLAY NUMBER CALL $ENABL ; AND ENABLE IT .ENDM ; .MACRO DISABL ..DN ; MACRO TO DISABLE A DISPLAY FILE MOV #..DN,R5 ; GET THE DISPLAY NUMBER CALL $DSABL ; AND DISABLE IT .ENDM .PAGE ; OCTAL FORMAT MACRO ; ; THIS MACRO IS USED TO SET UP A CALL TO ; THE OCTAL FORMATTING ROUTINE ; .MACRO FORMAT ..WORD,..AREA,..SIZE SAVREG ; SAVE ALL REGISTERS MOV ..WORD,R5 ; GET WORD TO BE FORMATTED MOV #'..AREA,R1 ; GET POINTER TO OUTPUT MOV #'..SIZE,R2 ; GET NUMBER OF DIGITS CALL $FRMAT ; FORMAT THE NUMBER RESREG ; RESTORE THE REGISTERS .ENDM .PAGE ; STATS$ - STATUS MACRO ; ; THIS MACRO IS USED TO SET UP THE STATUS/POINTER WORD ; IN THE DISPLAY FILE TABLE. ALL ARGUMENTS SHOULD BE ; PRESENT AND (WITH THE EXCEPTION OF ..PT) HAVE A VALUE OF ; OF 1(ON) OR 0(OFF) ; ; ..EX 1 = DISPLAY FILE EXISTS ; ..EN 1 = DISPLAY FILE ENABLED ; ..WP 1 = WRITE PROTECTED (DISPLAY FILE CANNOT BE DELETED) ; ..ND 1 = NO DISABLE (DISPLAY FILE CANNOT BE DISABLED) ; ..LP 1 = LIGHT PEN INTERRUPTS ALLOWED ; ..RL 1 = DISPLAY FILE MAY BE MOVED ; ..PT POINTER TO NEXT DISPLAY FILE ; .MACRO STATS$ ..EX,..EN,..WP,..ND,..LP,..RL,..PT ..=000000 .IF GT,..EX ..=100000 ; DISPLAY FILE EXISTS .ENDC .IF GT,..EN ..=..!40000 ; DISPLAY FILE IS ENABLED .ENDC .IF GT,..WP ..=..!20000 ; DISPLAY FILE IS WRITE PROTECTED .ENDC .IF GT,..ND ..=..!10000 ; DISPLAY FILE MAY NOT BE DISABLED .ENDC .IF GT,..LP ..=..!4000 ; L.P. INTERRUPTS ALLOWED .ENDC .IF GT,..RL ..=..!2000 ; DISPLAY FILE MAY BE MOVED .ENDC ..=..!..PT ; POINTER .WORD .. ; STATUS WORD .ENDM .PAGE .SBTTL GIDUS DISPLAY FILE TABLE ; ; GIDUS DISPLAY FILE TABLE ; ; 64(10) ENTRIES - ONE PER DISPLAY FILE ; 3 WORDS PER ENTRY - START/LAST/STATUS-POINTER ; ; STATUS WORD IS AS FOLLOWS: ; ; BITS MEANING ; ; 15 DISPLAY FILE EXISTS ; 14 DISPLAY FILE ENABLED ; 13 DISPLAY FILE WRITE PROTECTED ; 12 DISPLAY FILE CANNOT BE DISABLED ; 11 L.P. INTERRUPTS ALLOWED ; 10 DISPLAY FILE MAY BE MOVED ; 9-6 RESERVED ; 5-0 POINTER TO NEXT DISPLAY FILE IN LIST ; ; MASK BITS ; EX.BIT=100000 ; EXISTS BIT EN.BIT=40000 ; ENABLED BIT WP.BIT=20000 ; WRITE-PROTECT BIT ND.BIT=10000 ; NO DISABLE BIT RL.BIT=2000 ; RELOCATION BIT PT.BIT=77 ; POINTER BITS ; $$DFT: .WORD FIRST.,STATS.-2 ; FIRST DISPLAY FILE DF$FIR: STATS$ 1,1,1,1,0,0,1 .WORD CDF.,0 ; CHARACTER DISPLAY FILE DF$CDF: STATS$ 1,1,1,0,0,0,2 .WORD STATS.,MESAG.-4 ; STATUS DISPLAY FILE DF$STA: STATS$ 1,1,1,0,0,0,3 .WORD MESAG.,MP.-2 ; MESSAGE DISPLAY FILE DF$MSG: STATS$ 1,1,1,1,0,0,4 .WORD MP.,AP.-2 ; MAIN POINTER DF$MP: STATS$ 1,1,1,0,0,1,5 .WORD AP.,OMSG.-2 ; AUXILLARY POINTER DF$AP: STATS$ 1,1,1,0,0,1,77 .WORD OMSG.,GCMND.-2 ; OPTION MESSAGE FILE DF$OMS: STATS$ 1,0,1,0,0,0,0 .WORD GCMND.,OPTR.-2 ; GIDUS COMMAND DISPLAY FILE DF$CMD: STATS$ 1,0,1,0,0,0,0 .WORD OPTR.,LAST.-2 ; OPTION POINTER DF$OPT: STATS$ 1,0,1,0,0,1,0 ; ; USER DISPLAY FILES ; DF$USR: .REPT 54. .WORD 0,0 STATS$ 0,0,0,0,0,0,0 .ENDR ; .WORD LAST.,DHALT.-2 ; LAST DISPLAY FILE STATS$ 1,1,1,1,0,0,0 DF$TOP: .WORD 0 ; FIRST FREE WORD OF CORE .PAGE .SBTTL PROGRAM MAINLINE $START: RESET ; RESET ; FIX THINGS RESET ; MOV #37776,SP ; SET STACK TO TOP OF CORE MOV #STACK,R1 ; GET UPPER MEMORY BOUND CALL $CDINI ; INITIALIZE CHARACTER DISPLAY FILE SUB DF$TOP,R1 ; SUBTRACT LOWER BOUND ASR R1 ; FORM WORD COUNT FORMAT R1,ST.FRE,5 ; FORMAT INTO STATUS DISPLAY MOV #100,@#IS.KB ; ENABLE KEYBOARD INTERRUPTS MOV #100,@#IS.GT ; ENABLE DL-11 INTERRUPTS MOV #100,@#LKS.CL ; ENABLE CLOCK INTERRUPTS MOV #FIRST.,@#DPC ; START THE DISPLAY ST.NUL: WAIT ; WAIT FOR INTERRUPT TST GC$TRC ; TEST TRACE ADDRESS BEQ ST.NUL ; IF ZERO NO TRACE FORMAT @GC$TRC,ST.TRC,6 ; OTHERWISE FORMAT LOCATION BR ST.NUL ; WAIT FOR NEXT INTERRUPT .PAGE .SBTTL CHARACTER DISPLAY FILE INITIALIZATION ; THIS SUBROUTINE INITIALIZES THE CHARACTER ; DISPLAY FILE, AND CREATES CHARACTER POINTERS ; CD$FST: .WORD 0 ; Y POSITION OF FIRST LINE CD$OLD: .WORD 0 ; PREVIOUS # OF LINES IN USE CD$NEW: .WORD 8. ; DESIRED # OF LINES (DEFAULT 8) ; $CDINI: SAVREG ; SAVE THE REGISTERS CMP CD$OLD,CD$NEW ; SHOULD A SETUP BE DONE ? BEQ CD.1 ; NO, SIMPLY CLEAR EXISTING FILE CALL $CDSET ; YES, CREATE THE DISPLAY FILE CD.1: MOV CD$FST,R2 ; GET Y POSITION OF FIRST LINE MOV CD$NEW,R0 ; GET NUMBER OF LINES MOV #CDF.+12.,R1 ; R1 IS CDF. POINTER CD.2: TST (R1)+ ; POINT PAST FIRST 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.3: CLR (R1)+ ; BLANK OUT THE LINE SOB R3,CD.3 ; LOOP FOR ALL WORDS SOB R0,CD.2 ; LOOP FOR ALL LINES CLR CDF.X ; RESET CURSOR POSITION CLR DL$CNT ; CLEAR CHARACTER COUNT SUB #CHR.SC,R1 ; BACK UP POINTER TO FIRST CHAR MOV R1,DL$PNT ; AND SAVE POINTER RESREG ; RESTORE THE REGISTERS RETURN ; AND RETURN .PAGE ; THIS ROUTINE IS USED TO CREATE THE CHARACTER DISPLAY FILE ; WHICH BEGINS AT ADDRESS CDF. + 12. AND USES AS MUCH FREE ; CORE AS IS NECESSARY IN ORDER TO SET UP THE DESIRED NUMBER ; OF LINES USED FOR SCROLLING. EACH LINE OF THIS DISPLAY ; FILE STARTS WITH A POINT INSTRUCTION, FOLLOWED BY A 0 ; X CO-ORDINATE, AND A Y CO-ORDINATE THAT VARIES WITH THE ; VERTICAL POSITION OF THE LINE. NEXT IS THE CHAR INSTRUCTION ; WHICH IS FOLLOWED BY CHR.SC NUMBER OF BYTES ; CD$END: .WORD 0 ; LAST WORD + 2 OF DISPLAY FILE ; $CDSET: CMP CD$NEW,#31. ; TOO MANY LINES ? BLE CD.4 ; NO, CONTINUE MOV #31.,CD$NEW ; YES, SO SET 31 MAXIMUM CD.4: TST CD$NEW ; ARE THERE ENOUGH LINES ? BGT CD.5 ; YES, CONTINUE MOV #1,CD$NEW ; NO, SO SET 1 MINIMUM CD.5: MOV CD$NEW,CD$OLD ; SAVE NUMBER OF LINES CLR CD$FST ; WHERE DOES TOP LINE BELONG ? MOV #CDF.+12.,R0 ; R0 POINTS TO CDF MOV CD$NEW,R1 ; NUMBER OF LINES IN R1 CD.6: ADD #DST.SC,CD$FST ; FIND TOP LINE POSITION BY ADDING MOV #POINT!INT2!BLKOFF,(R0)+; FIRST WORD OF EACH LINE CLR (R0)+ ; CLEAR X POSITION CLR (R0)+ ; AND Y POSITION MOV #CHAR,(R0)+ ; INSERT CHAR INST. MOV #CHR.SC/2,R2 ; # OF WORDS PER LINE CD.7: CLR (R0)+ ; BLANK OUT LINE SOB R2,CD.7 ; LOOP FOR ALL WORDS SOB R1,CD.6 ; LOOP FOR ALL LINES MOV #DJMP,(R0)+ ; DISPLAY FILE ENDS WITH MOV #STATS.,(R0)+ ; A DJMP TO NEXT FILE MOV R0,CD$END ; FIRST FREE WORD MOV R0,DF$TOP ; OF CORE TST -(R0) ; SUBTRACT 2 FROM R0 MOV R0,DF$CDF-2 ; AND SAVE IN DISPLAY TABLE DEC CD$FST ; FIXUP TOP LINE POSITION 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: MOV #ER$ADD,R4 ; FATAL "? ODD ADDRESS REFERENCE ?" CALL $ERROR ; PRINT THE ERROR INC @#DSR ; RING THE BELL BR . ; AND HANG UP .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,#HME.CH ; GIDUS COMMAND ? BNE KB.0 ; NO, CONTINUE CALL GC.SET ; YES DO SETUP BR KB.RET ; AND RETURN KB.0: CMP R0,#LFT.CH ; LEFT ARROW ? BNE KB.1 ; NO, CONTINUE COMB CL$LFT ; YES, CHANGE STATE CLRB CL$RT ; DISABLE MOVEMENT TO RIGHT BR KB.RET ; AND RETURN KB.1: CMP R0,#RT.CH ; RIGHT ARROW ? BNE KB.2 ; NO, CONTINUE COMB CL$RT ; YES, CHANGE STATE CLRB CL$LFT ; DISABLE MOVEMENT TO LEFT BR KB.RET ; AND RETURN KB.2: CMP R0,#UP.CH ; UP ARROW ? BNE KB.3 ; NO, CONTINUE COMB CL$UP ; YES, CHANGE STATE CLRB CL$DWN ; DISABLE MOVEMENT DOWN BR KB.RET ; AND RETURN KB.3: CMP R0,#DWN.CH ; DOWN ARROW ? BNE KB.4 ; NO, CONTINUE COMB CL$DWN ; YES, CHANGE STATE CLRB CL$UP ; DISABLE MOVEMENT UP BR KB.RET ; AND RETURN KB.4: 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: TST $IO$ ; WAS I/O IN PROGRESS BEQ KB.5 ; NO, SEND THE CHARACTER CMP R0,#3 ; WAS IT A CTRL/C ? BNE KB.RET ; NO SO DON'T SEND IT MOV #$DLINT,@#DL$VEC ; YES, RESTORE CHARACTER MODE CLR $IO$ ; CLEAR THE I/O FLAG MOV #"CH,ST.DL ; DL-11 IN CHARACTER MODE MOV #"TI,ST.ATE ; RESTORE GIDUS-STATE KB.5: TSTB @#OS.GT ; IS THE 10 READY BPL KB.5 ; 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$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,#CMD.CH ; ENTER COMMAND MODE ? BNE DL.0 ; NO, PROCESS CHARACTER MOV #"CO,ST.DL ; YES, INDICATE IN STATUS DISPLAY INC $IO$ ; SET THE I/O FLAG MOV #$RCINT,@#DL$VEC ; TRAP INTERRUPTS AT $RCINT MOV ST.ATE,ST.OLD ; SAVE GIDUS STATE MOV #"RC,ST.ATE ; INDICATE GIDUS STATE MOV #9.,RC$CNT ; SET COMMAND BYTE COUNT MOV #RC$CMD,RC$PNT ; SET COMMAND BUFFER POINTER CLR RC$SUM ; CLEAR CHECKSUM BR DL.RET ; AND RETURN DL.0: CMP R0,#ADD.CH ; ENTER ADDFILE MODE ? BNE DL.1 ; NO, PROCESS CHARACTER TST AD$ABF ; CAN NEXT BLOCK BE ACCEPTED ? BNE DL.RET ; NO, DO NOT ACCEPT MOV #"AD,ST.DL ; ADDING, INDICATE IN STATUS DISPLAY INC $IO$ ; SET I/O FLAG MOV #$ADINT,@#DL$VEC ; TRAP INTERRUPTS AT $ADINT MOV ST.ATE,ST.OLD ; SAVE GIDUS STATE MOV #"RC,ST.ATE ; INDICATE RECEIVING BR DL.RET ; AND RETURN DL.1: 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 CD$NEW,R0 ; NUMBER OF LINES MOV #CDF.+12.,R1 ; CDF. POINTER SC.LUP: ADD #DST.SC,4(R1) ; SHIFT LINE UP CMP 4(R1),CD$FST ; 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 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 STOP INTERRUPT ROUTINE ; ; THIS ROUTINE IS EXECUTED EACH TIME THE DISPLAY ; STOPS. IF THERE IS NOTHING TO DO THE DISPLAY ; RESUMES IMMEDIATELY, ELSE A DISPATCH TO THE ; APPROPRIATE ROUTINE IS MADE. ST$FNC: .WORD 0 ; FUNCTION CODE ; ; STOP INTERRUPT DISPATCH TABLE ; ST$DIS: ST.RES ; FUNCT = 0 - RESUME ST.STP ; FUNCT = 1 - STOP DISPLAY ; $STINT: SAVREG ; SAVE THE REGISTERS MOV ST$FNC,R0 ; GET THE FUNCTION CODE ASL R0 ; FORM WORD OFFSET CALL @ST$DIS(R0) ; DISPATCH TO ROUTINE RESREG ; RESTORE THE REGISTERS CLR ST$FNC ; INDICATE NOTHING PENDING MOV #1,@#DPC ; RESUME THE DISPLAY RTI ; RETURN FROM INTERRUPT ; ; ; ; ; ; ST.RES: RETURN ; RETURN IMMEDIATELY ; ST.STP: TST (SP)+ ; IGNORE RETURN ADDRESS RESREG ; RESTORE THE REGISTERS CLR ST$FNC ; CLEAR FUNCTION CODE RTI ; AND RETURN FROM INTERRUPT .PAGE .SBTTL LIGHT PEN INTERRUPT ROUTINE ; LP$FLG: .WORD 0 ; ENABLED/DISABLED FLAG LP$HIT: .WORD 0 ; WAIT FOR HIT FLAG LP$DPC: .WORD 0 ; DPC AT TIME OF HIT ; LP$X: .WORD 0 ; X POSITION OF HIT LP$Y: .WORD 0 ; Y POSITION OF HIT LP$DIS: .WORD 0 ; DISPLAY NUMBER LAST HIT ; $LPINT: TST LP$FLG ; IS LIGHT PEN ENABLED ? BEQ LP.1 ; YES, PROCESS INFORMATION MOV #1,@#DPC ; ELSE RESUME THE DISPLAY RTI ; AND RETURN IMMEDIATELY ; LP.1: SAVREG ; SAVE THE REGISTERS INC LP$FLG ; DISABLE LIGHT PEN (FOR A MOMENT) CLR LP$HIT ; CLEAR THE WAIT CONDITION MOV @#DPC,LP$DPC ; SAVE THE DPC OF HIT MOV @#XSTAT,LP$X ; SAVE X POSITION MOV @#YSTAT,LP$Y ; SAVE Y POSITION MOV #1,@#DPC ; RESUME THE DISPLAY MOV #$$DFT,R0 ; R0 POINTS TO DISPLAY TABLE CLR R1 ; R1 CONTAINS DISPLAY NUMBER LP.2: CMP @R0,LP$DPC ; HIT IN THIS DISPLAY ? BHI LP.3 ; NO IT OCCURRED BEFORE CMP 2(R0),LP$DPC ; HIT IN THIS DISPLAY ? BHIS LP.FND ; YES, RETURN DISPLAY NUMBER LP.3: ADD #6,R0 ; NO, POINT TO NEXT DISPLAY INC R1 ; GET NEXT DISPLAY NUMBER CMP R1,#77 ; ARE WE THROUGH BLE LP.2 ; NO CONTINUE CHECKING CLR R1 ; ELSE 0 = BAD HIT LP.FND: MOV R1,LP$DIS ; SET UP DISPLAY NUMBER CLR LP$FLG ; RE-ENABLE LIGHT PEN MOV #"LE,ST.LP ; RESET STATUS DISPLAY RESREG ; RESTORE THE REGISTERS RTI ; RETURN FROM INTERRUPT .PAGE .SBTTL CLOCK INTERRUPT ROUTINE ; ; THIS ROUTINE COUNTS OFF A SPECIFIED NUMBER OF ; CLOCK TICS. WHEN THE COUNT REACHES ZERO THE ; ROUTINE CHECKS WHETHER ANY MOVEMENT ARROWS ; ARE ENABLED. IF SO THE ROUTINE CHECKS WHETHER ; MP. IS ENABLED (BIT 15 OF SWR) OR AP. ENABLED ; (BIT 1 OF SWR). NOTE THAT ONLY ONE POINTER MAY ; BE ENABLED IN THIS MANNER AND THE MAIN POINTER ; ALWAYS HAS PRECEDENCE OVER THE AUXILLARY POINTER. ; CL$RT: .BYTE 0 ; 1 = MOVE TO RIGHT CL$LFT: .BYTE 0 ; 1 = MOVE TO LEFT CL$UP: .BYTE 0 ; 1 = MOVE UP CL$DWN: .BYTE 0 ; 1 = MOVE DOWN ; CL$CNT: .WORD 2 ; NUMBER OF TICS TO WAIT ; BETWEEN MOVES CL$TIC: .WORD 2 ; RE-INITIALIZING VALUE FOR CL$CNT ; $CLINT: DEC CL$CNT ; DECREMENT COUNT BLE CL.0 ; CLOCK HAS TICKED AWAY JMP CL.RET ; ELSE RETURN CL.0: MOV CL$TIC,CL$CNT ; RESET COUNT BIT #100000,@#SWR ; MP. ENABLED ? BEQ CL.AP ; NO, SO CHECK AP. TSTB CL$RT ; MOVE RIGHT ? BEQ CL.1 ; NO, CONTINUE CMP MP.X,#MAXX ; CAN GO RIGHT ? BGE CL.1 ; NO, CONTINUE INC MP.X ; MOVE TO THE RIGHT CL.1: TSTB CL$LFT ; MOVE LEFT ? BEQ CL.2 ; NO, CONTINUE TST MP.X ; CAN GO LEFT ? BLE CL.2 ; NO, CONTINUE DEC MP.X ; MOVE TO LEFT CL.2: TSTB CL$UP ; MOVE UP ? BEQ CL.3 ; NO, CONTINUE CMP MP.Y,#MAXY ; CAN GO UP ? BGE CL.3 ; NO CONTINUE INC MP.Y ; MOVE UP CL.3: TSTB CL$DWN ; MOVE DOWN ? BEQ CL.FRM ; NO, CONTINUE TST MP.Y ; CAN GO DOWN ? BLE CL.FRM ; NO, CONTINUE DEC MP.Y ; MOVE DOWN CL.FRM: FORMAT MP.Y,ST.MPY,4 ; FORMAT THE NEW FORMAT MP.X,ST.MPX,4 ; X & Y POSITION BR CL.RET ; AND RETURN .PAGE ; CL.AP: BIT #1,@#SWR ; AP. ENABLED ? BEQ CL.RET ; NO, SO RETURN TSTB CL$RT ; YES, MOVE RIGHT ? BEQ CL.4 ; NO, CONTINUE CMP AP.X,#MAXX ; YES, CAN MOVE RIGHT ? BGE CL.4 ; NO, SO CONTINUE INC AP.X ; MOVE TO RIGHT CL.4: TSTB CL$LFT ; MOVE LEFT ? BEQ CL.5 ; BO, CONTINUE TST AP.X ; CAN MOVE LEFT ? BLE CL.5 ; NO, CONTINUE DEC AP.X ; MOVE TO LEFT CL.5: TSTB CL$UP ; MOVE UP ? BEQ CL.6 ; NO, CONTINUE CMP AP.Y,#MAXY ; CAN MOVE UP ? BGE CL.6 ; NO, CONTINUE INC AP.Y ; MOVE UP CL.6: TSTB CL$DWN ; MOVE DOWN ? BEQ CL.FRA ; NO, CONTINUE TST AP.Y ; CAN MOVE DOWN ? BLE CL.FRA ; NO, CONTINUE DEC AP.Y ; MOVE DOWN CL.FRA: FORMAT AP.Y,ST.APY,4 ; FORMAT X & Y POSITION FORMAT AP.X,ST.APX,4 ; INTO STATUS DISPLAY CL.RET: RTI ; RETURN FROM INTERRUPT .PAGE .SBTTL GIDUS COMMAND INTERPRETER ; ; THIS SET OF ROUTINES ARE USED TO ACCEPT KEYBOARD ; COMMANDS AND PROCESS THEM. NOTE THAT $GCINT IS ; AN ALTERNATE INTERRUPT ROUTINE FOR THE GT40 ; KEYBOARD. INTERRUPTS ARE PROCESSED HERE WHEN IN ; "GIDUS MODE", AND ARE PROCESSED BY $KBINT ; WHEN IN "HOST MODE" ; GC$TRC: .WORD 0 ; TRACE VARIABLE GC$ADR: .WORD 0 ; EXAMINE/MODIFY ADDRESS GC$ARG: .WORD 0 ; COMMAND ARGUMENT GC$PNT: .WORD 0 ; COMMAND CHARACTER POINTER ; ; COMMAND DISPATCH TABLE ; GC$DIS: .WORD "DI,GC.DI ; DISABLE COMMAND .WORD "EN,GC.EN ; ENABLE COMMAND .WORD "SP,GC.SP ; SPEED COMMAND .WORD "EX,GC.EX ; EXAMINE COMMAND .WORD "MO,GC.MO ; MODIFY COMMAND .WORD "TR,GC.TR ; TRACE COMMAND .WORD "DE,GC.DE ; DELETE COMMAND .WORD "HE,GC.HE ; HELP COMMAND .WORD "OF,GC.OF ; OFF COMMAND .WORD "LE,GC.LE ; ENABLE L.P. COMMAND .WORD "LD,GC.LD ; DISABLE L.P. COMMAND .WORD "RE,GC.RE ; RESET COMMAND .PAGE ; GIDUS COMMAND SET UP ROUTINE ; ; THIS ROUTINE IS CALLED TO ENABLE GIDUS COMMANDS ; WHEN "HOME" IS HIT DURING "HOST MODE" ; GC.SET: MOV #GC.END,GC.HLP ; DISABLE HELP SUB-FILE MOV #" ,R0 ; PREPARE TO BLANK MOV #7,R1 ; OUT COMMAND LINE MOV #GC.LNE,R2 GC.CLR: MOV R0,(R2)+ ; BLANK OUT 7 WORDS SOB R1,GC.CLR ; FOR A TOTAL OF 14 CHARACTERS MOV #7,R5 ; ENABLE GIDUS COMMAND CALL $ENABL ; DISPLAY FILE MOV #GC.LNE,GC$PNT ; SET UP CHARACTER POINTER CLR GC$ADR ; CLEAR INPUT ADDRESS CLR GC$ARG ; AND INPUT ARGUMENT MOV #$GCINT,@#KB$VEC ; TRAP FURTHER KB INTERRUPTS MOV #"GI,ST.ATE ; CHANGE GIDUS STATE RETURN ; RETURN TO $KBINT .PAGE ; $GCINT - GIDUS COMMAND INTERRUPT ROUTINE ; $GCINT: SAVREG ; SAVE THE REGISTERS MOVB @#IB.KB,R0 ; GET THE INPUT CHARACTER BIC #177600,R0 ; CLEAR TOP BYTE AND PARITY CMP R0,#HME.CH ; IS THIS A HOME? BNE GC.1 ; NO, CONTINUE MOV #7,R5 ; YES, DISABLE COMMAND CALL $DSABL ; DISPLAY FILE MOV #$KBINT,@#KB$VEC ; RESET INTERRUPT VECTOR (HOST) MOV #"TI,ST.ATE ; CHANGE GIDUS STATE BR GC.RET ; AND RETURN GC.1: CMP R0,#CR.CH ; CARRIAGE RETURN ? BEQ GC.PRC ; YES, PROCESS COMMAND MOV GC$PNT,R1 ; NO, R1 BECOMES CHAR. POINTER CMP R0,#RUB.CH ; IS THIS A RUBOUT? BNE GC.2 ; NO, CONTINUE CMP R1,#GC.LNE ; YES, IS THERE ANYTHING TO ZAP BLOS GC.2 ; NO, CONTINUE MOVB #' ,-(R1) ; ABRA CADABRA - DISAPPEAR MOV R1,GC$PNT ; RESET POINTER BR GC.RET ; AND RETURN GC.2: CMP R0,#SP.CH ; IS THIS A PRINTING CHARACTER ? BLT GC.RET ; NO, RETURN CMP R0,#'Z ; IS IT UPPER CASE ? BLE GC.2.5 ; NO, SO GOOD CHARACTER SUB #32.,R0 ; YES, SO FORCE UPPER CASE GC.2.5: CMP R1,#GC.LNE+14. ; GOOD CHAR, IS THERE ROOM ? BHIS GC.RET ; NO, IGNORE AND RETURN MOVB R0,(R1)+ ; YES, ADD THE CHARACTER MOV R1,GC$PNT ; RESET THE POINTER GC.RET: RESREG ; RESTORE THE REGISTERS RTI ; RETURN FROM INTERRUPT .PAGE .SBTTL GIDUS COMMAND PROCESSING ROUTINE ; ; THIS ROUTINE IS CALLED WHEN A GIDUS COMMAND ; IS TERMINATED BY A CARRIAGE RETURN ; GC.PRC: MOV #" ,R0 ; R0 IS USED TO MOV #GC.ANS,R1 ; BLANK OUT COMMAND REPLY MOV R0,(R1)+ ; MOV R0,(R1)+ ; CLEAR SIX CHARACTERS MOV R0,(R1)+ ; MOV #GC.END,GC.HLP ; DISABLE HELP SUB-FILE MOV #GC.LNE,R0 ; R0 POINTS TO START OF COMMAND MOV GC$PNT,R1 ; R1 POINTS AT END OF COMMAND CALL GC.NUM ; GET THE NUMBER MOV #GC.LNE,R0 ; R0 POINTS TO START OF COMMAND MOV #12.,R1 ; 12 COMMANDS IN TOTAL MOV #GC$DIS,R2 ; R2 POINTS TO DISPATCH TABLE GC.LUK: CMP @R0,(R2)+ ; IS THIS THE COMMAND ? BNE GC.3 ; NO, CONTINUE LOOKING JMP @0(R2) ; YES, EXECUTE THAT COMMAND GC.3: TST (R2)+ ; NO, POINT TO NEXT COMMAND SOB R1,GC.LUK ; AND TRY AGAIN ; GC.FIN: MOV #7,R1 ; INVALID COMMAND OR THROUGH MOV #" ,R0 ; BLANK OUT THE COMMAND MOV #GC.LNE,R2 ; LINE GC.4: MOV R0,(R2)+ ; 7 WORDS = 14 CHARACTERS SOB R1,GC.4 MOV #GC.LNE,GC$PNT ; RESET THE CHARACTER POINTER BR GC.RET ; AND RETURN .PAGE ; GC.NUM - RETURNS COMMAND ARGUMENT IN GC$ARG ; GC.NUM: CLR R5 ; CLEAR WORD TO BE FORMED GC.LUP: CMP R0,R1 ; ARE WE THROUGH LINE ? BLO GC.5 ; NO, CONTINUE MOV R5,GC$ARG ; YES, SAVE ARGUMENT RETURN ; AND RETURN GC.5: MOVB (R0)+,R2 ; GET NEXT CHARACTER CMP R2,#'0 ; IS IT A DIGIT ? BLT GC.LUP ; NO, CONTINUE CMP R2,#'7 ; IS IT AN OCTAL DIGIT ? BGT GC.LUP ; NO CONTINUE SUB #60,R2 ; YES, CONVERT TO BINARY ASL R5 ; ASL R5 ; SHIFT ONE OCTAL DIGIT ASL R5 ; BIS R2,R5 ; INSERT THE DIGIT BR GC.LUP ; CONTINUE TIL THROUGH .PAGE GC.DI: MOV GC$ARG,R5 ; GET DISPLAY FILE NUMBER CALL $DSABL ; DISABLE THAT DISPLAY FILE BR GC.FIN ; GC.EN: MOV GC$ARG,R5 ; GET DISPLAY FILE NUMBER CALL $ENABL ; ENABLE THAT DISPLAY FILE BR GC.FIN ; GC.SP: MOV #12,R5 ; SET SPEED = 12 - SPEED SUB GC$ARG,R5 MOV R5,CL$TIC ; AND SAVE AS NUMBER OF TICS BR GC.FIN ; GC.EX: MOV GC$ARG,GC$ADR ; SAVE ARGUMENT AS ADDRESS FORMAT @GC$ADR,GC.ANS,6 ; PRINT THAT LOCATION BR GC.FIN ; GC.MO: MOV GC$ARG,@GC$ADR ; MOVE ARGUMENT @ADDRESS BR GC.FIN ; GC.TR: MOV GC$ARG,GC$TRC ; SAVE ARGUMENT AS TRACE ADDRESS MOV GC$ARG,GC$ADR ; AND EXAMINE ADDRESS BR GC.FIN ; GC.DE: MOV GC$ARG,R5 ; GET DISPLAY NUMBER CALL $DELET ; AND DELETE IT BR GC.FIN ; GC.HE: MOV #GC.HLP,R0 ; ALTER THE DJMP MOV #GC.HLP+2,@R0 ; TO POINT TO NEXT WORD BR GC.FIN ; GC.OF: MOV #ME.END,ME.ON ; TURN OFF ERROR MESSAGE BR GC.FIN ; GC.LE: CLR LP$FLG ; INDICATE L.P. ENABLED MOV #"LE,ST.LP ; SHOW ENABLED IN STATUS DISPLAY BR GC.FIN ; GC.LD: INC LP$FLG ; INDICATE L.P. DISABLED MOV #"LD,ST.LP ; SHOW DISABLED IN STATUS DISPLAY BR GC.FIN ; GC.RE: TST GC$ARG ; HOW MANY LINES ? BEQ GC.RE1 ; IF ZERO THEN DON'T CHANGE MOV GC$ARG,CD$NEW ; ELSE SAVE GC.RE1: CALL $RESET ; DO THE RESET BR GC.FIN ; AND RETURN .PAGE .SBTTL RECEIVE COMMAND ROUTINE ; $RCINT - RECEIVE INTERRUPT ROUTINE TO FILL COMMAND BUFFER ; ; RECEIVER BUFFER ; RC$CMD: .WORD 0 ; COMMAND WORD RC$BCT: RC$DIS: .WORD 0 ; BLOCK COUNT OR DISPLAY # RC$STA: RC$X: .WORD 0 ; BLOCK #, STATUS, OR XPOS RC$Y: .WORD 0 ; Y POSITION RC$SUM: .WORD 0 ; CHECKSUM ; RC$PNT: .WORD 0 ; BUFFER POINTER RC$CNT: .WORD 0 ; BUFFER BYTE COUNT ; $IO$: .WORD 0 ; I/O FLAG RC$OPT: .WORD 0 ; REQUESTING OPTION FLAG ; $RCINT: SAVREG ; SAVE THE REGISTERS MOVB @#IB.GT,R0 ; GET THE INCOMING BYTE BIC #177400,R0 ; CLEAR TOP BYTE ADD R0,RC$SUM ; ADD INTO CHECKSUM DEC RC$CNT ; DECREMENT THE BYTE COUNT BLE RC.CMD ; PROCESS THE COMMAND IF THROUGH MOVB R0,@RC$PNT ; ELSE BUFFER THIS BYTE INC RC$PNT ; AND BUMP THE POINTER RC.RET: RESREG ; RESTORE THE REGISTERS RTI ; AND RETURN FROM INTERRUPT .PAGE ; RECEIVE COMMAND DISPATCH TABLE ; RC$DSP: .WORD RC.NC ; [0] INVALID COMMAND .WORD RC.EN ; [1] ENABLE DISPLAY FILE .WORD RC.DS ; [2] DISABLE DISPLAY FILE .WORD RC.MOV ; [3] MOVE DISPLAY FILE .WORD RC.RMP ; [4] REQUEST MAIN POINTER .WORD RC.RAP ; [5] REQUEST AUX. POINTER .WORD RC.DL ; [6] DISABLE LIGHT PEN .WORD RC.EL ; [7] ENABLE LIGHT PEN .WORD RC.RLH ; [8] REQUEST LAST L.P. HIT .WORD RC.RNH ; [9] REQUEST NEW L.P. HIT .WORD RC.RAD ; [10] REQUEST TO ADD DISPLAY .WORD RC.ANB ; [11] ADD NEXT BLOCK .WORD RC.DEL ; [12] DELETE DISPLAY FILE .WORD RC.SND ; [13] RE-SEND LAST TRANSMISSION .WORD RC.CLR ; [14] CLEAR CDF. .WORD RC.RST ; [15] RESET GIDUS .WORD RC.OPT ; [16] REQUEST OPTION HIT ; ; RC.CMD: MOV 14.(SP),@#PSW ; RESTORE PSW (ALLOW INTERRUPTS) TSTB RC$SUM ; TEST CHECKSUM - WAS IT GOOD ? BEQ RC.1 ; YES, CONTINUE WITH PROCESSING MOVB #66,TR$STA ; STATUS = "CHECKSUM ERROR" JMP $TRMIT ; TRANSMIT ; RC.1: MOV RC$CMD,R0 ; GET COMMAND WORD BLT RC.NC ; IF NEGATIVE THEN NO COMMAND CMP R0,#16. ; VALID COMMAND ? BGT RC.NC ; > 13, NO SUCH COMMAND MOVB TR$STA,TR$OLD ; SAVE LAST STATUS CLRB TR$STA ; DEFAULT STATUS IS GOOD ASL R0 ; FORM BYTE OFFSET JMP @RC$DSP(R0) ; EXECUTE THE COMMAND .PAGE .SBTTL COMMAND UTILTY ROUTINES ; RC.NC: MOVB #9.,TR$STA ; STATUS = "NO COMMAND" JMP $TRMIT ; TRANSMIT ; RC.EN: MOV RC$DIS,R5 ; GET DISPLAY NUMBER CALL $ENABL ; AND ENABLE IT ($ENABL SETS STATUS) JMP $TRMIT ; TRANSMIT ; RC.DS: MOV RC$DIS,R5 ; GET DISPLAY NUMBER CALL $DSABL ; AND DISABLE IT ($DSABL SETS STATUS) JMP $TRMIT ; TRANSMIT ; RC.MOV: MOV RC$DIS,R5 ; GET DISPLAY NUMBER CLR SE$MOD ; DIRECT SEARCH MODE CALL $SERCH ; GET DISPLAY STATUS BIT #EX.BIT,4(R4) ; DOES THIS DISPLAY EXIST ? BNE RC.M1 ; YES, CONTINUE CHECKING INCB TR$STA ; NO, STATUS = "NO SUCH DISPLAY" JMP $TRMIT ; TRANSMIT RC.M1: BIT #RL.BIT,4(R4) ; CAN DISPLAY BE MOVED ? BNE RC.M2 ; YES, MOVE IT MOVB #4,TR$STA ; STATUS = "CANNOT MOVE DISPLAY" JMP $TRMIT ; TRANSMIT RC.M2: MOV @R4,R4 ; GET ADDRESS OF FIRST WORD TST (R4)+ ; POINT TO X POSITION MOV RC$X,(R4)+ ; INSERT X AND Y MOV RC$Y,(R4)+ ; POSITION FROM COMMAND CMP R5,#4 ; MAIN POINTER MOVED ? BNE RC.M3 ; NO, CONTINUE FORMAT MP.X,ST.MPX,4 ; YES, SO FORMAT X FORMAT MP.Y,ST.MPY,4 ; AND Y POSITION RC.M3: CMP R5,#5 ; AUXILLARY POINTER MOVED ? BNE RC.M4 ; NO, CONTINUE FORMAT AP.X,ST.APX,4 ; YES, SO FORMAT X FORMAT AP.Y,ST.APY,4 ; AND Y POSITION RC.M4: JMP $TRMIT ; TRANSMIT ; RC.RMP: MOV MP.Y,R0 ; GET MAIN POINTER(Y) CALL TR.Y ; AND BUFFER IT MOV MP.X,R0 ; GET MAIN POINTER(X) CALL TR.X ; AND BUFFER IT JMP $TRMIT ; TRANSMIT ; RC.RAP: MOV AP.Y,R0 ; GET AUX. POINTER(Y) CALL TR.Y ; AND BUFFER IT MOV AP.X,R0 ; GET AUX. POINTER(X) CALL TR.X ; AND BUFFER IT JMP $TRMIT ; TRANSMIT .PAGE ; COMMAND UTILITY ROUTINES (CONTINUED) ; RC.DL: MOV #1,LP$FLG ; DISABLE THE LIGHT PEN MOV #"LD,ST.LP ; INDICATE IN STATUS DISPLAY JMP $TRMIT ; TRANSMIT ; RC.EL: CLR LP$FLG ; ENABLE THE LIGHT PEN MOV #"LE,ST.LP ; INDICATE IN STATUS DISPLAY JMP $TRMIT ; TRANSMIT ; RC.RLH: MOV LP$Y,R0 ; GET LAST HIT(Y) CALL TR.Y ; AND BUFFER IT MOV LP$X,R0 ; GET LAST HIT(X) CALL TR.X ; AND BUFFER IT MOVB LP$DIS,TR$DIS ; GET LAST FILE HIT TST RC$OPT ; IS THIS AN OPTION ? BNE RC.OP1 ; YES, SO PROCESS THE REMAINING JMP $TRMIT ; TRANSMIT ; RC.RNH: TST LP$FLG ; IS LIGHT PEN ENABLED ? BEQ RC.R1 ; YES, WAIT FOR HIT MOVB #5,TR$STA ; ELSE STATUS = "L.P. DISABLED" JMP $TRMIT ; TRANSMIT RC.R1: MOV #1,LP$HIT ; SET WAIT FLAG MOV #"LW,ST.LP ; AND SHOW IN STATUS RC.R2: TST LP$HIT ; AND TWIDDLE THUMBS BNE RC.R2 ; UNTIL WE GET A HIT BR RC.RLH ; PROCESS THE HIT ; RC.DEL: MOV RC$DIS,R5 ; GET DISPLAY NUMBER CALL $DELET ; AND DELETE IT JMP $TRMIT ; TRANSMIT ; RC.SND: MOVB TR$OLD,TR$STA ; RESET STATUS JMP $TRMIT ; AND RE-TRANSMIT LAST BLOCK ; RC.CLR: CALL $CDINI ; INITIALIZE CDF. JMP $TRMIT ; TRANSMIT ; RC.RST: MOV RC$DIS,CD$NEW ; GET DESIRED NUMBER OF LINES CALL $RESET ; AND RESET GIDUS JMP $TRMIT ; TRANSMIT ; RC.OPT: DISABL 10 ; DISABLE THE POINTER ENABLE 6 ; ENABLE THE PROMPT INC RC$OPT ; INDICATE AN OPTION HIT BR RC.RNH ; GET LIGHT PEN HIT RC.OP1: DISABL 6 ; DISABLE THE PROMPT MOV #740.,OP$X ; MOVE THE OPTION POINTER MOV LP$Y,OP$Y ENABLE 10 ; AND ENABLE THE POINTER JMP $TRMIT ; AND TRANSMIT .PAGE .SBTTL REQUEST TO ADD ; ; THIS ROUTINE PERFORMS THE FOLLOWING FUNCTIONS: ; ; [1] CHECKS IF THERE IS A FREE DISPLAY SLOT FOR FILE ; [2] CHECKS IF THERE IS ENOUGH CORE FOR THE FILE ; [3] SETS A MEMORY LIMIT BEYOND WHICH THE ADDITION CANNOT GO ; [4] SETS UP MEMORY AREA FOR ADDITION ; RC.RAD: MOV #1,AD$FLG ; INDICATE ADDITION NOT ALLOWED CMP DU$CNT,#77 ; IS THERE A DISPLAY SLOT ? BLE RC.R3 ; YES, CONTINUE CHECKING MOVB #7,TR$STA ; NO, STATUS = "NO DISPLAY SLOT" JMP $TRMIT ; TRANSMIT STATUS RC.R3: MOV RC$BCT,R0 ; GET FILE SIZE ADD #10.,R0 ; ADD SAFETY FACTOR MOV #STACK,R1 ; GET UPPER MEMORY BOUND SUB DF$TOP,R1 ; SUBTRACT LOWER MEMORY BOUND CMP R0,R1 ; IS THERE ENOUGH CORE ? BLT RC.R4 ; YES, ALLOW THE ADDITION MOVB #6,TR$STA ; NO, STATUS ="NOT ENOUGH CORE" JMP $TRMIT ; TRANSMIT RC.R4: MOV R0,AD$LIM ; SAVE SIZE FOR CHECK ADD DF$TOP,AD$LIM ; DON'T ALLOW ADDITION PAST MOV DF$TOP,AD$RST ; GET RESET POINTER MOV DF$TOP,AD$PNT ; AND ACTIVE POINTER CLR AD$FLG ; ALLOW ADDITION MOVB #11.,TR$STA ; STATUS = "SEND NEXT BLOCK" JMP $TRMIT ; TRANSMIT .PAGE .SBTTL ADD NEXT BLOCK COMMAND ; ; THIS ROUTINE PERFORMS THE FOLLOWING FUNCTION ; ; [1] CHECK FOR NULL BLOCK (I.E. DISPLAY FILE SENT) ; [2] CHECK FOR VALID BYTE COUNT ; [3] CHECK IF LIMIT EXCEEDED ; [4] UPDATE FILE POINTERS ; [5] TELL 10 TO SEND BLOCK ; RC.ANB: MOV #1,AD$ABF ; DON'T ALLOW BLOCK MOV RC$BCT,R0 ; GET BYTE COUNT BLE RC.LST ; IF ZERO THEN LAST BLOCK CMP R0,#200 ; VALID BYTE COUNT ? BLE RC.A1 ; YES MOVB #12.,TR$STA ; NO, STATUS = "BAD BLOCK SIZE" JMP $TRMIT ; TRANSMIT RC.A1: MOV AD$RST,R1 ; GET START ADDRESS ADD R0,R1 ; ADD BYTE COUNT CMP R1,AD$LIM ; DOES IT EXCEED LIMIT ? BLO RC.A2 ; NO MOVB #6,TR$STA ; STATUS = "NOT ENOUGH CORE" JMP $TRMIT ; TRANSMIT RC.A2: TST AD$FLG ; ADDITONS ALLOWED ? BEQ RC.A3 ; YES MOVB #14.,TR$STA ; NO, STATUS = "ADDITION NOT ALLOWED" JMP $TRMIT ; TRANSMIT RC.A3: MOV AD$RST,AD$PNT ; UPDATE ACTIVE POINTER CLR AD$SUM ; CLEAR THE CHECKSUM MOV R0,AD$CNT ; CLEAR THE BYTE COUNT MOVB #11.,TR$STA ; STATUS = "SEND NEXT BLOCK" CLR AD$ABF ; CLEAR THE ALLOW BLOCK FLAG JMP $TRMIT ; TRANSMIT .PAGE .SBTTL LAST BLOCK ROUTINE ; ; THIS ROUTINE PERFORMS THE FOLLOWING FUNCTIONS ; ; [1] INSERTS DISPLAY INFORMATION INTO THE FIRST ; AVAILABLE DISPLAY SLOT ; [2] INFORMS 10 OF THE DISPLAY SLOT CHOSEN ; [3] UPDATE STATUS DISPLAY WITH ; NUMBER OF DISPLAYS, NUMBER DISABLED, AND FREE CORE ; RC.LST: MOV #$$DFT,R0 ; R0 POINTS TO DISPLAY TABLE CLR R1 ; R1 IS DISPLAY NUMBER RC.L1: BIT #EX.BIT,4(R0) ; IS THIS SLOT IN USE BEQ RC.L2 ; NO, SO USE IT ADD #6,R0 ; ELSE POINT TO NEXT SLOT INC R1 ; AND BUMP DISPLAY NUMBER CMP R1,#77 ; ARE WE THROUGH ? BLT RC.L1 ; NO, SO CONTINUE RC.L2: MOV DF$TOP,(R0)+ ; INSERT FIRST ADDRESS MOV AD$RST,@R0 ; AND LAST ADDRESS SUB #2,(R0)+ ; POINT TO LAST WORD MOV RC$STA,@R0 ; INSERT THE STATUS WORD BIS #EX.BIT,@R0 ; SET THE EXIST BIT BIC #EN.BIT,@R0 ; CLEAR THE ENABLED BIT MOVB R1,TR$DIS ; BUFFER THE DISPLAY NUMBER FORMAT R1,ST.LST,2 ; AND SHOW IN STATUS DISPLAY INC DU$CNT ; INCREMENT THE USED COUNT FORMAT DU$CNT,ST.USE,2 ; AND FORMAT INTO STATUS DISPLAY INC DS$CNT ; INCREMENT THE DISABLED COUNT FORMAT DS$CNT,ST.DIS,2 ; AND FORMAT INTO STATUS DISPLAY MOV AD$RST,DF$TOP ; UPDATE LOWER MEMORY BOUND MOV #STACK,R1 ; GET UPPER MEMORY BOUND SUB DF$TOP,R1 ; SUBTRACT LOWER BOUND ASR R1 ; FORM WORD COUNT FORMAT R1,ST.FRE,5 ; FORMAT THE FREE CORE CLRB TR$STA ; ADDITION COMPLETED JMP $TRMIT ; TRANSMIT .PAGE .SBTTL ADD FILE INTERRUPT ROUTINE ; ; STATUS WORDS ; AD$LIM: .WORD 0 ; ADDITION CAN'T GO BEYOND AD$CNT: .WORD 0 ; BYTE COUNT AD$SUM: .WORD 0 ; CHECKSUM AD$PNT: .WORD 0 ; ACTIVE POINTER AD$RST: .WORD 0 ; RESET POINTER AD$FLG: .WORD 0 ; ALLOW FLAG AD$ABF: .WORD 0 ; ALLOW NEXT BLOCK FLAG ; $ADINT: SAVREG ; SAVE THE REGISTERS MOVB @#IB.GT,R0 ; GET THE LAST CHARACTER BIC #177400,R0 ; CLEAR THE TOP BYTE ADD R0,AD$SUM ; ADD INTO CHECKSUM DEC AD$CNT ; DECREMENT THE BYTE COUNT BLE AD.1 ; IF ZERO THEN THROUGH MOVB R0,@AD$PNT ; ELSE BUFFER THE BYTE INC AD$PNT ; BUMP THE POINTER AD.RET: RESREG ; RESTORE THE REGISTERS RTI ; RETURN FROM INTERRUPT ; AD.1: MOV 14.(SP),@#PSW ; ALLOW INTERRUPTS TSTB AD$SUM ; IS THE CHECKSUM GOOD ? BNE AD.2 ; NO BIC #1,AD$PNT ; YES MAKE THE LAST BYTE EVEN MOV AD$PNT,AD$RST ; UPDATE RESET ADDRESS MOVB #15.,TR$STA ; INDICATE BLOCK RECEIVED JMP $TRMIT ; AD.2: MOV AD$RST,AD$PNT ; RESET ACTIVE POINTER MOVB #66,TR$STA ; INDICATE CHECKSUM ERROR JMP $TRMIT ; TRANSMIT .PAGE .SBTTL TRANSMISSION ROUTINE ; ; TRANSMIT BUFFER ; TR$STA: .BYTE 0 ; STATUS BYTE TR$XL: .BYTE 0 ; X POSITION TR$XH: .BYTE 0 TR$YL: .BYTE 0 ; Y POSITION TR$YH: .BYTE 0 TR$DIS: .BYTE 0 ; DISPLAY NUMBER TR$SUM: .BYTE 0 ; CHECK SUM .BYTE 0 ; FILLER ; TR$OLD: .BYTE 0 ; LAST STATUS ; .EVEN $TRMIT: MOV #"TR,ST.ATE ; INDICATE "TRANSMITTING" CLR TR$SUM ; CLEAR THE CHECKSUM CLR RC$OPT ; TURN OFF OPTION FLAG MOV #TR$STA,R4 ; R4 IS BUFFER POINTER MOV #6,R3 ; BYTE COUNT TR.LUP: MOVB (R4)+,R5 ; GET THE NEXT BYTE ADD R5,TR$SUM ; ADD INTO CHECKSUM CMP R5,#74 ; IS IT A SPECIAL CHARACTER BGE TR.1 ; YES, SO BYPASS BIS #100,R5 ; ELSE MAKE PRINTABLE TR.1: CALL $SEND ; AND SEND IT SOB R3,TR.LUP ; DO SO FOR ALL CHARACTERS CLR R5 ; GET READY TO GET LOW BYTE BISB TR$SUM,R5 ; GET CHECKSUM ASR R5 ; ASR R5 ; SHIFT R5 FOUR PLACES ASR R5 ; IN ORDER TO GET HIGH 4 BITS ASR R5 ; BIS #100,R5 ; MAKE IT PRINTABLE CALL $SEND ; SEND FIRST HALF OF CSUM MOVB TR$SUM,R5 ; GET CHECKSUM BIC #177760,R5 ; CLEAR ALL EXCEPT LOW 4 BITS BIS #100,R5 ; MAKE PRINTABLE CALL $SEND ; SEND LAST HALF OF CHECKSUM MOV #$DLINT,DL$VEC ; RESET INTERRUPT VECTOR CLR $IO$ ; CLEAR I/O FLAG MOV ST.OLD,ST.ATE ; RESTORE GIDUS STATE RESREG ; RESTORE THE REGISTERS MOV #"CH,ST.DL ; RESTORE DL-11 STATE RTI ; RETURN FROM INTERRUPT ; TR.X: MOVB R0,TR$XL ; GET LOW BYTE BICB #340,TR$XL ; ONLY WANT FIVE BITS ASL R0 ; SHIFT R0 UP ASL R0 ; ASL R0 ; THREE BITS SWAB R0 ; SWAP THE BYTES MOVB R0,TR$XH ; GET HIGH BYTE BICB #340,TR$XH ; ONLY WANT FIVE BITS RETURN ; RETURN ; BICB #340,TR$YL ; ONLY WANT FIVE BITS ASL R0 ; SHIFT R0 UP ASL R0 ; ASL R0 ; THREE BITS SWAB R0 ; SWAP THE BYTES MOVB R0,TR$YH ; GET HIGH BYTE BICB #340,TR$YH ; ONLY WANT FIVE BITS RETURN ; RETURN ; TR.Y: CALL TR.X ; FORMAT INTO X FIELD MOVB TR$XL,TR$YL ; AND MOVE INTO MOVB TR$XH,TR$YH ; Y FIELD RETURN ; AND RETURN .PAGE $SEND: TSTB @#OS.GT ; IS 10 READY BPL $SEND ; WAIT UNTIL READY MOVB R5,@#OB.GT ; SEND THE CHARACTER RETURN ; RETURN .PAGE .SBTTL ENABLE A DISPLAY FILE ; ; UPON ENTRY R5 CONTAINS DISPLAY FILE ; NUMBER TO BE ENABLED ; $ENABL: SAVREG ; SAVE THE REGISTERS CLRB TR$STA ; INDICATE GOOD ENABLE TST R5 ; IS DISPLAY NUMBER NEGATIVE ? BLT EN.BN ; YES, ERROR CMP R5,#77 ; IS DISPLAY NUMBER IN RANGE BLE EN.GN ; YES, GOOD NUMBER EN.BN: MOV #ER$BDN,R4 ; R4 IS ERROR POINTER CALL $ERROR ; WARNING "% BAD DISPLAY NUMBER" MOVB #3,TR$STA ; INDICATE ERROR CONDITION BR EN.RET ; RETURN EN.GN: CLR SE$MOD ; INDICATE DIRECT SEARCH MODE CALL $SERCH ; GET THIS DISPLAY STATUS BIT #EX.BIT,4(R4) ; DOES THE DISPLAY EXIST ? BNE EN.1 ; YES, CONTINUE MOV #ER$DDE,R4 ; R4 IS ERROR POINTER CALL $ERROR ; WARNING "%DISPLAY DOES NOT EXIST" INCB TR$STA ; LET 10 KNOW THE ERROR BR EN.RET ; AND RETURN EN.1: BIT #EN.BIT,4(R4) ; IS THE DISPLAY ENABLED ? BNE EN.RET ; YES, RETURN MOV R4,R3 ; SAVE POINTER TO THIS ENTRY INC SE$MOD ; INDICATE INDIRECT SEARCH MODE CALL $SERCH ; FIND A DISPLAY POINTING PAST TST R4 ; WAS THE DISPLAY FOUND ? BGT EN.FND ; YES, CONTINUE MOV #ER$FNF,R4 ; R4 IS ERROR POINTER CALL $ERROR ; FATAL "? DISPLAY TABLE CORRUPT" BR EN.RET ; RETURN ; EN.FND: CALL $DSTOP ; POLITELY STOP THE DISPLAY MOV 2(R4),R0 ; GET ADDR. OF LAST WORD OF PREV. DISP. MOV 2(R3),R1 ; GET ADDR. OF LAST WORD OF THIS DISP. MOV @R0,@R1 ; NEW DISPLAY DJMPS TO NEXT IN LIST CLR @R0 ; RESET PREV. DISP. TO POINT BIS @R3,@R0 ; TO NEW DISPLAY MOV 4(R4),R0 ; GET STATUS POINTER OF PREV. DISP. BIC #177700,R0 ; MASK OUT ALL BUT POINTER BIS R0,4(R3) ; COPY POINTER TO NEW DISP. BIC #PT.BIT,4(R4) ; CLEAR POINTER OF PREV. DISP. BIS R5,4(R4) ; INSERT NEW DISPLAY NUMBER DEC DS$CNT ; DECREMENT THE DISABLED COUNT FORMAT DS$CNT,ST.DIS,2 ; AND FORMAT INTO STATUS DISPLAY BIS #EN.BIT,4(R3) ; INDICATE DISPLAY IS ENABLED MOV #FIRST.,@#DPC ; RESTART THE DISPLAY EN.RET: RESREG ; RESTORE THE REGISTERS RETURN ; AND RETURN .PAGE .SBTTL DISABLE A DISPLAY FILE ; ; UPON ENTRY R5 CONTAINS DISPLAY NUMBER ; TO BE DISABLED ; DU$CNT: .WORD 12 ; NUMBER OF DISPLAY FILES USED DS$CNT: .WORD 3 ; NUMBER OF DISABLED DISPLAY FILES ; $DSABL: SAVREG ; SAVE THE REGISTERS CLRB TR$STA ; INDICATE GOOD DISABLE TST R5 ; IS DISPLAY NUMBER NEGATIVE BLT DS.BN ; YES, ERROR CMP R5,#77 ; IS DISPLAY NUMBER IN RANGE ? BLE DS.GN ; YES, WE HAVE A GOOD NUMBER DS.BN: MOV #ER$BDN,R4 ; R4 IS ERROR POINTER CALL $ERROR ; WARNING "% BAD DISPLAY NUMBER" MOVB #3,TR$STA ; INDICATE ERROR CONDITION BR DS.RET ; RETURN DS.GN: CLR SE$MOD ; INDICATE DIRECT SEARCH MODE CALL $SERCH ; GET THIS DISPLAY STATUS BIT #EN.BIT,4(R4) ; IS DISPLAY DISABLED ? BEQ DS.RET ; YES, RETURN BIT #ND.BIT,4(R4) ; CAN DISPLAY BE DISABLED ? BEQ DS.1 ; YES, DO SO MOV #ER$ND,R4 ; R4 IS #ERROR POINTER CALL $ERROR ; WARNING "% CANNOT DISABLE" MOVB #2,TR$STA ; INDICATE ERROR CONDITION BR DS.RET ; RETURN DS.1: MOV R4,R3 ; SAVE POINTER TO THIS ENTRY DEC SE$MOD ; INDICATE INDIRECT SEARCH MODE CALL $SERCH ; FIND THE PREVIOUS DISPLAY TST R4 ; WAS THE DISPLAY FOUND ? BGT DS.FND ; YES, CONTINUE MOV #ER$FNF,R4 ; R4 IS ERROR POINTER CALL $ERROR ; FATAL "? DISPLAY TABLE CORRUPT" BR DS.RET ; RETURN ; DS.FND: CALL $DSTOP ; STOP THE DISPLAY MOV 2(R4),R0 ; GET ADDR. OF LAST WORD OF PREV. DISP. MOV 2(R3),R1 ; GET ADDR. OF LAST WORD OF THIS DISP. CLR @R0 ; RESET PREVIOUS DISPLAY BIS @R1,@R0 ; TO POINT TO NEXT DISPLAY MOV 4(R3),R0 ; R0 GETS POINTER WORD BIC #177700,R0 ; CLEAR ALL EXCEPT POINTER BIC #PT.BIT,4(R4) ; CLEAR PREV. POINTER BIS R0,4(R4) ; CHANGE TO NEW POINTER BIC #PT.BIT,4(R3) ; DISABLE THIS POINTER BIC #EN.BIT,4(R3) ; TURN OFF ENABLED BIT INC DS$CNT ; INCREMENT DISABLED COUNT FORMAT DS$CNT,ST.DIS,2 ; FORMAT INTO STATUS DISPLAY MOV #FIRST.,@#DPC ; RESTART THE DISPLAY DS.RET: RESREG ; RESTORE THE REGISTERS RETURN ; AND RETURN .PAGE .SBTTL DISPLAY TABLE SEARCH ROUTINE ; SE$MOD: .WORD 0 ; SEARCH MODE ; ; 0 = DIRECT SEARCH FOR REQUESTED DISPLAY ; -1 = SEARCH FOR DISPLAY POINTING TO REQUESTED ; 1 = SEARCH FOR DISPLAY POINTING PAST REQUESTED ; $SERCH: MOV #$$DFT,R4 ; R4 POINTS TO DISPLAY TABLE TST SE$MOD ; WHAT KIND OF SEARCH ? BNE SE.IND ; INDIRECT SEARCH MOV R5,R0 ; DIRECT SEARCH, GET NUMBER ASL R0 ; MULTIPLY BY TWO ADD R5,R0 ; ADD (JUST R0 * 3) ASL R0 ; FORM WORD OFFSET ADD R0,R4 ; ADD TO BASE ADDRESS BR SE.RET ; AND RETURN ; SE.IND: MOV #64.,R1 ; R1 = NUMBER OF DISPLAY FILES SE.LUP: MOV 4(R4),R0 ; GET STATUS POINTER WORD BIC #177700,R0 ; CLEAR ALL EXCEPT POINTER CMP R0,R5 ; COMPARE WITH REQUESTED BGE SE.FND ; IF >= SEARCH MAY BE OVER SE.CON: ADD #6,R4 ; ELSE LOOP SOB R1,SE.LUP ; FOR ALL DISPLAY FILES CLR R4 ; INDICATE UNSUCCESSFUL BR SE.RET ; AND RETURN SE.FND: TST SE$MOD ; WHAT KIND OF SEARCH ? BGT SE.PST ; LOOK FOR FILE POINTING PAST CMP R0,R5 ; IS THIS THE ONE ? BNE SE.CON ; NO, CONTINUE BR SE.RET ; YES, RETURN SE.PST: CMP R0,R5 ; IS THIS THE ONE ? BGT SE.RET ; YES, RETURN CLR R4 ; NO, BAD SEARCH SE.RET: RETURN ; RETURN .PAGE .SBTTL DELETE ROUTINE ; ; THIS ROUTINE IS USED TO DELETE A SPECIFIED ; DISPLAY FILE, AND COMPRESS THE REMAINING DISPLAY ; FILES IN ORDER TO RECLAIM THE CORE USED ; DE$LOW: .WORD 0 ; START ADDRESS OF DISPLAY DE$HGH: .WORD 0 ; END ADDRESS OF DISPLAY DE$SAV: .WORD 0 ; NUMBER OF BYTES RECLAIMED ; $DELET: SAVREG ; SAVE THE REGISTERS TST R5 ; IS THIS A GOOD DISPLAY ? BLT DE.BDN ; NO, SO ERROR CMP R5,#77 ; IS THIS A GOOD DISPLAY ? BLE DE.GDN ; YES, SO CONTINUE DE.BDN: MOV #ER$BDN,R4 ; R4 IS ERROR POINTER CALL $ERROR ; WARNING "% BAD DISPLAY NUMBER" MOVB #3,TR$STA ; LET 10 KNOW THE ERROR JMP DE.RET ; AND RETURN ; DE.GDN: CLR SE$MOD ; INDICATE DIRECT SEARCH MODE CALL $SERCH ; LOOK FOR DISPLAY BIT #EX.BIT,4(R4) ; DOES THIS DISPLAY EXIST BNE DE.DE ; YES, SO CONTINUE MOV #ER$DDE,R4 ; R4 IS ERROR POINTER CALL $ERROR ; WARNING "% DISPLAY DOES NOT EXIST" INCB TR$STA ; LET 10 KNOW THE ERROR JMP DE.RET ; AND RETURN ; DE.DE: BIT #WP.BIT,4(R4) ; IS THE DISPLAY WRITE-PROTECTED BEQ DE.WE ; NO, SO CONTINUE MOV #ER$WP,R4 ; R4 IS ERROR POINTER CALL $ERROR ; WARNING "% CANNOT DELETE THIS DISPLAY" MOVB #8.,TR$STA ; LET 10 KNOW THE ERROR JMP DE.RET ; AND RETURN ; DE.WE: MOV @R4,R1 ; GET LOW ADDRESS MOV R1,DE$LOW ; AND SAVE MOV 2(R4),R2 ; GET HIGH ADDRESS ADD #2,R2 ; POINT ONE WORD PAST MOV R2,DE$HGH ; AND SAVE SUB R1,R2 ; GET BYTE COUNT MOV R2,DE$SAV ; AND SAVE BIC #ND.BIT,4(R4) ; IGNORE THE DISABLE BIT CALL $DSABL ; DISABLE THE DISPLAY CLR (R4)+ ; CLR (R4)+ ; REMOVE DISPLAY TABLE ENTRY CLR (R4)+ ; .PAGE ; LOOP THROUGH THE DISPLAY TABLE. IF ANY ADDRESS WORDS ; WERE POINTING PAST THE DELETED DISPLAY, THEY SHOULD ; BE UPDATED TO THE NEW ADDRESS (CURRENT - DE$SAV) ; IN ORDER TO MAKE THESE TABLE MODIFICATIONS THE DISPLAY ; WILL HAVE TO BE STOPPED ; MOV #$$DFT,R4 ; R4 POINTS TO DISPLAY TABLE MOV #77,R0 ; R0 IS NUMBER OF DISPLAYS CALL $DSTOP ; STOP THE DISPLAY DE.TBL: MOV 2(R4),R3 ; SAVE LAST ADDRESS IN R3 BIT #EX.BIT,4(R4) ; DOES THE DISPLAY EXIST BNE DE.0 ; YES, CONTINUE CHECKING ADD #4,R4 ; NO, POINT TO NEXT ENTRY BR DE.3 ; AND CONTINUE THE LOOP DE.0: CMP (R4)+,DE$HGH ; DOES THIS NEED TO BE CHANGED ? BLT DE.1 ; NO, SON CONTINUE SUB DE$SAV,-2(R4) ; YES, UPDATE THE ADDRESS DE.1: CMP (R4)+,DE$HGH ; DOES THIS NEED A CHANGE ? BLT DE.2 ; NO, SO CONTINUE SUB DE$SAV,-2(R4) ; YES, UPDATE THE ADDRESS DE.2: CMP @R3,DE$HGH ; DOES IT NEED TO BE CHANGED ? BLT DE.3 ; NO, SO CONTINUE SUB DE$SAV,@R3 ; UPDATE THE ADDRESS DE.3: TST (R4)+ ; POINT TO NEXT TABLE ENTRY SOB R0,DE.TBL ; LOOP FOR ALL DISPLAYS ; ; NOW CORE NEEDS TO BE COMPACTED. THIS IS DONE BY SHIFTING ; EACH WORD ABOVE DE$HGH TO THE CORRESPONDING LOCATION ; ABOVE DE$LOW. WHEN SHIFTING DISPLAYS IN THIS MANNER ; IT WILL BE NECESSARY TO MODIFY ANY DJMP'S THAT ; ORIGINALLY POINTED PAST DE$HGH. ; MOV DE$LOW,R0 ; GET DESTINATION ADDRESS MOV DE$HGH,R1 ; GET SOURCE ADDRESS ; DE.MOV: CMP R1,#STACK ; ARE WE THROUGH YET ? BGE DE.FIN ; YES, GO FINISH UP MOV (R1)+,(R0)+ ; MOVE THE WORD BR DE.MOV ; AND CONTINUE ; ; RESTART THE DISPLAY, AND FIXUP THE STATUS DISPLAY ; DE.FIN: MOV #FIRST.,@#DPC ; *** RESTART DISPLAY *** SUB DE$SAV,DF$TOP ; RESET MEMORY POINTER MOV #STACK,R1 ; GET UPPER MEMORY BOUND SUB DF$TOP,R1 ; SUBTRACT LOWER BOUND ASR R1 ; FORM WORD COUNT FORMAT R1,ST.FRE,5 ; AND FORMAT INTO STATUS DISPLAY DEC DU$CNT ; THERE IS ONE LESS DISPLAY DEC DS$CNT ; AND ONE LESS DISABLED FORMAT DU$CNT,ST.USE,2 ; FORMAT INTO STATUS DISPLAY FORMAT DS$CNT,ST.DIS,2 ; " " " " " " DE.RET: RESREG ; RESTORE THE REGISTERS RETURN ; AND RETURN .PAGE .SBTTL RESET ROUTINE ; ; THIS ROUTINE IS USED TO RESET GIDUS BY PERFORMING ; THE FOLLOWING TASKS: ; ; [1] ALL USER DISPLAY FILES ARE DELETED ; [2] A NEW SCROLLING AREA IS LAYED OUT ; [3] THE POINTERS ARE RESET ; [4] THE APPROPRIATE DISPLAYS ARE ENABLED AND DISABLED ; $RESET: SAVREG ; SAVE THE REGISTERS MOV #DF$USR + 4,R1 ; R1 POINTS TO DISPLAY TABLE MOV #54.,R2 ; R2 IS NUMBER OF USER DISPLAYS MOV #11,R5 ; FIRST USER DISPLAY NUMBER RE.1: BIT #EX.BIT,@R1 ; DOES THE DISPLAY EXIST ? BEQ RE.2 ; NO, SO IGNORE IT BIC #WP.BIT,@R1 ; YES, SO CLEAR W.P. BIT CALL $DELET ; AND DELETE THE DISPLAY FILE RE.2: ADD #6,R1 ; POINT TO NEXT DISPLAY INC R5 ; GET DISPLAY NUMBER SOB R2,RE.1 ; AND LOOP FOR ALL USER DISPLAYS ; ; LAYOUT A NEW SCROLLING AREA ; DISABL 1 ; DISABLE CDF. FOR TIME BEING CALL $DSTOP ; STOP THE DISPLAY CALL $CDINI ; LAYOUT THE SCROLLING AREA MOV CD$END,DF$TOP ; RESET LOWER CORE BOUND MOV #FIRST.,@#DPC ; AND RESTART THE DISPLAY ; ; RESET THE POINTERS AND DISABLE THE LIGHT PEN ; MOV #760,MP.X ; RESET THE MAIN POINTER MOV #1320,MP.Y FORMAT MP.X,ST.MPX,4 ; FORMAT INTO STATUS DISPLAY FORMAT MP.Y,ST.MPY,4 MOV #1303,AP.X ; RESET THE AUX. POINTER MOV #1320,AP.Y FORMAT AP.X,ST.APX,4 ; FORMAT INTO STATUS DISPLAY FORMAT AP.Y,ST.APY,4 MOV #1,LP$FLG ; DISABLE THE LIGHT PEN CLR LP$HIT MOV #"LD,ST.LP ; INDICATE IN STATUS DISPLAY ; ; ENABLE AND DISABLE THE APPROPRIATE GIDUS DISPLAYS ; CMP CD$NEW,#27. ; IS THERE ROOM FOR STATUS BGT RE.3 ; NO, SO DISABLE IT ENABLE 2 ; YES, SO ENABLE ENABLE 4 ; AND ENABLE THE POINTERS ENABLE 5 BR RE.4 ; AND CONTINUE RE.3: DISABL 2 ; DISABLE STATUS DISABL 4 ; AND THE POINTERS DISABL 5 RE.4: ENABLE 1 ; ENABLE CDF. DISABL 6 ; DISABLE OPTION MESSAGE DISABL 10 ; AND OPTION POINTER ; ; FIXUP THE STATUS DISPLAY AND TURN OFF ANY ERROR MESSAGES ; MOV #STACK,R1 ; GET UPPER MEMORY BOUND SUB DF$TOP,R1 ; SUBTRACT LOWER MEMORY BOUND ASR R1 ; FORM WORD COUNT FORMAT R1,ST.FRE,5 ; AND FORMAT INTO STATUS DISPLAY CLR R1 ; LAST DISPLAY ADDED = 0 FORMAT R1,ST.LST,2 ; INDICATE IN STATUS DISPLAY MOV #ME.END,ME.ON ; TURN OFF ERROR MESSAGES RESREG ; RESTORE THE REGISTERS RETURN ; AND RETURN .PAGE .SBTTL ERROR DISPLAY ROUTINE ; ; UPON ENTRY R4 POINTS TO ERROR MESSAGE ; WHICH IS AN ASCIZ STRING ; .NLIST BEX ER$BDN: .ASCIZ /% BAD DISPLAY FILE NUMBER/ ER$FNF: .ASCIZ /? DISPLAY FILE NOT FOUND (DISPLAY TABLE CORRUPT)/ ER$ND: .ASCIZ /% CANNOT DISABLE A NO-DISABLE DISPLAY FILE/ ER$WP: .ASCIZ /% CANNOT DELETE A WRITE PROTECTED DISPLAY FILE/ ER$ADD: .ASCIZ /? ODD ADDRESS REFERENCE ?/ ER$DDE: .ASCIZ /% DISPLAY DOES NOT EXIST/ .EVEN .LIST BEX ; $ERROR: SAVREG ; SAVE THE REGISTERS MOV #ME.TXT,R0 ; R0 POINTS AT TEXT LINE MOV #" ,R1 ; R1 USED TO BLANK OUT LINE MOV #36.,R2 ; NUMBER OF WORDS TO ZAP ER.1: MOV R1,(R0)+ ; BLANK IT OUT SOB R2,ER.1 MOV #ME.TXT,R0 ; R0 POINTS AT TEXT LINE ER.2: MOVB (R4)+,(R0)+ ; MOVE IN CHARACTERS BNE ER.2 ; UNTIL NULL MOV #ME.ON,R0 ; NOW TURN ON MOV #ME.ON+2,@R0 ; THE DISPLAY RESREG ; RESTORE THE REGISTERS RETURN ; AND RETURN .PAGE .SBTTL UTILITY ROUTINES ; $SAVRG: PUSH R1 ; PUSH R2 ; PUSH R3 ; SAVE ON THE STACK PUSH R4 ; PUSH R5 ; MOV R0,PC ; AND RETURN ; ; ; $RESRG: TST (SP)+ ; THROW AWAY R0 POP R5 ; POP R4 ; POP R3 ; POP ALL REGISTERS POP R2 ; OFF THE STACK POP R1 ; RTS R0 ; RESTORE R0 AND RETURN .PAGE .SBTTL DISPLAY STOP ROUTINE ; ; THIS ROUTINE POLITELY STOPS THE DISPLAY ; $DSTOP: CMP DPC,#LAS.1 BEQ DS.R9 MOV #1,ST$FNC ; STOP FUNCTION PUSH @#PSW ; SAVE PSW CLR @#PSW ; ALLOW THE STOP DS.WA: TST ST$FNC ; HAVE WE STOPPED YET ? BNE DS.WA ; NO, KEEP WAITING POP @#PSW ; RESTORE THE OLD PSW DS.R9: RETURN ; RETURN .PAGE ; $FRMAT - CONVERT R0 TO OCTAL ; ; R1 POINTS TO OUTPUT AREA ; R2 CONTAINS NUMBER OF DIGITS TO CONVERT ; $FRMAT: ADD R2,R1 ; SET UP POINTER FR.NXT: MOV R5,R3 ; USE R3 FOR TEMP. STORAGE BIC #177770,R3 ; CLEAR ALL EXCEPT BOTTOM DIGIT ADD #60,R3 ; CONVERT TO ASCII MOVB R3,-(R1) ; MOVE TO OUTPUT AREA DEC R2 ; LOOP FOR BLE FR.RET ; ALL DIGITS CLC ; CLEAR CARRY BIT FOR ROTATE BIC #7,R5 ; ZAP BOTTOM DIGIT ROR R5 ; ROR R5 ; GET NEXT DIGIT ROR R5 ; BR FR.NXT ; AND CONVERT IT FR.RET: RETURN ; RETURN .PAGE .SBTTL GIDUS 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. .PAGE ; GIDUS STATUS DISPLAY FILE ; STATS.: POINT ; SGM - POINT MODE .WORD 0,1350 ; FIRST LINE OF SCREEN CHAR ! BLKOFF ; SGM - CHARACTER MODE ST.ATE: .ASCII /TI / <0> ; GIDUS STATE ST.DL: .ASCII /CH FR=/ ; DL-11 STATE ST.FRE: .ASCII /00000 DU=/ ; FREE CORE ST.USE: .ASCII /12 DD=/ ; DISPLAYS IN USE ST.DIS: .ASCII /03 LA=/ ; DISABLED DISPLAYS ST.LST: .ASCII /00 MP=(/ ; LAST DISPLAY ADDED ST.MPX: .ASCII /0760,/ ; MAIN POINTER X ST.MPY: .ASCII /1320) AP=(/ ; MAIN POINTER Y ST.APX: .ASCII /1303,/ ; AUX. POINTER X ST.APY: .ASCII /1320) / ; AUX. POINTER Y ST.LP: .ASCII /LD / ; L.P. STATUS ST.TRC: .ASCII /TRACE / ; TRACE VARIABLE .BYTE 0 ; .EVEN ST.END: DJMP,MESAG. ; ONTO NEXT DISPLAY ST.OLD: .WORD 0 ; OLD STATUS .PAGE ; MESSAGE DISPLAY FILE ; MESAG.: POINT ; SGM - POINT MODE .WORD 0,1321 ; SECOND LINE OF DISPLAY DJMP ; DISABLE AS A SUB-FILE ME.ON: ME.END CHAR ! BLKON ! INT3 ; SGM - CHARACTER MODE .NLIST BEX ME.TXT: .ASCII /GIDUS MESSAGE DISPLAY FILE/ .BYTE 0 .ASCII / / .LIST BEX ME.END: DJMP,MP. ; ONTO MAIN POINTER .PAGE ; MAIN POINTER DISPLAY FILE ; MP.: POINT!LPOFF!INT2!BLKOFF!LINE0 ; SGM - POINT MODE MP.X: .WORD 760 ; X POSITION MP.Y: .WORD 1320 ; Y POSITION SHORTV ; SGM - SHORT VECTOR SV 30,0 ; SV -60,0,1 ; SV 30,30 ; THE POINTER SV 0,-60,1 ; SV 5,0 CHAR ! INT2 ! LPOFF ; SGM - CHARACTER MODE .ASCII /MP/ ; FOR MAIN POINTER MP.END: DJMP,AP. ; ONTO AUX. POINTER DISPLAY FILE ; ; ; ; ; ; ; AUXILLARY POINTER DISPLAY FILE ; AP.: POINT!LPOFF!INT2!BLKOFF!LINE0 ; SGM - POINT MODE AP.X: .WORD 1303 ; X POSITION AP.Y: .WORD 1320 ; Y POSITION SHORTV ; SGM - RELATIVE VECTOR SV 30,0 ; SV -60,0,1 ; SV 30,30 ; THE POINTER SV 0,-60,1 ; SV 5,0 ; CHAR ! INT2 ! LPOFF ; SGM - CHARACTER MODE .ASCII /AP/ ; FOR AUX. POINTER AP.END: DJMP,LAST. ; ONTO NEXT DISPLAY FILE .PAGE ; OPTION LIST DISPLAY FILE ; OMSG.: POINT ! LPOFF ! BLKON ! INT3 ; OPTION MESSAGE FILE .WORD 810., 655. ; POSITION STATSA ! ITAL0 ; NORMAL FONT CHAR ; CHARACTER MODE .ASCII /SELECT OPTION/ .BYTE 0 OM.END: DJMP,0 ; A DISABLED DISPLAY FILE .PAGE ; GIDUS COMMAND DISPLAY FILE ; GCMND.: POINT ! LPOFF ! BLKOFF ! INT2 ; SGM - POINT MODE .WORD 0 ; X POSITION .WORD 1246 ; Y POSITION CHAR ; SGM - CHARACTER MODE STATSA ! ITAL1 ; ITALICS ON .ASCII /GIDUS>> / STATSA ! ITAL0 ; ITALICS OFF GC.LNE: .ASCII / / GC.ANS: .ASCII / / ; COMMAND ANSWER DJMP ; A DISABLED SUB-DISPLAY FILE GC.HLP: GC.END POINT ; SGM - POINT MODE .WORD 0 ; X POSITION .WORD 1170 ; Y POSITION CHAR ; SGM - CHARACTER MODE .NLIST BEX .ASCII /COMMANDS ARE:/ .ASCII /DISABLE N/ .ASCII /ENABLE N/ .ASCII /(LD) DISABLE LIGHT PEN/ .ASCII /(LE) ENABLE LIGHT PEN/ .ASCII /SPEED N/ .ASCII /DELETE N/ .ASCII /EXAMINE ADDR/ .ASCII /MODIFY VALUE/ .ASCII /TRACE ADDR/ .ASCII /HELP/ .ASCII /RESET NLINES/ .ASCII /OFF/ .EVEN .LIST BEX GC.END: DJMP,0 ; A DISABLED DISPLAY FILE ; ; ; OPTION POINTER DISPLAY FILE ; OPTR.: POINT ! LPOFF ! BLKON ! INT3 OP$X: .WORD 740. ; X POSITION OP$Y: .WORD 0 ; Y POSITION STATSA ! ITAL0 ; NORMAL FONT CHAR ; CHARACTER MODE .ASCII /==>/ .BYTE 0 OP.END: DJMP,0 ; A DISABLED DISPLAY FILE .PAGE ; LAST DISPLAY FILE ; LAST.: DSTOP ; STOP WITH INTERRUPT LAS.1: DJMP,FIRST. ; RE-DISPLAY ; ; ; ; ; ; DHALT.: STATSA!SINOF ; FULL STOP, NO INT. ; CDF.: POINT!INT2!BLKON CDF.X: .WORD 0, CHAR .BYTE ,0 STATSA!ITAL0 ; ; ; ; ; .END $START