.TITLE XGP SUPPORT PACKAGE %ABSADR==1 ;XGP SUPPORT PACKAGE ;PHYSICAL CHARACTERISTICS OF XGP ;EACH SCAN LINE IS: (ALL IN DECIMAL) ; 1700 BITS ; 108 PDP-11 WORDS ; 54 PDP-10 WORDS ;IN OCTAL THAT IS: ; 330 PDP-11 BYTES ;IT TAKES 7.75 MILLISECONDS TO PRINT ONE SCAN LINE IMWDSZ=108. ;NUMBER OF WORDS OF IMAGE LINE BITS IMSLSZ==*2 ;IMAGE MODE SCAN LINE SIZE (BYTES) ;INCLUDES BUFFER HEADERS AND INITIAL IMAGE MODE WORD NBITS==IMWDSZ*20 ;NUMBER OF BITS IN A SCAN LINE ; REGISTER DEFINITIONS R0=%0 ; R0 - R3 -- WORK REGS R1=R0+1 R2=R1+1 R3=R2+1 R4=R3+1 ;USUALLY CONTAINS FONT INDEX R5=R4+1 ;USUALLY CONTAINS #MQ SP=%6 ; STACK POINTER PC=%7 ; PROGRAM COUNTER .XCREF R0,R1,R2,R3,R4,R5,SP,PC ;CORE ALLOCATOR SPECS CORSIZ==140000-200 ;ROOM FOR CARPET BPT ROUTINE INUSE==1 ; MARKS CORE BLOCK IN USE NEBISH==20 ; BYTES WE'RE WILLING TO WASTE IN BLOCK MAXFNT==20 ; MAXIMUM # ALLOWABLE FONTS LAMBDA==-10.*60. ; PDP10 TIME OUT CONSTANT CF==18. ;CONFETTI SIZE IN HALF SECONDS NSLBFS==36. ;NUMBER OF SCAN LINE BUFFERS NCLKQS==12. ;MAX NUMBER OF QUEUED CUT REQUESTS ;INTERRUPT VECTORS BPTV==14 IOTV==20 POWRFV==24 ACCTCT==0 ;OFFSET OF COUNT ENTRY IN ACCT (USUALLY NOT SHOWN) ACCTWD==2 ;OFFSET OF WORD OFFSET IN SCAN LINE ACCTBT==4 ;OFFSET OF BIT OFFSET IN SCAN LINE ACCTNW==5 ;OFFSET OF NUMBER OF WORDS IN THIS CHAR ACCTPT==6 ;OFFSET OF POINTER TO FONT ENTRY ; I/O DEVICE ADDRESSES XCR=172100 ; XEROX CONTROL REGISTER XSR=172104 ; XEROX STATUS REGISTER MAR=172102 ; XGP MEMORY ADDRESS REGISTER XCUT=172106 ;REGISTER TO HACK CUTS ONLY, FCUTI=4 .EXPUNGE ASH,DIV,MUL DIV=177300 ; EAE MAGIC LOCATIONS AC=177302 MQ=177304 MUL=177306 SC=177310 SR=177311 NOR=177312 LSH=177314 ASH=177316 LKS=177546 ; LINE CLOCK STATUS PS=177776 ; PROCESSOR STATUS ; XGP STATUS BITS FOS==100000 ; (15) OVERSCAN FSYN==40000 ; (14) SYNC ERROR FOR==20000 ; (13) DMA OVERRUN FNXM==10000 ; (12) NXM FRDYC==4000 ; (11) DEV RDY CHANGED FBCB==2000 ; (10) BAD CONTROL BYTE IN CHAR MODE RDMASK==274 ; MASK FOR PRINTER STATUS BITS (EXCLUDES PAPER SPEED) FRDY==100 ; (6) DEVICE READY (INCLUDES "PAPER UP TO SPEED") FACT==1 ; (0) ACTIVE ; XGP CONTROL BITS FERR==100000 ; (15) ERROR FMOT==2000 ; (10) MOTION FDONE==200 ; (7) DONE FDIE==100 ; (6) DONE INTERUPT ENABLE FCUTI==4 ;(2) CUT PAPER NOW! FCUT==2 ; (1) CUT PAPER FGO==1 ; (0) GO LNKV=124 ; POINTS TO CHANNEL HEADER AREA ;MACRO TO ALIGN . ON R0 PDP-10 WORD .MACRO TENWRD .XLIST ZZZ==.&3 .IF NE ZZZ .=.+4-ZZZ .ENDC .LIST .ENDM .MACRO PUSH R0 .XLIST MOV R0,-(SP) .LIST .ENDM .MACRO POP R0 .XLIST MOV (SP)+,R0 .LIST .ENDM .MACRO REPT1 CT,ARG .XLIST .REPT CT ARG .ENDR .LIST .ENDM .MACRO REPT2 CT,ARG1,ARG2 .XLIST .REPT CT ARG1 ARG2 .ENDR .LIST .ENDM .MACRO REPT3 CT,ARG1,ARG2,ARG3 .XLIST .REPT CT ARG1 ARG2 ARG3 .ENDR .LIST .ENDM .=4 REPT2 77,.+2,IOT .=BPTV 0 0 .=124 0 0 ; MAIN LOOP FOR STARTUP .=400 ; START ADDRESS BR START ;COMMUNICATION AREA WITH THE PDP10 ABORTF: 0 ;FLAG SET WHEN THE 11 IS ABORTING, RESET BY PDP10 WHEN IT NOTICES XGPE: 0 ;ERROR FLAGS FROM THE XGP. POSSIBLE CAUSES OF ABORTS IF NOT READY ERRADR: 0 ;ADDRESS OF CALLS TO ERROR, WHICH CAUSES AN ABORT TENWRD XGPIMP: .=.+20 ;RING BUFFER POINTERS FOR IMAGE OUTPUT FROM SYSTEM ;POINTER TO NEXT BUFFER IN RING ;USE FLAG 0 => EMPTY ;POINTER TO 4000 BYTE BUFFER ;UNUSED TENWRD KSTLOD: .=.+4 ;-1 WHILE LOADING KST, 0=>KST LOADED, POSITIVE=># CHARACTERS NOT LOADED FULFLG: .=.+ ;NUMBER OF CHARS IN EACH FONT NOT LOADED NORUG: HALT START: RESET ; CLEAR THE UNIBUS CLR PS ; SET PRIORITY LEVEL 0 MOV #STK,SP ; SETUP THE STACK CLR R0 MOV #340,R1 ; SET LEVEL 7 CLR (R0)+ ; END OF LIST PTR CLR (R0)+ MOV #ERR1,(R0)+ ; SETUP ERROR TRAP VECTOR MOV R1,(R0)+ MOV #ERR2,(R0)+ ; SETUP RESERVED INSTR. TRAP MOV R1,(R0)+ MOV #POWRF,POWRFV ; SETUP POWER FAILURE TRAP MOV #IOTBRK,IOTV ;SET UP BAD TRAP CATCHER MOV R1,22 TST BPTV ;IS CARPET THERE BNE START1 MOV #NORUG,BPTV MOV R1,BPTV+2 START1: MOV R1,@#62 MOV #XGPDON,@#370 ; SETUP XGP TRAP MOV R1,@#372 MOV #<6_5>,R1 ; SET REST ON LEVEL 6 MOV #CLKBRK,@#100 ; LINE CLOCK MOV R1,@#102 CLR TICKS ; START CLOCK MOV #100,LKS MOV #1,TICKS1 JSR PC,FRECLR ; INITIALIZE FREE STORAGE ;RESTART FOR ABORTS, ERRORS ST4: CLR XGPIMP ;CLEAR POINTER TO MAKE SYSTEM UNHAPPY ABOUT ;PUTTING STUFF INTO BUFFERS NOW JSR PC,TENIOR ; RESET 10-11 COMMUNICATION CHANNELS BIS #100000,CIHDR ; OPEN COMMAND INPUT ; PDP10 - PDP11 COMMUNICATION PDP10: INC IDLE JSR PC,LNKI ; GET COMMAND CHARACTER ASL R0 ; MAKE IT R0 WORD PTR. CMP R0,#DSPL ; IS DISPATCH LEGAL? BHIS PDP10 ; NO - IGNORE IT. CLR IDLE JMP @DSP(R0) ; DISPATCH DSP: LKSET ; (1) SPECIFY CHARACTER SET MIXED ; (5) MIXED (TEXT & VECTORS) MODE IMAGE ; (6) IMAGE MODE TEST DSPL==.-DSP ; DISPATCH TABLE LENGTH TEST: JSR PC,FRECLR JSR PC,XGPRDY ;TEST XGP HAPPINESS JSR PC,SLBSU ;SETUP XGP BUFFERS CLR R5 TEST3: JSR PC,SLB MOV R0,SLBO ADD #4,R0 MOV #1000,(R0)+ CLR R2 DEC R5 BLE TEST1 TEST2: MOV BIT100(R2),(R0)+ TST (R2)+ CMP R2,#IMWDSZ*2 BLT TEST2 MOV #1,@SLBO BR TEST3 TEST1: MOV #-1,(R0)+ TST (R2)+ CMP R2,#IMWDSZ*2 BLT TEST1 MOV #100.,R5 MOV #1,@SLBO BR TEST3 BIT100: .REPT 17. 1 ;WORD WITH BIT 0 0 0 0 0 0 0 20 0 0 0 0 0 0 0 400 0 0 0 0 0 0 0 10000 0 0 0 0 0 0 0 0 .ENDR IMAGE: MOV #1,AUTCUT JSR PC,XGPRDY ;XGP HAPPY? JSR PC,FRECLR ;CLEAR OUT ALL FREE STORAGE AND FONT INFO MOV #SLB1,XGPIMP+4 ;POINTER TO FIRST BUFFER MOV #SLB1+10000,XGPIMP+4+8 ;POINTER TO SECOND BUFFER CLR XGPIMP+2 ;CLEAR USE FLAG FOR FIRST BUFFER CLR XGPIMP+2+8 ;CLEAR USE FLAG FOR SECOND BUFFER MOV #XGPIMP,XGPIMP+8 ;SETUP BACK POINTER IN BUFFER CHAIN MOV #XGPIMP+8,XGPIMP ;SETUP POINTER TO SECOND BUFFER (ALLOW SYSTEM TO START) MOV #XGPIMP,IMBP ;SETUP INITIAL BUFFER POINTER MOV #XGPIMP+8,IMOBP ;POINTER TO BUFFER IN USE MOV #SLB1+20000,R0 ;FIRST FREE LOCATION FOR SCAN LINE BUFFERS MOV R0,SBNP ;SAVE AS POINTER TO FIRST BUFFER MOV R0,SLBINI ;FIRST PI LEVEL BUFFER IM2: CLR (R0)+ ;CLEAR USE FLAG MOV R1,R2 ;SAVE POINTER 2 BACK MOV R0,R1 ;SAVE BACK POINTER ADD #IMSLSZ-2,R0 ;INCREMENT TO NEXT BUFFER LOCATION CMP R0,#CORSIZ ;OVERLOWED CORE? BHIS IM1 ;YES, DONE MOV R0,(R1) ;SAVE POINTER IN OLD BUFFER BR IM2 ;BACK FOR MORE BUFFERS ;REGISTER USE: R2 COUNT OF WORDS IN THIS SCAN LINE ; R3 POINTER INTO THE SCAN LINE ; R4 POINTER INTO THE 10 BUFFER ; R5 COUNT OF FREE WORDS IN THE 10 BUFFER IM1: MOV #SLB1+20000,(R2) ;BACK POINTER AT LAST BUFFER LOCATION CLR XGPST ;NOT STARTED CLR XGPFIN ;NOT FINISHED CLR R5 ;ZERO INITIAL BUFFER WORD COUNT IM3: JSR PC,SLB ;GET A SCAN LINE BUFFER MOV R0,IMSLP ;SAVE POINTER TO SCAN LINE MOV R0,R3 ;SCAN LINE POINTER JSR PC,GETWD ;GET COUNT OF WORDS IN THIS LINE DEC R0 ;FLUSH THIS ONE BLE IMDONE ;BETTER BE AT LEAST 2 CMP R0,#IMWDSZ ;REST HAD BETTER FIT INTO A SCAN LINE BUFFER BGT IMDONE ;OR ELSE FLUSH MOV R0,R2 ;COUNT OF WORDS TO GET FOR THIS LINE DEC R2 ;ONE LESS 10 WORD JSR PC,GETWD ;LINE NUMBER/CUT/EOF TST R0 ;ZERO NESS BEQ IMDONE ;HE LOSES CMP #100000,R0 ;EOF? BEQ IMDONE ;YUP MOV R0,IMLPOS ;LINE POSITION AND CUT FLAG BIC #100000,R0 ;CLEAR OUT CUT FLAG CMP R0,#200.*36. ;LESS THAN A YARD OF PAPER! BHIS IMDONE ;HE LOSES! ADD #4,R3 ;SKIP OVER LINE # AND BUFFER POINTER IN SCAN LINE IM4: DEC R5 ;ONE LESS WORD IN THE 10 BUFFER BLT IM5 ;REFILL NEEDED FOR 10 BUFFER MOV (R4)+,(R3)+ ;TRANSFER THE WORD INTO SCAN LINE DEC R2 ;ONE LESS WORD IN THIS SCAN LINE BGT IM4 ;BACK FOR MORE MOV IMLPOS,@IMSLP ;CLOBBER SCAN LINE POSITION IN BR IM3 ;NEW SCAN LINE IM5: JSR PC,GWRF1 ;REFILL BUFFERS, SETUP R5 AND R4 BR IM4 ;TRY AGAIN GETWD: DEC R5 BLT GWRF ;REFILL MOV (R4)+,R0 ;GET WORD FROM 10 BUFFER RTS PC GWRF: JSR PC,GWRF1 ;REFILL BUFFER BR GETWD ;BACK TO TRY AGAIN GWRF1: MOV IMOBP,R0 ;PICK UP OLD POINTER CLR 2(R0) ;FREE UP THE BUFFER MOV IMBP,R0 ;PICK UP 10 BUFFER HEADER POINTER MOV #-60.*60.,TIMER GWRF3: TST 2(R0) ;10 FILLED BUFFER YET? BNE GWRF2 ;YUP READY TST TIMER ;TIMED OUT YET? BLT GWRF3 ;NOT YET JMP ABORT ;YES, HE LOSES GWRF2: MOV #4000,R5 ;COUNT SETUP AS 1K 10 WORDS MOV 4(R0),R4 ;PICKUP POINTER TO BUFFER BEGINNING MOV R0,IMOBP ;OLD BUFFER MOV (R0),IMBP ;RING THE BUFFER POINTER RTS PC IMDONE: CLR XGPIMP ;RESET BUFFER POINTER, DISABLE PDP-10 CLOBBERS MOV #100000,(R3) ;SEND EOF TO INTERRUPT LEVEL JSR PC,XGPWT ;WAIT FOR XGP TO BE DONE JSR PC,FRECLR JMP PDP10 LKSET: JSR PC,CMDI ;CONTROL CODE PUSH R0 ;SAVE FOR LATER JSR PC,LNKI ;FONT # CMP R0,#MAXFNT ;LEGAL FONT #? BLO LK1 ;YUP CLR R0 ;DEFINE FONT 0 INSTEAD LK1: MOV R0,R4 ;R4 HAS FONT INDEX ASL R4 ;CONVERT TO WORD QUANTITY JSR PC,CLRKST ;CLEAR OUT OLD CHAR SET IN THIS FONT CLR FULFLG(R4) ;CLEAR COUNT OF CHARS IGNORED DUE TO NO MEMORY MOV #-1,KSTLOD ;SET FLAG FOR PDP-10 POP R3 ;CONTROL CODE BEQ LKX ;THATS ALL WE WANT TO DO JSR PC,WRDI ;HEIGHT MOV R0,HEIGHT(R4) JSR PC,WRDI ;BASE MOV R0,BASE(R4) MOV #400,R0 ;GET FONT DISPATCH TABLE JSR PC,GETBLK MOV R0,FNTBLS(R4) BEQ LK10 ;BRANCH IF NO CORE MOV #200,R1 LK1A: CLR (R0)+ ;CLEAR OUT THE TABLE DEC R1 BGT LK1A LK10: JSR PC,LNKI ;CHAR CODE TSTB R0 BLT LKX ;SIGN OF CHAR SET=> END OF CHARS FOR THIS FONT ASL R0 ;WORD POINTER MOV FNTBLS(R4),CHRIDX ;OFFSET INTO FONT TABLE BEQ LK10A ;IF ZERO THEN DISPATCH TABLE DOES NOT EXIST ADD R0,CHRIDX LK10A: JSR PC,LNKI ; "BEFORE" CHARACTER ADJUST NEG R0 ;SUBTRACTS FROM COLUMN POSITION MOV R0,LBADJ JSR PC,WRDI ;"AFTER" CHARACTER ADJUST MOV R0,LAADJ JSR PC,WRDI ;BITS PER ROW BEQ NULCHR ;ZERO BITS WIDE => NULL ADD #17,R0 ;MAKE IT ROUND UP MOV R0,MQ MOV #20,DIV ;FIND OUT NUMBER OF WORDS MOV MQ,LWDSPR ;STASH IT AWAY CLR SKIPS ;NUMBER TOP ROWS ALL ZERO TO BE SKIPPED CLR BROWS ;HEIGHT(FONT)-SKIPS CLR BOTZR ;CLEAR NUMBER OF BOTTOM ROWS BLANK MOV HEIGHT(R4),NROWS CLR LKOVRF ;BUFFER HAS OVERFLOWED FLAG LK5: MOV #SLB1,R5 ;POINTER TO TEMPORARY TABLE AREA LK2: DEC NROWS ;ROWS LEFT IN THIS CHAR BLT LK8 ;NONE LEFT CLR ROWNZ ;COUNT OF NON ZERO WORDS IN THIS ROW MOV LWDSPR,R2 ;LOOP COUNT FOR FETCHING WORDS LK3: DEC R2 BLT LK4 ;FINISHED WITH THIS ROW CMP #BITSNK-4,R5 BLOS LKBFUL ;BUFFER FULL? JSR PC,CMDI ;GET BYTE OF FONT DESCR. MOVB R0,(R5)+ ;STASH IN TEMP LOC JSR PC,CMDI ;NEXT BYTE MOVB R0,(R5)+ TST -2(R5) ;IS THIS ENTRY ZERO? BEQ LK3 ;YES, MAYBE RESET TEMP POINTER, INC ROWNZ ;COUNT OF NON ZERO ROWS BR LK3 ;LOOP FOR MORE LKBFUL: JSR PC,WRDI ;BUFFER IS FULL, JUST GOBBLE TWO WORDS INC LKOVRF ;FLAG A BUFFER OVERFLOW BR LK3 LKX: MOV FULFLG(R4),KSTLOD ;SET FLAG FOR PDP-10 JMP PDP10 LK4: TST BROWS ;GOT ANY NON ZERO ROWS YET? BNE LK13 ;YUP, CANT HACK TST ROWNZ ;THIS ROW ZERO? BNE LK6 ;NOPE, CANT HACK INC SKIPS ;SKIP OVER THIS ROW (DONT STORE IT) BR LK5 ;BACKUP R5 TO BEG, START OVER LK6: INC BROWS ;COUNT OF NON ZERO ROWS SO FAR BR LK2 LK13: TST ROWNZ ;THIS ROW ZERO? BNE LK11 ;NO INC BOTZR ;YES, MAYBE ON THE BOTTOM BR LK2 ;BACK FOR ANOTHER ROW LK11: CLR BOTZR ;NON ZERO ROW, ZERO COUNT OF BOTTOM ZERO ROWS BR LK2 ;BACK FOR ANOTHER ROW NULCHR: MOV CHRIDX,R1 BEQ FONTFL ;BRANCH IF DISPATCH TABLE DOES NOT EXIST MOV #4,R0 ;BLOCK FOR ADJUSTS ONLY JSR PC,GETBLK ;GET ENUF FOR THIS CHAR BEQ FONTFL ;BRANCH IF NONE MOV R0,(R1) MOVB LBADJ,(R0)+ ;SAVE BEFORE CHAR ADJUST CLRB (R0)+ ;CLEAR WORDS/ROW FOR THIS CHAR MOV LAADJ,(R0)+ ;SAVE AFTER CHARACTER ADJUST BR LK10 FONTFL: INC FULFLG(R4) ;COUNT OF OVERFLOWED CHARACTERS BR LK10 ;NEXT CHARACTER LK8: TST BROWS ;ANY BLACKNESS AT ALL? BEQ NULCHR ;NOPE, NOT WORTH STORING THIS CHAR TST LKOVRF ;DID BUFFER OVERFLOW? BNE FONTFL MOV CHRIDX,R1 ;RESTORE CHAR INDEX BEQ FONTFL ;BRACH IF FONT DISPATCH DOES NOT EXIST MOV LWDSPR,MQ ;WORDS/ROW MOV BOTZR,MUL ;TIMES NUMBER OF ZERO BOTTOM ROWS SUB MQ,R5 ;FLUSH ROW SUB MQ,R5 ;TWICE BECAUSE ITS WORDS! SUB #SLB1,R5 ;NUMBER OF WORDS IT TOOK TO STORE FONT MOV R5,R0 ;SETUP FOR CORE ALLOC CALL ASR R5 ;CONVERT TO COUNT ADD #8,R0 ;ALLOW ROOM FOR SKIPS AND HEIGHT JSR PC,GETBLK ;CALL CORE ALLOC BEQ FONTFL ;BRANCH IF NO CORE FOUND MOV R0,(R1) ;STORE POINTER TO FONT ENTRY MOVB LBADJ,(R0)+ ;SAVE BEFORE ADJUST FOR THIS CHAR MOVB LWDSPR,(R0)+ ;SAVE WORDS/ROW FOR THIS CHAR MOV LAADJ,(R0)+ ;SAVE AFTER CHARACTER ADJUST MOV SKIPS,(R0)+ ;STASH BLANK TOP SCAN LINES SKIPPED MOV HEIGHT(R4),R2 ;HEIGHT OF FONT SUB SKIPS,R2 ;SUB SCAN LINES SKIPPED AT TOP SUB BOTZR,R2 ;SUBTRACT OFF NUMBER OF BOTTOM ZERO ROWS FROM HEIGHT NEG R2 ;SL1 WANTS HEIGHT NEGATIVE MOV R2,(R0)+ ;STASH REMAINING HEIGHT MOV #SLB1,R1 ;ORIGIN OF STORED CHAR LK9: MOV (R1)+,(R0)+ ;STASH AWAY ACTUAL BLACK BITS DEC R5 ;COUNT OF NUMBER TO STASH BGT LK9 ;NOT DONE JMP LK10 ;BACK FOR ANOTHER CHARACTER ;CLEAR CHARACTER SET CLRKST: MOV FNTBLS(R4),R3 ;GET CHAR INDEX FOR 0 CHAR THIS FONT BEQ RTSPC ;BRANCH IF FONT DISPATCH DOES NOT EXIST PUSH #200 ;SETUP LOOP COUNT CLRKS1: MOV (R3),R0 ;POINTER TO FONT DEF BEQ CLRKS2 ;NO CHAR THERE JSR PC,RETBLK ;RETURN MEMORY CLRKS2: CLR (R3)+ ;INCREMENT POINTER DEC (SP) ;COUNT RAN OUT? BGT CLRKS1 ;NO TST (SP)+ ; POP STACK MOV FNTBLS(R4),R0 CLR FNTBLS(R4) ;RETURN FONT DISPATCH TO FREE STORAGE JMP RETBLK ; 10-11 COMMUNICATION ROUTINES ; LNKI - GET R0 BYTE FROM PDP10 LNKI: JSR PC,CMDI BIC #177400,R0 RTSPC: RTS PC ;HERE FOR FULL WORD INPUT FROM PDP-10 WRDI: JSR PC,CMDI PUSH R0 JSR PC,CMDI MOVB R0,1(SP) POP R0 RTS PC ;HERE FOR EMPTY COMMAND BUFFER CMDI1: MOV CIBUF,R0 ;POINTS TO THIS BUFFER MOV #-1,(R0)+ ;MARK AS FREE MOV (R0),R0 ;NEXT BUFFER ON RING CMDI1A: MOV #LAMBDA,TIMER CMDI2: TST DBSW BNE CMDI4 TST TIMER BGT CMDI3 ;TIME OUT EXIT CMDI4: TST CIHDR ;TEST FOR ARBITRARY CLOSE BY 10 BLT .+4 BPT ;HE DID IT! MOV (R0),CICNT BLE CMDI2 ;WAIT FOR BUFFER TO FILL MOV R0,CIBUF CLR (R0) ;MARK BUFFER AS BUSY ADD #BHDRL,R0 ;FIRST AVAILABLE BYTE OF BUFFER MOV R0,CINXT ;HERE TO GET BYTE FROM COMMAND BUFFER ; RETURNS BYTE IN R0 CMDI: DEC CICNT BLT CMDI1 ;BUFFER EMPTY MOVB @CINXT,R0 INC CINXT RTS PC ;HERE WHEN TEN TIMES OUT WAITING FOR COMMAND INPUT CMDI3: TST IDLE BNE CMDI1A JMP TIMOUT ;HERE TO RESET ALL I/O CHANNELS TO 10 TENIOR: MOV #LNKV,R0 CLR (R0)+ ;POINTS TO CHANNEL HEADER AREA CLR (R0)+ ;# CHANNELS CLR (R0)+ ;POINTS TO BUFFER AREA CLR (R0)+ ;SIZE OF BUFFER AREA MOV #CIHDR,R2 ;ORIGIN OF CHANNEL HEADER AREA MOV #ACTCHN,R3 ;CHANNEL COUNT TENIO1: JSR PC,CLOS10 ;CLOSE THAT CHANNEL DEC R3 BGT TENIO1 MOV #LNKV,R0 ;SET CHANNEL HEADER POINTER MOV #CIHDR,(R0)+ MOV #ACTCHN,(R0)+ MOV #BUFORG,(R0)+ MOV #BUFFRL,(R0)+ RTS PC ;HERE TO ZAP BUFFER RING ZAPRNG: PUSH R0 ZAP1: MOV R1,(R0)+ ;THAT WITH WHICH TO ZAP MOV (R0),R0 ;NEXT ON RG CMP R0,(SP) ;CHECK FOR WRAP AROUND BNE ZAP1 POP R0 CLR (R0) ;MAKE BUFFER WE ARE POINTING AT BUSY RTS PC ;HERE TO INSURE ALL BUFFERS IN DATA RING ARE FULL FILL: MOV DIBUF,R0 MOV 2(R0),R0 ;RING PAST THE BUSY BUFFER MOV #LAMBDA*4,TIMER ;BE MORE FORGIVING HERE FILL1: TST DBSW BNE FILL4 TST TIMER BGT FILL3 FILL4: TST DIHDR BGE FILL2 ;TEN CLOSED CHANNEL TST (R0) ;THE TEN WILL GET HERE SOONER OR LADTER BLE FILL1 MOV 2(R0),R0 ;NEXT ON RING CMP R0,DIBUF BNE FILL1 FILL2: RTS PC ;END OF RING FILL3: JMP TIMOUT ;CLOSE 10 CHANNEL CLOS10: CLR (R2)+ ;CLOSE CHANNEL MOV #-1,R1 ;MARK ALL BUFFERS AS FREE MOV (R2)+,R0 ;BUFFER RING JSR PC,ZAPRNG ;SHOULD BE ENOUGH IF THE 10 IS CLEVER JSR PC,ZAPRNG ;BUT WE'RE PARANOID CLR (R2)+ ;POINTS INTO BUFFER CLR (R2)+ ;COUNT RTS PC ;DYNAMIC STORAGE ALLOCATOR ROUTINES GETBLK: PUSH R1 PUSH R2 JSR PC,EVENUP ;INSURE AN EVEN # OF BYTES TST R0 ;REASONABLE REQUEST? BNE GTB1 ;YUP JSR PC,ERROR ;LOSEY LOSEY GTB1: ADD #BHDRL,R0 ;ADD IN HEADER LENGTH MOV ROVER,R1 BNE GETBL1 MOV @AVAIL,R1 MOV R1,ROVER GETBL1: MOV (R1),R2 ;NEXT BLOCK CMP R0,-2(R1) BLOS GETBL2 ;FOUND R0 WINNER CMP R2,AVAIL BEQ GETBL3 ;END OF CHAIN MOV R2,R1 BR GETBL1 ;HERE IF WINNER FOUND GETBL2: MOV R2,ROVER SUB R0,-2(R1) ;SIZE OF THIS BLOCK NOW CMP -2(R1),#NEBISH BLO GETB21 MOV R1,R2 ;BREAK INTO TWO BLOCKS ADD -2(R1),R2 ;ORIGIN OF NEW BLOCK MOV -2(R1),-4(R2) ;SIZE INTO TOP OF OLD BLOCK GETBL4: MOV R0,R1 ;LENGTH OF NEW BLOCK BIS #INUSE,R0 ;MARKS BLOCK IN USE MOV R0,-2(R2) ;MARKER INTO BLOCK MOV R2,R0 ;RETURN POINTER TO CALLER ADD R1,R2 ;ORIGIN OF NEXT BLOCK MOV #INUSE,-4(R2) ;MARK LAST WORD OF NEW BLOCK POP R2 POP R1 TST R0 ;RETURN IN CONDITION CODES ALSO RTS PC ;HERE TO GIVE CALLER ENTIRE BLOCK GETB21: JSR PC,UNLINK ;TAKE BLOCK OUT OF FREE LIST ADD -2(R1),R0 ;SIZE OF BLOCK MOV R1,R2 ;NEW BLOCK BR GETBL4 ;HERE ON END OF FREE LIST GETBL3: TST ROVER BNE GTBL5 POP R2 POP R1 CLR R0 ;INDICATE MEMORY FULL BY 0 RETURN RTS PC GTBL5: CLR ROVER MOV @AVAIL,R1 BR GETBL1 ;TAKES BLOCK IN R1 AND PATCHES IT OUT OF FREE STORAGE LIST UNLINK: MOV (R1),R2 MOV R2,@2(R1) ;PATCH FORWARD POINTER INTO PRECEEDING BLOCK MOV 2(R1),2(R2) ;PATCH BACK POINTER INTO NEXT BLOCK CMP ROVER,R1 BNE .+6 MOV R2,ROVER ;DON'R1 LET ROVER POINT TO NON-EXISTENT BLOCK RTS PC ;HERE TO RETURN R0 BLOCK TO FREE STORAGE RETBLK: MOV R0,OLDBLK ;SAVE FOR DEBUGGING CMP R0,#FS+2 BHIS .+4 HALT ;CAN'R1 TAKE THAT ONE BACK MOV -2(R0),R1 ;SIZE BIT #INUSE,R1 BNE .+4 HALT ;CAN'R1 FREE R0 BLOCK WHICH ISN'R1 IN USE BIC #INUSE,R1 BIT #INUSE,-4(R0) ;IS BLOCK BELOW RESERVED BNE RETBL1 ;YES, CHECK LOWER BOUND SUB -4(R0),R0 ;POINTS TO ENLARGED BLOCK ADD R1,-2(R0) ;NEW SIZE MOV R0,R1 ADD -2(R0),R1 ;POINTS TO BLOCK ABOVE MOV -2(R0),-4(R1) ;PUT MARKER AT TOP OF BLOCK BIT #INUSE,-2(R1) BNE RTSPC2 ;BLOCK ABOVE RESERVED, GOOD BYE ADD -2(R1),-2(R0) ;NEW SIZE OF MOBY BIG BLOCK JSR PC,UNLINK ;TAKE THIS BLOCK OUT OF FREE LIST MOV R0,R1 ;MARK TOP OF ENLARGED BLOCK ADD -2(R0),R1 ;POINTS TO NEXT BLOCK MOV -2(R0),-4(R1) ;MARK TOP OF BLOCK WITH SIZE RTS PC ;BLOCK BELOW RESERVED, CHECK ABOVE RETBL1: MOV R1,-2(R0) ;MARK THIS BLOCK AS FREE ADD R0,R1 ;POINTS TO NEXT BLOCK MOV -2(R0),-4(R1) ;MARKER INTO TOP OF BLOCK BIT #INUSE,-2(R1) BNE LINK ;BR IF BLOCK ABOVE RESERVED, PATCH THIS ONE BACK IN JSR PC,UNLINK ;TAKE BLOCK ABOVE OUT OF FREE STORAGE ADD -2(R1),-2(R0) ;NEW SIZE MOV R0,R1 ADD -2(R0),R1 ;POINTS TO NEXT BLOCK MOV -2(R0),-4(R1) ;MARK TOP OF BLOCK LINK: ;PATCH THIS IN AT AVAIL CMP ROVER,R0 BNE .+6 CLR ROVER MOV AVAIL,R1 ;PREVIOUS BLOCK MOV (R1),R2 ;NEXT BLOCK MOV R0,(R1) ;FWD PNTR IN PREV BLK MOV R2,(R0) ;FWD PNTR IN THI BLK MOV R1,2(R0) ;BACK PNTR IN THIS BLK MOV R0,2(R2) ;BACK PNTR IN NEXT BLK RTSPC2: RTS PC EVENUP: BIT #1,R0 BEQ RTSPC2 INC R0 RTS PC ;HERE TO INITIALZE FREE STORAGE VARIABLES FRECLR: MOV #CORSIZ,MEMTOP MOV MEMTOP,R1 MOV #-1,-(R1) ;EVERYTHING ABOVE FREE STORAGE RESERVED MOV R1,MEMTOP ;SET UP FREE STORAGE MOV #FAKEBL+2,R1 MOV R1,AVAIL MOV R1,ROVER MOV #FS+2,R2 ;SET UP FAKE BLOCK CLR -2(R1) ;SIZE 0 MOV R2,(R1) ;FAKEBL FD PNTR MOV R2,2(R1) ;BACK PNTR MOV #-1,4(R1) ;LOOKS TAKEN FROM ABOVE MOV R1,(R2) ;FD PNTR IN FS MOV R1,2(R2) ;BACK PNTR IN FS MOV MEMTOP,R0 SUB #FS,R0 ;SIZE OF FREE STORAGE (LEAVE 1 WD FOR -1) MOV R0,-(R2) ;CLEAR THE KSET POINTERS INTO FREE STORAGE MOV #FNTBLS,R0 ;CLEAR FONT DISPATCH TABLE MOV #MAXFNT,R1 FRECL1: CLR (R0)+ DEC R1 BGT FRECL1 RTS PC ; ERROR HANDLING ; POWER FAIL PROCEDURE POWRF: MOV SP,@#0 MOV #POWRU,@#24 CLR XCR HALT POWRU: JMP START ; NON-XGP TRAPS ; ERROR HANDLING ERROR: MOV (SP),ERRADR CLR XCR ;STOP THE XGP BPT ;GOES TO EITHER NORUG OR CARPET JMP START IOTBRK: JSR PC,ERROR ERR1: JSR PC,ERROR ERR2: JSR PC,ERROR PARAM: MOV #PLDO,R1 ;ORIGIN OF TABLE OF WORDS TO BE CLOBBERED JSR PC,LNKI MOV R0,R2 ;WORD COUNT P2: DEC R2 ;DONE? BLT P1 JSR PC,WRDI CMP R1,#PLDF ;OVERFLOW TABLE OF WORDS TO INITIALIZE? BHIS P2 ;YES MOV R0,@(R1)+ ;STASH THE WORD AWAY BR P2 P1: MOV BOTMAR,R0 ADD TOPMAR,R0 CMP R0,LPAGE ;PAGE LENGTH BETTER BE BIGGER THAN TOPMAR+BOTMAR BHIS PARMER ;LOSE! MOV LPAGE,R0 ;PAGE LENGTH SUB BOTMAR,R0 ;BOTTOM MARGIN IN SCAN LINES MOV R0,BOTMAR ;WE WANT BOTMAR TO BE DISTANCE FROM TOP OF PAGE RTS PC ;RETURN PARMER: JMP ABORT PLDO: VSP ;VERTICAL INTER BASELINE SPACING LFTMAR ;LEFT MARGIN TOPMAR ;TOP MARGIN BOTMAR ;BOTTOM MARGIN (SCAN LINES FROM THE TOP OF THE PAGE) LPAGE ;LENGTH OF PAGE (BETWEEN CUTS) IN SCAN LINES PAGEN ;PAGE NUMBER AUTCUT ;0=> DONT CUT THE PAPER VLPFLG ;0=> NORMAL NON ZERO=> PAGES TERMINATED ONLY WITH FF PLDF:: SLBSU: MOV #SLB1,R0 ;SETUP SCAN LINE BUFFER POINTERS MOV R0,SBNP ;SETUP INITIAL SCAN LINE BUFF POINTER MOV R0,SLBINI ;FIRST PI LEVELBUFFER SLSU2: CLR (R0)+ ;CLEAR OUT USED FLAG MOV R1,R2 ;SAVE PAST 2 POINTERS MOV R0,R1 ADD #IMSLSZ-2,R0 ;SIZE OF BUFFER CMP R0,#SLBND ;EXCEEDED ALLOCATION? BHIS SLSU1 ;YUP, FINISHED MOV R0,(R1) ;CHAINED BUFFER POINTER BR SLSU2 SLSU1: MOV #SLB1,(R2) ;COMPLETE THE RING OF BUFFERS CLR XGPST ;XGP NOT STARTED CLR XGPFIN ;AND NOT FINISHED RTS PC MIXED: JSR PC,XGPRDY ;TEST XGP HAPPINESS MOV #100000,DIHDR ;OPEN DATA INPUT JSR PC,SLBSU ;SETUP SCAN LINE BUFFERS MOV #GCHARN,GCHARD ;SETUP INITIAL DISPATCH FOR CHAR GETTING LOOP CLR EOFF ;CLEAR END OF FILE FLAG CLR FONT ;START OUT WITH FONT 0 CLR PPN ;ZERO PAPER PAGE NUMBER CLR HEADRF ;NO HEADER INITIALLY JSR PC,PARAM ;GET MARGINS,VSP,ETC. JSR PC,FILL ;FILL TEXT LINE BUFFERS PAGE: CLR FFF ;CLEAR FORM FEED FLAG ON THIS LINE CLR OLLOW ;CLEAR DESCEND OF PREV LINE CLR BSLC ;CLEAR BLACK SCAN LINE COUNT JSR PC,VECTRS ;RESET VECTORS FOR NEW PAGE CLR TVPOS ;TOP OF PAGE IS SCAN LINE ZERO MOV TOPMAR,RVSP ;PRETEND PREVIOUS LINE HAD SPACING OF TOPMAR TST HEADRF ;HAVE WE GOT A HEADER LINE BEQ TLINE ;YES MOV GCHARD,HGCHAR ;SAVE OLD SOURCE OF CHARACTERS MOV #HDRS,GCHARD ;SETUP SOURCE FROM HEADER LINE MOV HCNT,HCNT1 ;SETUP COUNT OF CHARS IN HEADER LINE MOV #HBUF,HPTR ;SETUP POINTER TO HEADER CHRACTER LINES MOV FONT,HSFONT ;SAVE FONT PREVIOUS TO HEADER. CLR FONT ;RESET HEADER FONT TO FONT ZERO. TLINE: TST FFF ;SHOULD I FORM FEED AFTER THIS LAST LINE? BNE EPAGE ;YES MOV RVSP,OVSP ;SAVE OLD LINE'S VERTICAL SPACE COMMAND JSR PC,LSETUP ;MAIN LOOP FOR TEXT LINE PROCESSING TST QFF ;QUICK FORM FEED FLAG? (NO OTHER STUFF ON THE LINE) BNE EPAGE TST LFF ;QUICK LINE FEED? BNE LFQ ;YES, DO IT QUICKLY MOV SKPCNT,R0 ;DOES THIS LINE HAVE ITS OWN IDEA OF HOW MANY ;LINES TO SKIP BEFORE IT? BNE TL3 ;SKIP AROUND COMPUTATION OF # OF LINES TO SKIP MOV OVSP,R0 ;GET LAST LINE'S VSP PARAMETER SUB OLLOW,R0 ;AMOUNT PREV LINE DESCENDED SUB BASEL,R0 ;SUBTRACT UPPER PART OF THIS LINE BLE TL1 ;LOSE, DESCEND+ASCEND > VSP, HE LOSES MOV R0,SKPCNT ;COUNT OF LINES TO SKIP BETWEEN TEXT LINES TL3: ADD TVPOS,R0 ;TEST FOR OVERFLOW OF BOTTOM MARGIN TST VLPFLG ;VARIABLE LENGTH PAGE FLAG BNE TL3A CMP R0,BOTMAR BGE NPAGE ;OVERFLOW TL3A: JSR PC,VECTCK ;SETUP LINES WITH VECTORS TL2: MOV CHRRCT,R0 MOV R0,OLLOW ;SAVE DESCEND OF THIS LINE SUB BASEL,OLLOW ;FOR NEXT LINE SPACING ADD TVPOS,R0 TST VLPFLG ;VARIABLE LENGTH PAGE FLAG BNE TL2A CMP R0,BOTMAR BGE NPAGE ;THIS GUY JUST MADE A TEXT LINE RUN OFF THE ;END OF THE PAGE TL2A: CLR NPF ;CLEAR FLAG INDICATING LAST LINE CAUSED PAGE SKIP TST LFF ;QUICK LINE FEED? BNE LFQ ;YES ADD CHRRCT,BSLC ;NO, ADD CHRRCT TO BLACK LINE COUNT SLINE: DEC CHRRCT ;COUNT # SCAN LINES IN THIS TEXT LINE BLT TLINE ;GET A NEW TEXT LINE INC TVPOS ;NEXT LINE JSR PC,SLB ;MAIN S.L. LOOP, GET A S.L. BUFFER JSR PC,SLBC ;CLEAR IT OUT MOV R0,SLBO ;SETUP POINTERS TO S.L. ORIGIN JSR PC,VECT ;SETUP VECTORS ON THIS LINE MOV #MQ,R5 ;POINTER TO MQ IN R5 MOV #ACCT,R2 ;POINTER TO CHAR TABLE FOR LINE IN R2 JMP SL1 ;OFF TO THE MAIN LOOP FOR CHAR PROCESSING LFQ: ADD OVSP,RVSP ;EXPAND VERTICAL SPACING OF PREVIOUS LINE ;LEAVE OLLOW SAME BR TLINE ;NEXT TEXT LINE TL1: CLR SKPCNT ;SETUP ZERO LINES TO SKIP BR TL2 ;NO VECTORS PROCESSED, JUMP TO PAGE CHECK NPAGE: TST NPF ;DID THIS PREVIOUS LINE CAUSE A PAGE SKIP ALSO? BNE EPAGE ;YES, FORGET THAT LOSING LINE INC NPF ;SET LAST LINE PRODUCED A PAGE OVERFLOW JSR PC,TLBACK INC PPN ;AOS PRINTING PAGE NUMBER (RESET FF TIME) EPAGE: TST BSLC ;NEW PAGE, HAVE WE PUT ANYTHING ON THE OLD ONE? BEQ BLANK ;NOPE, DONT FEED THE FORM EP1: MOV LPAGE,SKPCNT SUB TVPOS,SKPCNT JSR PC,VECTCK ;CHECK TO END OF PAGE FOR MORE VECTORS JSR PC,SLB ;BUFFER FOR FORM FEED MOV TVPOS,R1 ;LOC TO CUT PAPER BIS #100000,R1 ;SET SIGN BIT FOR PAPER CUT MOV R1,(R0) ;CLOBBER INTO SCAN BUFFER COUNT TST EOFF ;END OF FILE? BEQ PAGEA ;NEW PAGE STUFF JSR PC,SLB MOV #100000,(R0) ;SEND EOF TO INTERRUPT LEVEL STUFF JSR PC,XGPWT ;WAIT FOR INT. LEVEL TO PROCESS IT JMP PDP10 ;BACK FOR ANOTHER COMMAND FROM THE 10 PAGEA: JMP PAGE BLANK: TST EOFF ;AT END OF FILE? BNE EP1 ;YES, FORM FEED ANYWAY CLR FFF ;RESET FORM FEED INDICATION JMP PAGE ;AND CONTINUE PROCESSING TEXT TLBACK: CLR EOFF ;RESET EOF UNTIL IT IS PROCESSED AGAIN CLR FFF ;LIKEWISE FFF mov blfont,font ;restore font in effect at beginning of old line MOV #TLRD,GCHARD ;MAKE GCHAR READ STORED TEXT LINE MOV TLCNT,TLCNT1 ;SETUP COUNT OF NUMBER OF CHARS IN LAST TEXT LINE RTS PC ;VECTCK IS CALLED WHEN THE TEXT PROCESSOR IS ABOUT TO ;SKIP OVER LINES BEFORE CREATING ANY SCAN LINE ;BUFFERS. IT IS UP TO VECTCK TO CHECK IF ANY VECTORS ;CROSS THESE SCAN LINES AND IF NECESSARY TO PRODUCE SCAN ;LINE BUFFERS FOR THEM. IN ANY CASE, IT INCREMENTS ;TVPOS. IT MUST SET BSLC FOR ANY LINES IT PRODUCES. VECTCK: ADD SKPCNT,TVPOS RTS PC ;VECT GETS CALLED JUST AFTER THE TEXT LINE PROCESSOR PRODUCES ;A NEW SCAN LINE. IT MUST DECIDE IF ANY VECTORS CROSS THIS LINE ;AND INSERT THEM INTO THE SCAN LINE BUFFER. VECT: RTS PC ;VECTRS GETS CALLED AT THE BEGINNING OF EACH PAGE TO RESET THE VECTOR ;DATA BASE, SINCE VECTORS ARE NOT ALLOWED TO CROSS PAGE BOUNDARIES. VECTRS: RTS PC ;ADVECT ADDS A VECTOR TO THE VECTOR DATABASE DESCRIPTION OF THE ;VECTOR IS IN X0,Y0,VN,XF,XS,XI ADVECT: RTS PC SLB: MOV SBNP,R0 ;R0 GETS ADR OF NEW BUFF TST (R0) ;FREE? BNE WAITR ;NO SLBA: MOV 2(R0),SBNP ;SETUP NEW POINTER RTS PC SLBC: ADD #4,R0 ;SKIP OVER HEADER MOV #1000,(R0)+ ;IMAGE MODE XGP LINE MOV R0,R1 REPT1 IMWDSZ,CLR (R1)+ ;LOTS OF CLEARS RTS PC WAITR: TST XGPST ;HAS XGP BEEN STARTED? BNE WAIT1 ;YES JSR PC,XGPSTR ;NOPE, BUT WE WILL WAIT1: TST (R0) ;REALLY SIT AND WAIT BNE WAIT1 BR SLBA XGPSTR: PUSH R1 PUSH R2 XGPST1: INC XGPST MOV #FMOT,XCR MOV #-2*60.,TIMER STXGP1: WAIT TST TIMER BLT STXGP1 BIT XSR,#FRDY BEQ XGPST1 MOV MKTOCT,R1 MOV R1,R2 TST TICKS1 BNE STX1 MOV TICKS,R2 STX1: JSR PC,CUTCLK ;R1 HAS # OF TICKS BEFORE IT CUTS THIS STUFF SUB #30*CF,R1 BLT STX2 SUB #30*CF,R2 BGE STX1 STX2: MOV SLBINI,SBPI ;SETUP INT LEVEL POINTERTO BUFFS CLR VPOS ;CLEAR OUT INT LEVEL VERTICAL POSITION MOV #ITEMP,OBUF ;SETUP BACK BUFFER POINTER TO POINT ;TO HARMLESS JUNK CLR XGPE ;ZERO ERROR CONDITIONS MOV #FMOT,XCR ;START IT UP MOV #BNULL,MAR ;WITH A NULL INITIAL BUFFER MOV #FDIE+FGO+FMOT,XCR ;ENABLE INTERRUPTS, AND GO POP R2 POP R1 RTS PC XGPWT: TST XGPST ;HAVE WE STARTED THE XGP? BNE XWT1 ;YES JSR PC,XGPSTR ;NO, START IT UP (THIS ONLY HAPPENS ON SHORT FILES XWT1: TST XGPFIN ;XGP FINISHED? BEQ XWT1 ;NO, WAIT MORE CLR XGPFIN ;RESET DONE FLAG CLR XGPST ;NO LONGER STARTED CLR TICKS ;RESET TIMER CLR TICKS1 XRDYX: RTS PC XGPRDY: BIT #RDMASK,XSR BEQ XRDYX ;EVERYTHING OK ABORT: BIS XSR,XGPE ;ERROR FLAGS INTO XGPE CLR XGPIMP ;PREVENT 10 FROM CLOBBERING BUFFERS CLR XCR ;STOP XGP INC ABORTF ;SIGNAL 10 WE HAVE ABORTED AB1: TST ABORTF ;10 RESPONDED? BNE AB1 ;NOPE, CONTINUE WAITING JMP START ;FINALLY RESTART SL1: INC (R2)+ ;COUNT BLT SL2 ;<0, PRINT THIS CHAR BGT FIDDLE ;>0 SKIP OVER THIS CHAR MOV #77777,-2(R2) ;SET MAX POS #, SO WE SKIP FROM NOW ON SL2: MOV (R2)+,R0 ;WORD OFFSET FROM ORIGIN MOVB (R2)+,R4 ;BIT OFFSET FROM ORIGIN ADD #0,R0 ;OFFSET WITH S.L. ORIGIN SLBO==.-2 ;CLOBBERED AT SLINE MOVB (R2)+,R1 ;WIDTH OF THIS CHAR IN WORDS MOV (R2),R3 ;PTR TO FONT BITS SL3: MOV (R3)+,(R5) ;BITS TO MQ CLR -(R5) ;CLEAR BITS SHIFTED IN MOV R4,LSH ;BITPOS INTO SHIFT COUNT BIS MQ,(R0)+ ;BITS TO CORE BIS (R5)+,(R0) ;BITS TO CORE DEC R1 BGT SL3 MOV R3,(R2)+ ;UPDATE FONT POINTER BR SL1 FIDDLE: DEC -(R2) ;RESTORE COUNT BEQ EOL ;ZERO COUNT => END OF LINE DEC (R2) ;DEC SKIP COUNT BGT FIDL1 ;SKIP MORE MOV ACCTPT(R2),R3 ;COUNT WAS ONE, SETUP CHAR TO START NEXT PASS TST (R3)+ ;INC R3, SKIP OVER SKIP COUNT MOV (R3)+,(R2) ;-HEIGHT => LINE BUFF MOV R3,ACCTPT(R2) ;PTR TO FIRST LINE OF FONT DEF. FIDL1: ADD #10,R2 ;SKIP OVER REST OF ACCT ENTRY BR SL1 ;TRY AGAIN EOL: MOV SLBO,R0 ;ADR OF OLD S.L. BUFF MOV TVPOS,-6(R0) ;STASH "IN USE" VERTICAL POSITION FIELD JMP SLINE ;NEW SCAN LINE GCHAR: JMP @GCHARD ;DISPATCH TO APPROPRIATE ROUTINE GREFIL: JSR PC,GRF ;GET NEW TEXT LINE BUFFER GCHARN: DEC DICNT ;COUNT DOWN CHARS LEFT IN BUFFER BLT GREFIL ;NONE LEFT MOVB @DINXT,R0 ;GET CHAR INC DINXT ;COUNT POINTER UP MOVB R0,@TLP ;SAVE CHAR IN LINE BUFFER BLT GEOF ;END OF FILE CHARACTER INC TLP ;TEXT LINE POINTER INC TLCNT ;COUNT OF NUMBER OF CHARS IN LAST TEXT LINE CMP TLP,#TLBND ;OVERFLOW? BHIS TLOV ;YES GCH1: BIC #177600,R0 ;CLEAR EXCEPT 177 BITS, SETUP CONDITION CODE RTS PC GRF: MOV DIBUF,R0 ;POINTER TO OLD BUFFER MOV #-1,(R0)+ ;INDICATE OLD BUFFER FREE MOV (R0),R0 ;PICK UP RING POINTER TO NEW BUFFER GRF1: MOV (R0),DICNT ;COUNT OF BYTES IN THIS BUFFER BLE TWAIT ;WAIT FOR A TEXT BUFFER (UGH) MOV R0,DIBUF ;STASH POINTER TO CURRENT BUFFER HEADER CLR (R0) ;INDICATE BUSY ADD #BHDRL,R0 ;SKIP OVER BUFFER HEADER MOV R0,DINXT ;USE AS POINTER TO FIRST CHAR IN BUFFER RTS PC TLOV: MOV #TLEND,TLP ;OVERFLOW LOCATION FOR TLBUF BR GCH1 ;BACK TO FEED CHAR AT M.P. TLRD: MOVB @TLP,R0 ;GET CHAR OUT OF BUFFER BLT GEOF ;EOF INC TLP ;BUMP POINTER DEC TLCNT1 ;RUN OUT OF CHARS? BEQ TLRD1 ;YES CMP TLP,#TLEND ;OR REACHED END OF BUFFER? BHIS TLRD1 ;YES TLRD2: BIC #177600,R0 ;FLUSH LH RTS PC TLRD1: MOV #GCHARN,GCHARD ;SETUP NORMAL TEXT INPUT BR TLRD2 ;RETURN LAST CHAR GEOF1: TST (SP)+ ;POP PC OFF STACK GEOF: TST (SP)+ ;POP PC OFF STACK JMP CHEOF ;TRAP TO EOF ROUTINE AT LINE LEVEL TWAIT: MOV #LAMBDA,TIMER ;SETUP TIMER TST DIHDR ;TEST FOR CHANNEL CLOSED BGE GEOF1 ;10 CLOSED CHNL ON US TW1: TST (R0) ;READY YET? BGT GRF1 ;YES, GO TO IT TST TIMER ;TIMER TIMED OUT? BLT TW1 ;NOPE, CHECK SOME MORE TST DBSW ;DEBUGGING? BNE TW1 ;YES, BE PATIENT TIMOUT: JMP ABORT ;ABORT THIS ABORTION PNUM: MOV @PNPT,R0 ;PICK UP CHAR OF PAGE NUMBER BEQ PNUM1 INC PNPT INC PNPT ;INCREMENT TO NEXT WORD IN PNBUFF BIC #177600,R0 RTS PC PNUM1: MOV PGCHAR,GCHARD ;RESTORE OLD SOURCE OF CHARACTERS BR GCHAR ;GO USE IT HDRS: DEC HCNT1 ;COUNT OF HEADER LINE OUT? BLT HDRS1 ;YUP MOVB @HPTR,R0 ;PICK UP CHARACTER INC HPTR ;BUMP POINTER BIC #177600,R0 ;CLEAR LEFT HALF RTS PC HDRS1: MOV HGCHAR,GCHARD ;SETUP OLD SOURCE OF CHARACTERS mov hsfont,font ;restore text font after header line BR GCHAR ;AND GO USE IT. ;MAIN LINE SETUP, PROCESSES TEXT STRING ;INTO ACCT TABLE LSETUP: MOV #TLBUF,TLP ;RESET TEXT LINE BUFFER POINTER CLR TLCNT ;CLEAR COUNT OF CHARS ON THIS LINE CLR SEPER ;CLEAR OUT INTER-CHAR SPACING CLR SKPCNT ;RESET LINES FIRM IDEA OF WHERE IT SHOULD GO CLR SKSL ;RESET # LINES SKIP PRIOR TO CHARS OF THIS KSET MOV FONT,R4 ;FONT INDEX INTO R4 mov r4,blfont ;save font at line beginning in case of backup MOV VSP,RVSP ;SETUP DEFAULT SPACING AFTER THIS LINE MOV HEIGHT(R4),CHRRCT ;SETUP INITIAL CHAR HEIGHT MOV BASE(R4),BASEL ;SETUP INITIAL BASE LINE MOV #ACCT,R2 ;INDEX TO ACCT TABLE IN R2 MOV LFTMAR,BITPOS ;SET LEFT MARGIN MOV LFTMAR,STUBIT ;SET START OF UNDERLINE DEFAULT CH1: CMP R4,#2*MAXFNT BLO 1$ BPT 1$: JSR PC,GCHAR ;MAIN CHAR PROC. LOOP ASL R0 ;WORD QUANTITY MOV R0,R1 TST (R1)+ ;MAKE 177 => 0 BIC #177400,R1 ;CLEAR OUT OVERFLOW BIT CMP R1,#34 ;<15+1>_1 BLE CTBLD ;DISPATCH ON CHARS 177, AND 0-15 CH2: MOV FNTBLS(R4),R1 ;FONT OFFSET + CHAR CODE BEQ CH1 ;BRANCH IF FONT DISPATCH DOES NOT EXIST ADD R1,R0 MOV (R0),R0 beq ch1 ;null char table entry MOVB (R0)+,R1 ;PICK UP "BEFORE" POSITION ADJUST NEG R1 ADD BITPOS,R1 ;ADD IN CURRENT POSITION BLT CH4 ;CHAR BEFORE BEG OF LINE MOV R1,MQ ;SAVE AWAY INITIAL POSITION OF THIS CHAR MOV #20,DIV ;DIVIDE IT BY 20 MOV R1,BITPOS ;BITPOS IS A GOOD TEMP MOV 1(R0),R1 ;GET "AFTER" CHAR ADJ ADD BITPOS,R1 ;ADD IN POSITION ADD SEPER,R1 ;ADD IN INTER CHAR SEPERATION MOV R1,BITPOS MOV MQ,R3 ;# WDS OFFSET FROM BEG OF S.L. ASL R3 ;CONVERT TO WD ADR MOVB (R0)+,R1 ;GET NUMBER OF WORDS PER ROW MOVB R1,ACCTNW(R2) ;SAVE IN ACCT TABLE FOR SCAN LINE SCAN BEQ CH1 ;NO WORDS, NUL CHARACTER tst (r0)+ ASL R1 ;WORD QUANTITY ADD R3,R1 ;WORD OFFSET AT END OF SCAN FOR THIS CHAR CMP R1,#IMWDSZ*2 ;OVER THE END? BHIS CH1 ;YES, IGNORE MOV R3,ACCTWD(R2) ;SAVE WORD OFFSET FROM BEG OF S.L. MOVB AC,ACCTBT(R2) ;BIT OFFSET MOV (R0),R3 ;TOP LINE OFFSET ADD SKSL,R3 ;OFFSET OF TOP LINE DUE TO FONT SWITCHING, SUPERSCRIPT BNE CH3 ;ZERO OFFSET, SETUP POINTERS AND HEIGHT FOR FIRST PASS MOV 2(R0),(R2) ;LOAD -HEIGHT INTO ACCT TABLE ADD #4,R0 ;SKIP OVER SKIPS,HEIGHT MOV R0,ACCTPT(R2) ;POINTER TO FONT TABLE ADD #10,R2 ;INDEX TO NEXT ACCT ENTRY CMP R2,#ACCTMX ;OVERFLOW OF ACCT TABLE? BLO CH1 ;NO, CONTINUE ACCTOV: CLR (R2)+ ;INSERT END TEST IN ACCT CLR (R2)+ CLR (R2)+ CLR (R2)+ MOV #BITSNK,R2 ;SETUP R2 TO R0 BIT SINK BR CH1 CH3: MOV R3,(R2) ;SKIP COUNT INTO ACCT MOV R0,ACCTPT(R2) ;POINTER TO FONT TABLE ADD #10,R2 ;INDEX TO NEXT ACCT ENTRY CMP R2,#ACCTMX BLO CH1 BR ACCTOV CH4: MOV 1(R0),R1 ;AFTER CHAR ADJUST ADD SEPER,R1 ;INTER CHAR SPACING ADD R1,BITPOS ;FIDDLE BIT POSITION BR CH1 ;BACK FOR MORE CHARS CTBLD: JMP @CTBL(R1) CTBL: CHESC ;177 CH1 ;0, IGNORE CH2 ;1 NORM CH2 CH2 CH2 CH2 CH2 CH2 CHBS ;10 BACKSPACE CHTB ;11 TAB CHLF ;12 CH2 ;13 NORM CHFF ;14 FEED THOSE FORMS CHCR ;15 RETURN THOSE CARRIAGES CHESC: JSR PC,GCHAR ASL R0 ;WORD QUAN MOV R0,R1 TST (R1)+ ;177 => 0 BIC #177400,R1 ;CLEAR OVERFLOW BIT CMP R1,#34 BGT CH2 JMP @CHTB1(R1) CHTB1: CH2 ;177, NORM CH2 ;0, NORM ESC1 ;XGP ESCAPE 1 ESC2 ;XGP ESCAPE 2 ESC3 ;XGP ESCAPE 3 ESC4 ;XGP ESCAPE 4 CH1 ;5 CH1 ;6 CH1 ;7 CH2 ;10 (BACKSPACE) NORM CH2 ;11 (TAB) NORM CH2 ;12 (LF) NORM CH1 ;13 IGNORE CH2 ;14 NORM (FF) CH2 ;15 (CR) NORM CHBS: MOV FNTBLS(R4),R1 BEQ CH1A ;BRANCH IF FONT DISPATCH DOES NOT EXIST ADD #40*2,R1 ;CODE FOR SPACE MOV (R1),R1 ;CHARACTER DEFINITION beq ch1a ;no space character in this font MOVB (R1),R0 ;BEGINING ADJUST FOR SPACE MOV 2(R1),R1 ;FINAL ADJUST FOR SPACE SUB R0,R1 ;DIFFERENCE ADD SEPER,R1 SUB R1,BITPOS ;BACK UP BGE CH1A CLR BITPOS ;CHECK END OF LINE CH1A: JMP CH1 CHTB: MOV FNTBLS,R1 ;USE WIDTH OF SPACE OF FONT 0 FOR TABBING CALCULATION BEQ CHTAB1 ;FONT DISPATCH EXIST? ADD #40*2,R1 ;CODE FOR SPACE MOV (R1),R1 ;PICK UP CHARACTER DEF BEQ CHTAB1 ;SPACE EXIST? MOVB (R1),R0 ;WIDTH OF SPACE, CURRENT FONT mov 2(R1),R1 ;after adjust SUB R0,R1 ;AFTER ADJUST - BEFORE ADJUST CHTB0: ADD SEPER,R1 ;ADD IN INTER CHAR SPACING ADD R1,BITPOS ;SPACE AT LEAST 1 SPACE WORTH ASL R1 ASL R1 ASL R1 MOV BITPOS,MQ SUB LFTMAR,MQ ;TABS TAB 8 FROM THE LEFT MARGIN! MOV R1,DIV TST AC BEQ CH1A SUB AC,R1 ADD R1,BITPOS ;ADD REMAINDER OF BITPOS/<8*SPACEWIDTH> TO BITPOS BR CH1A ;IGNORE OTHERWISE CHTAB1: MOV #20,R1 ;FONT 0 SPACE DOES NOT EXIST, DREAM UP A SPACE WIDTH BR CHTB0 CHCR: MOV LFTMAR,BITPOS BR CH1A CHEOF: INC EOFF ;END OF FILE, SIMULATE FORM FEED CHFF: INC PAGEN ;NEW PAGE, INC PAGE NUMBER CLR PPN ;FORM FEED, CLR GENERATED DECIMAL PAGE # INC FFF ;CAUSE FORM FEED AFTER THIS LINE CHLF: CMP R2,#ACCT ;ANY CHARACTERS PUT OUT ON THIS LINE? BEQ CHLFQ ;NOPE, DO A QUICK LINE FEED CLR QFF ;QUICK FORM FEED FLAG (NO OTHER CHARS ON LINE) CLR LFF ;DONT DO ONE CLR (R2)+ ;LINE FEED, SETUP END CONDITION IN ACCT, CLR (R2)+ CLR (R2)+ CLR (R2)+ RTS PC ;AND RETURN TO HACK THE SCAN LINES CHLFQ: MOV FFF,QFF ;SETUP QUICK FORM FEED FLAG IF NEEDED INC LFF ;QUICK LINE FEED FLAG RTS PC ;RETURN ESC1: JSR PC,GCHAR ;GET ESCAPE CODE CMP R0,#20 ;<20? BLT FONTSW ;YES, ITS A FONT SWITCH SUB #40,R0 ;NO OTHER ESCAPES TILL 40 BLT CH1B ;IGNORE OTHERS CMP R0,#ESC1TL/2 BHIS CH1B ;IGNORE ILLEGAL CODES ASL R0 ;GET WORD ADR JMP @ESC1T(R0) ;DISPATCH ESC1T: COLSEL ;40 XGP COLUMN SELECT UNDER ;41 ! UNDERLINE LINSPC ;42 " VARIABLE LENGTH LINE FEED BALADJ ;43 # ABSOLUTE BASE LINE ADJUST PPAPN ;44 $ PRINT PAPER PAGE NUMBER AHEAD ;45 % GOBBLE AND PRINT HEADER LINE STUND ;46 & START UNDERLINE STPUND ;47 ' STOP UNDERLINE SEPERS ;50 ( SET INTER-CHAR SPACING STPUNV ;51 ) VARIABLE NUMBER OF SCAN LINE STOP UNDERLINE RBLADJ ;52 * RELATIVE BASE LINE ADJUST RBLUSC ;53 + RELATIVE BASE LINE UNDERLINE ESC1TL==.-ESC1T PPAPN: MOV GCHARD,PGCHAR ;SAVE OLD SOURCE OF CHARACTERS MOV #PNUM,GCHARD ;SETUP SOURCE OF PAGE NUMBER ROUTINE PUSH R0 MOV #PNBUFF,R0 MOV R0,PNPT ;POINTER TO BEG OF PAGE NUMBER MOV PAGEN,MQ ;DECIMAL PRINT INTO (R0) JSR PC,DECPN1 MOV PPN,MQ BEQ PPAPN1 ;IF ZERO, DONT PRINT . OR NUMBER MOV #'.,(R0)+ JSR PC,DECPN1 PPAPN1: CLR (R0)+ ;END TEST IS ZERO WORD POP R0 BR CH1B AHEAD: INC HEADRF ;SET HEADER EXISTS FLAG JSR PC,GCHAR ;GET COUNT OF NUMBER OF BYTES MOV R0,HCNT ;SAVE COUNT MOV R0,HCNT1 ;SAVE IN TEMPORARY COUNT MOV #HBUF,HPTR ;SETUP POINTER TO HEADER BUFFER HD1: DEC HCNT1 ;RUN OUT OF BYTES? BLT CH1B ;YES JSR PC,GCHAR ;GET NEXT CHAR FOR HEADER LINE MOVB R0,@HPTR ;SAVE IN HEADER BUFFER INC HPTR ;BUMP HEADER POINTER BR HD1 ;BACK FOR NEXT BYTE OF HEADER DECPN1: MOV #10.,DIV MOV AC,-(SP) ADD #'0,(SP) TST MQ BEQ DECPN2 CLR AC JSR PC,DECPN1 DECPN2: POP (R0)+ RTS PC FONTSW: CMP R0,#MAXFNT ;> MAX FONT #? BGE CH1B ;YES ASL R0 ;CONVERT TO WORD ADDRESS MOV R0,R4 ;SETUP R4 CORRECTLY MOV R4,FONT ;SAVE AWAY FOR INTER-LINE RESTORATION CMP R2,#ACCT ;WRITTEN ANY CHARS YET ON THIS LINE? BEQ FONT1 ;NO, JUST CLOBBER CHRRCT AND BASEL MOV BASE(R4),R0 ;PICK UP NEW BASE CMP R0,BASEL ;COMPARE WITH OLD BASE LINE BLE FONTSM ;SMALLER FONT, SET SKSL SUB BASEL,R0 ;GET # LINES WE NEED TO PUSH THIS LINE JSR PC,PUSHL ;DOWN BY FONT2: MOV HEIGHT(R4),R0 ;HEIGHT OF NEW FONT ADD SKSL,R0 ;PLUS LINES SKIPPED BEFORE IT CMP R0,CHRRCT ;HAD BETTER BE LESS THAN CHRRCT BLE CH1B ;OK MOV R0,CHRRCT ;MAKE IT SO CH1B: JMP CH1 FONTSM: MOV BASEL,SKSL SUB R0,SKSL ;SKIPS=BASEL-BASE(FONT) BR FONT2 ;CHECK DECSENDING DIRECTION FONT1: MOV BASE(R4),BASEL ;NO CHARS YET, JUST CLOBBER BASEL, CHRRCT,SKSL MOV HEIGHT(R4),CHRRCT CLR SKSL BR CH1B ;ABSOLUTE BASE LINE ADJUST BALADJ: JSR PC,GCHAR ;GET AMOUNT ASL R0 MOV R0,TEMP MOVB TEMP,R0 ASR R0 MOV BASEL,R1 ;BASE LINE SUB BASE(R4),R1 ;SKIPS FOR THIS FONT (UNADJUSTED) SUB R0,R1 ;NEW SKIP COUNT BLT SUPER ;NEGATIVE, WE WENT OFF THE TOP BALAD1: MOV R1,SKSL ;OK, SETUP SKIP COUNT BR FONT2 ;AND CHECK WE DONT RUN OUT OF SCAN LINES AT BOTTOM SUPER: NEG R1 ;COUNT OF LINES TO PUSH DOWN MOV R1,R0 JSR PC,PUSHL ;PUSH IT BR FONT2 ;CHECK FOR DESCENDING CHARS ;RELATIVE BASE LINE ADJUST RBLADJ: JSR PC,GCHAR ASL R0 ;CHARACTER IS 7-BIT SIGNED INTEGER MOV R0,TEMP MOVB TEMP,R0 ;USE SIGN EXTEND FEATURE OF MOVB TO ACCUMULATOR ASR R0 SUB R0,SKSL MOV SKSL,R1 BPL FONT2 BR SUPER PUSHL: CLR SKSL ;IT MUST BE 0 OR WE WOULDNT BE HERE ADD R0,BASEL ;CLOBBER BASEL DOWN SOME ADD R0,CHRRCT ;AND EXPAND CHRRCT MOV R2,R2PL MOV R3,R3PL MOV #ACCT,R2 ;POINTER TO SKIP/COUNT FIELD PUSH1: CMP R2,R2PL ;TEST DONE WITH LINE SO FAR BHIS PX MOV (R2),R3 ;GET SKIP/HEIGHT BLT PUSH3 ;HEIGHT WAS SETUP BEQ SPAZ ;THIS SHOULDNT HAPPEN ADD R0,R3 ;ADD SKIP COUNT TO CHAR MOV R3,(R2) ;PUT IT BACK PUSH2: ADD #8,R2 ;NEXT ENTRY IN ACCT BR PUSH1 PUSH3: MOV R0,(R2) ;SKIP COUNT WAS REALLY 0, CLOBBER IN THE NEW ONE SUB #4,ACCTPT(R2) ;BACKUP THE FONT POINTER BR PUSH2 SPAZ: JSR PC,ERROR PX: MOV R2PL,R2 ;RESTORE R2 MOV R3PL,R3 ;RESTORE R3 RTS PC COLSEL: JSR PC,GCHAR ;GOBBLE HI ORDER BYTE SWAB R0 ASR R0 ;ITS ONLY 7 BITS MOV R0,TEMP JSR PC,GCHAR BIS TEMP,R0 ;OR IN THE LOW ORDER BYTES MOV R0,BITPOS ;JUMP AWAY TO THE NEW LINE POS BR CH1C STUND: MOV BITPOS,STUBIT ;SAVE AWAY SPOT TO START UNDERLINING CH1C: JMP CH1 STPUND: MOV #1,ULCNT ;ONE LINE OF UNDERLINEAGE BR STPUN1 STPUNV: JSR PC,GCHAR ;MULTIPLE UNDERLINE COMMAND MOV R0,ULCNT ;VARIABLE NUMBER OF UNDERLINE LINES STPUN1: MOV STUBIT,OSTBT ;SAVE OLD START UNDERLINE JSR PC,GCHAR MOV R0,ULSL ;SCAN LINE TO UNDERLINE ON MOV BITPOS,STPL ;LENTH OF UNDERLINE SUB SEPER,STPL ;SUBTRACT INTER CHARACTER SPACING SUB STUBIT,STPL BGE STPUN2 ;ABS VALUE NEG STPL ;WIN FOR STOPPING BEFORE YOU START MOV BITPOS,STUBIT STPUN2: MOV ULSL,SVULSL ;SAVE ULSL IN CASE WE LOOP BACK FOR MORE THAN ONE UNDERLINE BR UNDERL ;RELATIVE BASELINE UNDERSCORE, SAME AS UNSER, BUT ADDS THE ADJUSTED BASELINE RBLUSC: JSR PC,UNDER1 ;GET PARAMETERS MOV ULSL,R0 ;GET THE UNDERLINE LINE BIT #100,R0 ;POSITIVE OR NEGATIVE? BNE RBLUS1 ;NEGATIVE, MAKE IT FULL WORD BIC #177600,R0 ;CLEAR OUT ANY STRAY BITS RBLUS2: SUB BASEL,R0 ;TURN IT INTO BASELINE ADJUSTED FROB ADD SKSL,R0 ADD BASE(R4),R0 ;ADJUST BASELINE MOV R0,ULSL ;AND THIS IS THE LINE TO UNDER LINE ON BR UND2 RBLUS1: BIS #177600,R0 ;TURN IT NEGATIVE BR RBLUS2 UND1: BIS #177600,R0 ;SET TO NEGATIVE NUMBER BR UND2 ;BRANCH BACK UND3: NEG R0 ;MAKE R0 POSITIVE COUNT OF LINES TO PUSH DOWN ADD R0,SKSL PUSH SKSL ;SAVE SKIP COUNT, WE ARE NOT REALLY CHANGING FONTS JSR PC,PUSHL ;SHOVE IT POP SKSL ;RESTORE SKIP COUNT CLR R0 ;UNDERLINE ON SCAN LINE ZERO BR UND4 UNDER1: MOV STUBIT,OSTBT ;SAVE START OF UNDERLINE JSR PC,GCHAR MOV R0,ULSL JSR PC,GCHAR SWAB R0 ASR R0 MOV R0,TEMP JSR PC,GCHAR BIS TEMP,R0 MOV R0,STPL MOV BITPOS,STUBIT MOV #1,ULCNT ;ONE UNDERLINE ONLY MOV ULSL,SVULSL ;SAVE AWAY ULSL (NOT REALLY NECESSARY, BUT... RTS PC UNDER: JSR PC,UNDER1 UNDERL: MOV STUBIT,R0 CMP R0,#NBITS ;STARTING PAST END OF LINE? BHIS CH1C ;YES, TOTALLY IGNORE ADD STPL,R0 ;ENDING LOCATION CMP R0,#NBITS ;ENDING OFF END OF LINE? BLO UND5 ;NO, DO IT MOV #NBITS,STPL SUB STUBIT,STPL UND5: MOV ULSL,R0 ;PICK UP CHAR FOR SCAN LINE NUMBER BIT #100,R0 ;POSITIVE OR NEGATIVE? BNE UND1 ;NEGATIVE, MAKE IT FULL WORD BIC #177600,R0 ;CLEAR OUT ANY STRAY BITS UND2: TST STPL BEQ CH1D ADD BASEL,R0 ;RELATIVE TO BASELINE ADD ULOFF,R0 ;PLUS KLUDGY OFFSET TO MAKE TJ6 HAPPY BLT UND3 CMP R0,CHRRCT BLT UND4 ;OK, WITHIN EXISTING LINE MOV R0,CHRRCT ;EXPAND LINE ENOUGH FOR THIS UNDERLINE INC CHRRCT UND4: MOV R0,ULSL ;SETUP SCAN LINE NUMBER TO WIN ON MOV R4,ULR4 ;SAVE FONT POINTER MOV STUBIT,MQ MOV #20,DIV MOV MQ,R0 ASL R0 MOV R0,ACCTWD(R2) MOVB AC,ACCTBT(R2) MOV STPL,MQ MOV #20,DIV ;GET # WORDS OF UNDERLINEAGE MOV MQ,R0 MOV AC,R1 BIC #177600,R0 ;PARANOIA, CLEAR OUT ENUF BITS TO MAKE BYTE POS BEQ UL1 ;NO WORDS, MAYBE SOME BITS MOV #ONES,R4 MOV ULSL,R3 BNE UL2 ;SETUP HEIGHT ON FIRST LINE ADD #4,R4 ;SETUP POINTER TO FONT BITS DEC R3 ;0=> -1 WHICH IS HEIGHT OF UNDERLINE UL2: MOV R3,(R2) ;SETUP SCAN LINE NUMBER MOVB R0,ACCTNW(R2) ;SETUP # WORDS OF ONES MOV R4,ACCTPT(R2) ;POINTER TO ONES ADD #10,R2 ;INDEX TO NEXT ACCT ENTRY TST R1 BEQ UL5 ;NO STRAY BITS, EXIT CMP R2,#ACCTMX ;OVERFLOW ACCT? BHIS ACTOVU ADD STPL,STUBIT ;FINAL POSITION SUB R1,STUBIT ;FINAL POSITION AFTER END OF WHOLE WORDS MOV STUBIT,MQ ;CONVERT TO WORD+BIT OFFSET INTO S.L. MOV #20,DIV MOV MQ,R0 ASL R0 MOV R0,ACCTWD(R2) MOVB AC,ACCTBT(R2) UL1: MOV R1,R4 ;PICK UP CHAR OF N BITS OF ONES ASL R4 ;CONVERT TO WORD ADDRESS ADD R1,R4 ;3 WDS/ENTRY IN CHAR TABLE ASL R4 ADD #ULTBL,R4 ;ORIGIN OF TABLE OF "CHARS" WITH BITS ON MOV ULSL,R3 BNE UL3 DEC R3 ;0 => -1 (HEIGHT) ADD #4,R4 ;SKIP OVER SKIPS,HEIGHT UL3: MOV R3,(R2) ;COUNT FIELD MOVB #1,ACCTNW(R2) ;ONE WORD ONLY MOV R4,ACCTPT(R2) ADD #10,R2 ;INDEX TO NEXT ACCT ENTRY UL5: MOV ULR4,R4 MOV OSTBT,STUBIT ;RESTORE START OF UNDERLINE CMP R2,#ACCTMX ;OVER FLOW ACCT? BLO UL6 ACTOVU: MOV ULR4,R4 JMP ACCTOV SEPERS: JSR PC,GCHAR ;GET INTER CHAR SPACING MOV R0,SEPER CH1D: JMP CH1 UL6: DEC ULCNT ;MORE LINES? BLE CH1D ;NOPE, DONE INC SVULSL ;NEXT LOWER SCAN LINE MOV SVULSL,ULSL JMP UNDERL ;BACK FOR MORE, FANS LINSPC: JSR PC,GCHAR ;GET SPACING AFTER THIS LINE MOV R0,RVSP JMP CHLF ;GO LINE FEED ESC2: JSR PC,GCHAR ;GET RELATIVE COLUMN SELECT CMP R0,#100 ;POS OR NEG? BGE SUBCOL ;NEG, SUBTRACT ADD R0,BITPOS ;ADD IT IN BR CH1D SUBCOL: BIS #177700,R0 ;MAKE IT NEGATIVE # ADD R0,BITPOS ;ADD IT IN BGE CH1D ;IF POS, RETURN CLR BITPOS ;OTHERWISE, CLEAR IT TO ZERO BR CH1D ESC3: JSR PC,GCHAR ;GET VERTICAL POSITION FOR THIS LINE SWAB R0 ASR R0 ;7 BITS ONLY MOV R0,TEMP JSR PC,GCHAR BIS TEMP,R0 CMP R0,TVPOS ;POS HAD BETTER BE AFTER THIS ;CURRENT LINE POSITION, OR HE LOSES BLE CH1D SUB TVPOS,R0 ;FIND DIFFERENCE MOV R0,SKPCNT ;CAUSE THAT MANY SKIPS BEFORE THIS LINE BR CH1D ESC4: JSR PC,GCHAR SWAB R0 ASR R0 MOV R0,TEMP JSR PC,GCHAR BIS TEMP,R0 MOV R0,Y0 JSR PC,GCHAR SWAB R0 ASR R0 MOV R0,TEMP JSR PC,GCHAR BIS TEMP,R0 MOV R0,X0 JSR PC,GCHAR SWAB R0 ASR R0 MOV R0,TEMP JSR PC,GCHAR BIS TEMP,R0 MOV R0,R1 ASR R0 ASR R0 CLR DXS BIT #4000,R0 BEQ DXSC INC DXS DXSC: BIC #4000,R0 MOV R0,DXI BIC #177774,R1 SWAB R1 ASR R1 MOV R1,TEMP JSR PC,GCHAR BIS TEMP,R0 MOV R0,DXF JSR PC,GCHAR SWAB R0 ASR R0 MOV R0,TEMP JSR PC,GCHAR BIS TEMP,R0 MOV R0,VN JSR PC,GCHAR SWAB R0 ASR R0 MOV R0,TEMP JSR PC,GCHAR BIS TEMP,R0 MOV R0,VW JSR PC,ADVECT ;ADD VECTOR TO THE DATA BASE JMP CH1 XGPDON: PUSH R0 TST XCR BLT XGPERR ;SIGN BIT OF XCR IS ERROR FLAG XGPD1: MOV SBPI,R0 ;POINTER TO INTERRUPT SCAN LINE BUFFERS CLR @OBUF ;INDICATE OLD BUFFER NOW EMPTY MOV R0,OBUF ;SAVE POINTER TO NEW BUFFER INC VPOS ;INC INTERRUPT COUNT TST (R0) ;EMPTY? BLE EMPTY ;YES, OR CUT CMP (R0)+,VPOS ;REACHED PLACE FOR THIS LINE YET? BLT XGPMIS ;BIT THE BAG, TRY TO RECOVER BEST AS POSS BGT NULLIN ;NOPE, SEND R0 NULL LINE XGPC: MOV (R0)+,SBPI ;ADVANCE POINTER MOV R0,MAR ;SETUP POINTER TO SCAN LIEN XGPX: MOV #FDIE+FGO+FMOT,XCR ;STARTER UP POP R0 RTI XGPERR: MOV XSR,R0 BIS R0,XGPE BIT #FRDYC,R0 ;READY CHANGED? BEQ XGPD1 ;NOPE, IGNORE ERROR BIT #FRDY,R0 ;READY UP? BNE XGPD1 ;READY REALLY STILL UP ANYWAY JMP ABORT ;WE REALLY JUST LOST READINESS XGPMIS: MOV -2(R0),VPOS ;PRETEND WE DIDNT LOSE THIS LINE BR XGPC ;CONTINUE (FORGE AHEAD) EMPTY: BLT CUTR ;NEGATIVE, CUT OR EOF NULLIN: MOV #BNULL,MAR ;SETUP NULL LINE MOV #ITEMP,OBUF ;JUNK LOCATION TO BE CLEARED ON NULL LINE BR XGPX CUTR: MOV (R0)+,ITEMP BIC #100000,ITEMP BEQ EOFI ;END OF FILE IF CUT AT PAGE LOC 0 CMP ITEMP,VPOS ;REACHED CUT PAGE LOCATION? BGT NULLIN ;NOPE, WAIT WITH BLANK LINES CLR VPOS ;JUST CUT, RESET INTERRUPT POSITION PUSH R1 MOV MKTOCT,R1 JSR PC,CUTCLK ;CUT WHEN THIS LINE GETS TO CUTTER POP R1 MOV (R0),SBPI ;ADVANCE BUFFER POINTER BR XGPD1 ;GET NEXT BUFFER ON NEW PAGE EOFI: CLR XCR ;STOP THE WORLD INC XGPFIN ;SET DONE FLAG POP R0 RTI CLKBRK: INC TICKS BVC CLKB1 INC TICKS1 CLKB1: INC TIMER PUSH R0 MOV #CLKQS,R0 CLKB3: TST (R0)+ BEQ CLKB2A DEC -(R0) BNE CLKB2 MOV #FCUTI,XCUT ;ACTIVATE CUTTER BAR CLKB2: TST (R0)+ CLKB2A: CMP R0,#CLKQS+<2*NCLKQS> BLO CLKB3 CUTX: POP R0 RTI ;HERE TO QUEUE CUT REQUEST ;R1 HAS # 60THS BEFORE CUT HAPPENS CUTCLK: TST AUTCUT ;ARE WE SUPPOSED TO CUT? BEQ CUTX1 ;NO PUSH R0 MOV #CLKQS,R0 ;LOOP LOOKING FOR IDLE CLOCK QUEUE BLOCK CUT1: TST (R0)+ ;FREE? BEQ CUT2 ;YES CMP R0,#CLKQS+<2*NCLKQS> ;END TEST BLO CUT1 ;LOOP CUTX1A: POP R0 CUTX1: RTS PC CUT2: MOV R1,-(R0) BR CUTX1A IDLE: 0 ;0 => NOT WAITING FOR MAIN PDP10 COMMAND ITEMP: 0 ;TEMPORARY AT INTERRUPT LEVEL (XGP) TEMP: 0 ;MAIN PROG TEMP lbadj: 0 ;temp for before adjust in loading fonts laadj: 0 ;temp for after adjust in loading fonts lwdspr: 0 ;temp for words/row in loading fonts LKOVRF: 0 ;BUFFER OVERFLOW WHILE LOADING CHARACER FLAG FONT: 0 ;INDEX TO CURRENT FONT, FOR INTERLINE HACKING ;SINCE THIS IS IN R4 DURING LINE SCAN blfont: 0 ;storage for font at beginning ;of this line for use in backup after page length exceeded hsfont: 0 ;storage for font before header line ;started, used to restore after header over SKPCNT: 0 ;SKIPPED LINE COUNT BETWEEN TEXT LINES (# TOTALLY BLANK LINES) BASEL: 0 ;NUMBER OF SCAN LINES DOWN THE BASE LINE FOR THIS TEXT LINE IS CHRRCT: 0 ;TOTAL NUMBER OF SCAN LINES WITH BLACKNESS ON IN THIS ;TEXT LINE SKSL: 0 ;NUMBER OF SCAN LINES SKIPPED BEFORE OUTPUTTING CHARACTERS ;IN THE CURRENT FONT. NON ZERO ONLY AFTER FONT SWITCH ;OR UPWARDS THEN DOWNWARDS BALADJ BITPOS: 0 ;BIT POSITION WE ARE ABOUT TO OUTPUT THE ;NEXT CHARACTER INTO TVPOS: 0 ;MAIN PROGRAM IDEA OF VERTICAL PAGE POSITION VPOS: 0 ;INT LEVEL VERT PAGE POSITION SEPER: 0 ;INTER CHARACTER SPACING (RESET AT END OF LINE) OSTBT: 0 ;SAVED STUBIT FOR WITHIN UNDERLINE ROUTINE STUBIT: 0 ;SAVED LOCATION FROM "START OF UNDERLINE" ULSL: 0 ;SCAN LINE WE ARE UNDERLINNG ON SVULSL: 0 ;PLACE TO SAVE ULSL DURING MULTIPLE UNDERLINES STPL: 0 ;LENGTH IN BITS OF AN UNDERLINE COMMAND ULCNT: 0 ;COUNT OF NUMBER REMAINING UNDERLINES IN MULTIPLE UNDERLINE MODE AUTCUT: 0 ;0=> NO CUTTING ON THIS FILE VSP: 0 ;DEFAULT INTERLINE SPACING (BASE LINE TO BASE LINE) RVSP: 0 ;REAL VSP FOR THIS LINE (CHANGED BY VARIABLE LF) OVSP: 0 ;SAVE RVSP FROM THE PREVIOUS LINE (USED TO ;CALCULATE SKPCNT) OLLOW: 0 ;AMOUNT THE PREVIOUS TEXT LINE DESCENDED BELOW ITS BASE LINE ;USED TO CALCULATE SKPCNT EOFF: 0 ;END OF FILE FLAG (SET BY GCHAR)(EXAMINED NEAR TLINE) BSLC: 0 ;COUNT OF BLACK SCAN LINES THIS PAGE ;USED TO IGNORE TOTALLY BLANK PAGES QFF: 0 ;QUICK FORM FEED FLAG CAUSES NO ATTEMPT ;TO BE MADE TO PRINT THIS STUFF SINCE ITS BLANK ANYWAY LFF: 0 ;SET IF THIS TEXT LINE HAS NO PRINTING CHARS ;CAUSES THE TLINE STUFF TO SKIP OVER THE LINES IN QUESTION GCHARD: 0 ;DISPATCH FOR SOURCE OF TEXT CHARACTERS TLCNT: 0 ;COUNT OF CHARS ON THIS LINE SO FAR TLCNT1: 0 ;TEMPORARY COUNT USED IN TLRD BECAUSE TLCNT IS CLOBBERED AT LSETUP TLP: 0 ;POINTER TO BYTE WHERE NEXT CHAR IN TEXT LINE ;WILL BE BUFFERED IN CASE OF RESCAN AT BOTTOM OF PAGE TLBUF: .=.+1000 ;BYTE BUFFER TO STORE LAST TEXT LINE TLBND==.-2 ;LIMIT OF TEXT LINE BUFFER TLEND: 0 ;EXTRA LOCATION FOR OVERFLOW OF TLBUF PGCHAR: 0 ;SAVED GCHARD WHILE IN PNUM INPUT ROUTINE PAGEN: 0 ;PAGE NUMBER WE ARE ON (INC AT FF ONLY) PPN: 0 ;NUMBER OF PAGES GENERATED (IE WITHOUT FORM FEEDS IN THE TEXT) PNPT: 0 ;POINTER TO PNBUFF DURING PAGE NUMBER PRINTING PNBUFF: .=.+30 ;BUFFER FOR PAGE NUMBER HEADRF: 0 ;FLAG INDICATING PRESENCE OF R0 TEXT LINE HEADER HGCHAR: 0 ;SAVED GCHARD WHILE IN HEADER LINE HCNT: 0 ;COUNT OF BYTES IN HEADER LINE HCNT1: 0 ;TEMP COUNT OF BYTES IN HEADER LINE WHILE IN HDRS HPTR: 0 ;POINTER TO HEADER LINE BUFFER HBUF: .=.+200 ;BUFFER FOR HEADER LINE (MAX 200 SINCE BYTE COUNT <177) NPF: 0 ;FLAG INDICATING THAT LAST TEXT LINE CAUSED AN OVERFLOW FORM FEED FFF: 0 ;FEED FORMS AFTER THIS LINE (SET BY R0 FF IN TEXT LINE) VLPFLG: 0 ;FLAG NON ZERO FOR VARIABLE LENGTH PAGES, TERMINATED ONLY BY FF BOTMAR: 0 ;BOTTOM MARGIN, SCAN LINES FROM TOP TOPMAR: 0 LFTMAR: 0 LPAGE: 0 ;LENGTH OF PAGE IN SCAN LINES XGPST: 0 ;XGP STARTED FLAG XGPFIN: 0 ;XGP INTERRUPT LEVEL FINISHED SLBINI: 0 ;POINTER TO FIRST PI LEVEL BUFFER SBNP: 0 ;POINTER TO MAIN PROG S.L. BUFFERS SBPI: 0 ;INTERRUPT POINTER TO S.L BUFFERS OBUF: 0 ;POINTER TO OLD INT LEVEL S.L. BUFFER USED TO SET EMPTY FLAG MKTOCT: 4020 ;MAGIC DISTANCE IN 60THS SEC FROM DRUM EXPOSURE TO PAPER CUTTER CLKQS: .=.+ ;SPACE FOR NCLKQS CUT MARKS TICKS: 0 ;LOW ORDER TIMER TICKS1: 0 ;HIGH ORDER OF TIMER TIMER: 0 ;SHORT TERM TIMER REGISTER R3PL: 0 ;SAVED R3 IN PUSHL R2PL: 0 ;SAVED R2 IN PUSHL ULR4: 0 ;SAVED R4 IN UNDERLINE CODE Y0: 0 ;Y0 OF VECTOR X0: 0 ;X0 OF VECTOR DXS: 0 ;SIGN OF DELTA X DXI: 0 ;INTEGER PART OF X DXF: 0 ;FRACTION OF DX VN: 0 ;NUMBER OF SCAN LINES ACTIVE FOR VW: 0 ;X WIDTH OF THE VECTOR CHRIDX: 0 ;TEMP IN LKSET FOR INDEX INTO CHAR TABLE SKIPS: 0 ;COUNT OF BLANK SCAN LINES AT TOP OF CHAR BROWS: 0 ;COUNT OF BLACK ROWS OF CHAR IN LKSET NROWS: 0 ;TEMP FOR REMAINING HEIGHT OF CHAR IN LKSET BOTZR: 0 ;COUNT OF ZERO LINES AT THE BOTTOM OF THIS CHARACTER BEING LOADED ROWNZ: 0 ;COUNT OF NON ZERO WORDS IN THIS ROW OF CHAR FSPTR: 0 ;FREE STORAGE POINTER ULOFF: 3 ;DOWNWARDS OFFSET OF UNDERLINES TO APOLOGIZE TO TJ6 DBSW: 0 ;DEBUGGING SWITCH OR NOT ONES: 0 ;SKIPS -1 ;NEGATIVE OF HEIGHT REPT1 IMWDSZ,-1 ;LOTS OF ONES ULTBL: REPT3 20,0,-1,<<1_<.RPCNT+1>>-1> BNULL: .BYTE 2,0,0,1 ;NULL SCAN LINE HEIGHT: REPT1 MAXFNT,0 BASE: REPT1 MAXFNT,0 FNTBLS: REPT1 MAXFNT,0 IMBP: 0 ;POINTER TO NEXT PDP-10 BUFFER RING ENTRY IMOBP: 0 ;POINTER TO CURRENT/OLD PDP-10 BUFFER RING ENTRY IMSLP: 0 ;POINTER TO CURRENT SCAN LINE BEGINNING IMLPOS: 0 ;SAVED LINE POSITION FOR THIS LINE .=.+100 ;STACK STK: 0 PAT: PATCH: .BLKW 100 PATCHE: -1 ;10-11 CHANNEL HEADER AREA ; 11-10 COMMUNICATIONS BUFFER SIZES ACTCHN==3 ;ACTIVE CHANNELS ;(CI) COMMAND INPUT CHANNEL DESCRIPTION CINBUF==2 ; NUMBER OF BUFFERS CIBFL==100 ; SIZE OF BUFFER ;(CO) COMMAND OUTPUT CHANNEL DESCRIPTION CONBUF==0 COBFL==0 ;(DI) DATA INPUT CHANNEL DESCRIPTION DINBUF==10 DIBFL==300 ;CHANNEL HEADER AREA .MACRO CHHDR CI .IIF EQ CI'NBUF,CI'BF0==0 TENWRD CI'HDR: 0 ; STATUS BITS ; 15 1=>CHANNEL OPEN CI'BUF: CI'BF0 ; BUFFER RING POINTER (BUFFER BEING HACKED BY 11) CI'NXT: 0 ; NEXT AVAILABLE BYTE CI'CNT: 0 ; # BYTES IN BUFFER .ENDM ;LEAVE CONTIGUOUS AND IN THIS ORDER .IRP R0, .XLIST CHHDR R0 .LIST .ENDM .MACRO FOO1 R0,B R0'BF'B: -1 .ENDM .MACRO FOO2 R0,B R0'BF'B .ENDM ;CHANNEL BUFFERS BHDRL==6 ; SIZE OF BUFFER HEADER AREA .MACRO BFRING R0,NUM,SIZE .IF NE NUM TENWRD R0'BF0: -1 ; BYTE COUNT(.LT.=>FREE, .EQ.=>BUSY, .GT.=>COUNT) R0'BF1 ; POINTS TO NEXT BUFFER ON RING SIZE ; BUFFER SIZE IN BYTES .=.+SIZE .IFL NUM-2 .ERROR LESS THAN TWO BUFFERS SPECIFIED .ENDC .IFGE NUM-2 .REPT NUM-2 TENWRD FOO1 R0,\<.RPCNT+1> FOO2 R0,\<.RPCNT+2> SIZE .=.+SIZE .ENDR TENWRD FOO1 R0,\ FOO2 R0,0 SIZE .=.+SIZE TENWRD .ENDC .ENDC .ENDM BUFORG==. .IRP R0, .XLIST BFRING R0,R0'NBUF,R0'BFL .LIST .ENDM BUFFRL==.-BUFORG ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; LEAVE CONTIGOUS AND IN THIS ORDER SEE LK3 FOR THE REASON TENWRD SLB1: .=.+ ;SPACE FOR SCAN LINE BUFFERS ;POINTER STRUCTURE SETUP AT MX1 ;AREA USED IN LKSET FOR TEMP STORAGE SLBND: ;BOUNDARY OF SCAN LINE BUFFER AREA ACCT: .=.+2200;MAX OF 128 ENTRIES (PRINTING CHARS/LINE) BITSNK: .=.+20 ;AREA FOR OVERFLOW OF ACCT TO BE SUNK INTO ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;FORMAT OF ACCT TABLE ENTRIES ;FOUR WORDS PER INK PRODUCING CHARACTER ;WD0/ IF POS, SKIP THIS NUMBER OF ROWS BEFORE STARTING ; IF NEG, THIS IS AN ASCENDING NUMBER OF ROWS LEFT IN THIS ENTRY ; IF ZERO, END OF LINE ;WD1/ WORD OFFSET INTO SCAN LINE BUFFER ;WD2/ (LOW BYTE) BIT OFFSET INTO SCAN LINE BUFFER (<17) ; (HIGH BYTE) WIDTH IN WORDS OF ROW ;WD3/ POINTER TO EITHER ; (1) HEADER OF FONT ENTRY IF WD2 RH POS ;OR (2) POINTER INTO FONT ENTRY ;INCREMENTED TO POINT TO NEW WORDS AS OLD ONES USED UP ACCTMX==.-20 ;LIMIT TEST FOR ACCT OVERFLOW ;FORMAT FOR CHARACTER FONT TABLE: ;WD0 OF FONT TABLE: WDS/ROW,,BEFORE ADJUST ;WD1 AFTER CHARACTER ADJUST (FULL WORD) ;WD2 SKIP COUNT BEFORE USEFUL BITS ;WD3 NEGATIVE OF HEIGHT (NOT COUNTING SKIPPED LINES) ;WD4 ON START OF FONT BITS ;FREE STORAGE VARIABLES MEMTOP: 0 ;FIRST NXM AVAIL: 0 ;POINTS TO FIRST FREE BLOCK ROVER: 0 ;POINTS TO HEAD OF SEARCH LIST OLDBLK: 0 ;FAKE BLOCK FAKEBL: 0 FS+2 FAKEBL+2 -1 ;FREE STORAGE FS=. ;FREE STORAGE STARTS HERE .END START