	.TITLE TAPFOR
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;		LAWRENCE UNIVERSITY
;		COMPUTER CENTER
;		APPLETON, WISCONSIN 54911
;		(414) 739-3681, EXT. 564
;
;   PROGRAM NAME, VERSION AND DATE:
;	TAPFOR.MAC, VERSION DEC-11-YPTA-PB/L1, 8/1/70
;
;   PROGRAM AUTHORSHIP:
;	TAPFOR IS BASED ON THE STANDARD DEC FORMATTING PROGRAM,
;	DEC-11-YPTA-PB, AS OF 8/1/70. IT WAS MODIFIED FOR USE AS
;	A STAND-ALONE RSTS SUPPORT PROGRAM BY MARK WILLIAMSON AND
;	PAUL KONING, BOTH OF THE LAWRENCE UNIVERSITY COMPUTER CENTER.
;
;   PURPOSE OF PROGRAM:
;	TAPFOR IS A PROGRAM FOR FORMATTING DECTAPES IN THE STANDARD
;	FORMAT FOR THE PDP11. IT WAS ADAPTED SO THAT IT CAN BE STORED
;	ON THE RSTS CIL AND LOADED BY THE RSTS INITIALIZING ROUTINES,
;	IN THE SAME WAY AS ROLLIN OR DSKINT.
;
;   LANGUAGE AND OPERATING SYSTEM:
;	TAPFOR IS WRITTEN IN PAL11 (MACRO). IT OPERATES AS A STAND-ALONE
;	PROGRAM, I. E. IT DOES NOT USE THE SUPPORT OF ANY MONITOR, BE IT
;	RSTS OR DOS.
;
;   AVAILABILITY:
;	TAPFOR IS A NON-PROPRIETARY PROGRAM PRODUCT OF LAWRENCE
;	UNIVERSITY. IT IS DISTRIBUTED AT COST FOR EDUCATIONAL USE, ON
;	THE CONDITION THAT IT NOT BE SOLD, RENTED OR LEASED FOR PROFIT.
;
;   LIMITATIONS:
;	(NONE)
;
;   FURTHER DOCUMENTATION:
;	FOR GENERAL DOCUMENTATION PLEASE CONSULT THE DOCUMENTATION FOR
;	THE ORIGINAL DEC FORMATTING PROGRAM. THE CHANGES MADE INVOLVE
;	THE FOLLOWING:
;
;	1) TAPFOR WILL PRINT OUT SETUP INSTRUCTIONS TO THE OPERATOR
;	   WHENEVER HIS INTERVENTION IS NEEDED. THE PRINTING
;	   ROUTINE ASSUMES A 30 CPS (LA30 OR TEXAS INSTRUMENTS 700 TYPE
;	   DEVICE) AS THE CONSOLE KEYBOARD AND PROVIDES APPROPRIATE FILL
;	   CHARACTERS.
;	2) AFTER PRINTING OUT INSTRUCTIONS, TAPFOR WILL WAIT FOR THE
;	   OPERATOR TO ACT AS INSTRUCTED AND HIT A KEY ON THE KEYBOARD.
;	   TAPFOR THEN CONTINUES.
;	3) TAPFOR CAN NOW BE LINKED TO ANY LOCATION IN CORE, SO THAT
;	   IT CAN BE MADE LOADABLE BY DOS, RKDP, TCDP OR RSTS BY AN
;	   APPROPRIATE CHOICE OF LOAD ADDRESS.
;
;   DISCLAIMER:
;	NEITHER THE AUTHORS OF THIS PROGRAM NOR LAWRENCE UNIVERSITY
;	ASSUME ANY LIABILITY, EXPRESSED OR IMPLIED, WITH RESPECT TO
;	THE CORRECTNESS OR PERFORMANCE OF THIS PROGRAM.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
	.TITLE	TAPFOR
	R0=%0                          ; REGISTER ASSIGNMENTS
	R1=%1
	R2=%2
	R3=%3
	R4=%4
	R5=%5
	R6=%6
	R7=%7
	SP=R6
	PC=R7
	SR=177570                  ; SWITCH REGISTER
	PS=177776                  ; PROCESSOR STATUS
	NOP=240                    ; NO-OPERATION INSTR.
	CR=15                      ; CARRIAGE RETURN
	LF=12                      ; LINE FEED
	TKS=177560                 ; KEYBOARD STATUS
	TKB=177562                 ; KEYBOARD BUFFER
	TPS=177564                 ; TELEPRINTER STATUS
	TPB=177566                 ; TELEPRINTER BUFFER

.MACR  AND A,B
	BIC  #-A-1,B           ; MASK APPLIED TO A AND B
.ENDM
	.MACRO	WAITTY		; WAIT FOR HIM TO TYPE SOMETHING
	TST	@#TKB		; JUNK WHATS THERE ALREADY
	TSTB	@#TKS		; DID HE TYPE ANYTHING YET?
	BPL	.-4		; NOT YET!!
	.ENDM			; YUP - SO GO ON WITH THE SHOW.



START:  RESET                      ; CLEAR THE WORLD
	MOV #6,@#4
	CLR @#6
	MOV #12,@#10
	CLR @#12                     ; SET UP TRAP VECTORS
	MOV #START,SP		; SET UP THE STACK FIRST
        JSR PC,MESSAG              ; GO PRINT INSTRUCTIONS
        WAITTY                          ; GIVE HIM A CHANCE TO GET READY
        MOV #340,PS                 ; LOCKOUT PI BY RAISING CPU PRI
        MOV #101101,R0             ; REVERSE END ZONE=55
        MOV #-4096.,R4             ;COUNTER FOR REZ
        MOV #13,@TCCM              ; GO!!
LP1:    JSR PC,FLAG                ; WAIT FOR READY OR ERROR
        MOV R0,@TCDT               ; LOAD MARK TRACK
        INC R4                     ; DONE ALL?
        BNE LP1                   ; LOOP IF NOT FINISHED
        MOV #-199.,R4             ; COUNTER FOR IBS
        MOV #10101,R0             ; INTERBLOCK SYNC=25
LP2: JSR PC,FLAG               ;WAIT FOR FLAG
        MOV R0,@TCDT              ;LOAD MARK CODE
        INC R4                    ;DONE ALL?
        BNE  LP2                  ;IF NOT , KEEP LOADING
        MOV #-578.,R3             ;COUNTER FOR NUMBER OF BLOCKS
LP3:    JSR PC,FRMBLK             ;WRITE DODES FOR ONE BLOCK
        INC R3                    ;DONE ALL?
        BNE LP3                   ;IF NOT, WRITE ANOTHER BLOCK
        MOV #-199.,R4             ;COUNTER FOR IBS
         MOV #10101,R0            ;INTERBLOCK SYNC=25
LP4:    JSR PC,FLAG               ;WAIT FOR FLAG
        MOV R0,@TCDT            ;LOAD MARK CODE
        INC R4                  ;DONE ALL
        BNE LP4                 ;IF NOT, KEEP WRITING IBS
        MOV #-4096.,R4          ;COUNTER FOR FEZ
       MOV #10010,R0            ;FORWARD END ZONE=22
LP5:   JSR PC,FLAG              ;WAIT FOR FLAG
       MOV R0,@TCDT             ;LOAD MARK CODE
       INC R4                   ;DONE ALL?
       BNE LP5                  ;IF NOT KEEP WRITING FEZ
       JSR PC,FLAG              ;WAIT FOR LAST FLAG
       CLR @TCCM                ;STOP TAPE.  MARK + TIMING TRACKS ARE
HLT1:  JSR PC,MESS2              ;WRITTEN.  RESET WRTM SWITCH AND
       WAITTY                        ; HALT.
       JMP WRTBNO                ;SET WALL SWITCH THEN CONTINUE
FRMBLK: MOV #-266.,R4            ;COUNTER FOR 1 BLOCK'S WORTH OF MKTRACK
        MOV #BLKMRK,R0           ;POINTER FO MARK CODE TABLE
LP6:    JSR PC,FLAG             ;WAIT FOR FLAG
        MOV (R0),@TCDT          ;FETCH MARK CODE
        ADD #2,R0               ;ADVANCE POINTER
        INC R4                  ;DONE ALL?
        BNE LP6                 ;IF NOT FETCH ANOTHER CODE
        RTS PC                  ;IF SO, EXIT
WRTBNO: JSR PC,COBLKG           ;GENERATE TABLE OF CMPOBV BLK NUMBERS
        MOV #-3,R0              ;THREE BLOCKS
        MOV #4002,@TCCM         ;SEARCH REVERSE
WLP1:   INCB @TCCM              ;GO
        JSR PC,FLAG             ;WAIT FOR BLOCK NUMBER
        INC R0                  ;FOUND THREE?
        BNE WLP1                ;IF NOT KEEP SEARCHING
        MOV #76677,R0           ;COMPLEMENT OBVERSE OF 1011(LAST BLOCK#)
        MOV #17,@TCCM           ;WRITE ALL FORWARD
        JSR PC,FLAG             ;WAIT TO SYNC UP FOR WRITING
WLP2:   BISB #3,@TCST           ;SET XDA BITS FOR 0 REVERSE
        MOV R0,@TCDT            ;WRITE LAST BLOCK  FROM HERE TO END ZONE
        JSR PC,FLAG1            ;SKIP NEXT INSTRUCTION IF END ZONE 
        BR WLP2                 ;KEEP WRITING 1011
        MOV #1101,FBLK          ;INITIALIZE PARAMETERS FOR LAST BLOCK,
        MOV #BYST,R5            ;XDA BIT TABLE AND
        MOV #RBN,R3             ;TABLE OF REVERSE BLOCK NUMBERS
        MOV #4017,@TCCM         ;WRITE ALL REVERSE
WALUP:  DEC FBLK                ;DECREMENT BLOCK NUMBER
        CMP #-2,FBLK            ;LAST BLOCK WRITTEN?
        BEQ CHECK               ;YES-CHECK DATA AND BLOCK NUMBERS
        MOV #-1,R4              ;-1 REVERSE =0 FWD
        MOV #-260.,TOG1         ;NUMBER OF WORDS
WLP3:   JSR PC,FLAG             ;WAIT FOR SYNC FLAG TO WRITE
        BISB #3,@TCST            ;1 KBV=0 FWD
        MOV R4,@TCDT             ;LOAD DATA WORD
        INC TOG1                 ;WRITE IF 260 TIMES
        BNE WLP3                ;KEEP WRITING KUNTIL FINISHED
        JSR PC,FLAG             ;WAIT FOR FLAG BEFORE WRITING FWD BLK#
        MOVB (R5)+,@TCST        ;FETCH RELEVANT XDA BITS
        MOV (R3),@TCDT          ;FETCH RELEVANT COMP.OBV.BLK#
        ADD #2,R3               ;ADVANCE TABLE POINTER
        CMP R5,#BYST+10         ;SEE IF XDA BIT TABLE IS EXHAUSTED
        BNE .+6                 ;IF NOT, PROCEED
        MOV #BYST,R5            ;IF SO, REINITIALIZE POINTER
        MOV #WALBF,R4           ;SETUP POINTER FOR LAST FIVE WORDS.
        MOV #-5,TOG1            ;COUNT OF FIVE
WLP4:   JSR PC,FLAG             ;WAIT FOR REQUEST FLAG
        BISB #3,@TCST           ;SET XDA 17&16
        MOV (R4),@TCDT          ;FETCH DATA WORD
        ADD #2,R4               ;ADVANCE POINTER
        INC TOG1                ;ADVANCE COUNTER
        BNE WLP4                ;KEEP WRITING UNTIL FINISHED
        BR WALUP                ;FINISHED-DO NEXT BLOCK
CHECK:  JSR PC,FLAG             ;TAPE IS FORMATTED, CHAECK DATA
        MOVB #3,@TCCM             ;REWIND INTO END ZONE
CHKL1:  JSR PC,FLAG1              ;SKIP NEXT INSTRUCTION IF EZ
        BR CHECK+4                ;KEEP REWINDING
        CLR @TCCM                 ;STOP TAPE
        CLR TOG2                  ;START WITH BLOCK#0
CHKL2:     MOVB #3,@TCCM          ;SEARCH FWD
        JSR PC,FLAG               ;WAIT FOR FLAG
        CMP TOG2,@TCDT            ;IS FWD BLOCK NUMBER CORRECT?
        BEQ DATCHK                ;YES-CHECK DATA
        MOV @TCDT,R0              ;NO-PUT INCORRECT BLK# IN R0 FOR SHOW
        CLR @TCCM                 ;STOP TAPE AND
EHLT2:  HALT                      ;HALT WITH BAD FWD BLK IN LIGHTS, 
        MOV TOG2,R0             ;CONTINUE TO FIND CORRECT BLOCK#
EHLT3:  HALT                     ;HALT WITH CORRECT FWD BLK# IN LIGHTS
        MOV #4003,@TCCM          ;TRY AGAIN
DATCHK: MOV #-257.,TOG1         ;CHECK REV. CHKSUM AND DATA
        MOVB #7,@TCCM           ;READ ALL
DCHKL1: JSR PC,FLAG             ; WAIT FOR WORD
        TST @TCDT                ;IT SHOULD=0
        BEQ DATOK                 ;IF SO, PROCEED
        CLR @TCCM                 ;IF NOT, STOP TAPE,
        MOV TOG2,R0            ; FETCH BLK# AND
EHLT4:  HALT                   ; HALT WITH BLK# IN LITES. CONT.
        MOV #257.,R0           ; TO FIND DATA WORD POSITION
        ADD TOG1,R0            ; DETERMINE WHICH WORD IS WRONG
EHLT5:  HALT                   ; HALT WITH #OF WORD IN LITES. 0=REV. CHK
        MOV @TCDT,R0           ; 'CONT' TO FETCH BAD WORD
EHLT6:  HALT                   ; HALT WITH BAD DATA IN LITES
        MOV #4003,@TCCM        ; 'CONT' TO TRY AGAIN.
        BR CHKL1               ; RESTART CHECK
DATOK:  INC TOG1               ; CHECK ALL DATA IN BLOCK
        BNE DCHKL1             ; KEEP CHECKING TIL DONE
        INC TOG2               ; SET UP FOR NEXT BLOCK
        CMP #1102,TOG2         ; HAVE ALL BLOCKS BEEN CHECKED?
        BNE CHKL2              ; IF NOT KEEP CHECKING
RCHK:   MOVB #3,@TCCM          ; YES-- FIND FWD EZ
        JSR PC,FLAG1           ; SKIP ON EZ
EHLT7:  HALT                   ;1101 SHOULD BE LAST BLOCK #
        MOV #1101,TOG2         ; FIRST REVERSE BLK=1101
RERCV:  MOV #4000,@TCCM        ; SET TAPE TO REVERSE
        MOV #DATBUF,R0         ; INITIALIZE DATA BUFFER POINTER
ZLUP:   CLR (R0)               ; ZERO DATA WORD
        ADD #2,R0              ; ADVANCE POINTER
        CMP R0,#DATBUF+512.    ; IS BUFFER FILLED?
        BNE ZLUP               ; IF NOT, KEEP CLEARING
CHKL3:  MOVB #3,@TCCM          ;SEARCH REVERSE AND
           JSR PC,FLAG            ; WAIT FOR FLAG
        CMP TOG2,@TCDT         ; IS REVERSE BLK# CORRECT?
        BEQ WRTDTA             ; YES-- WRITE DATA
        MOV @TCDT,R0           ; NO-PUT INCORRECT BLK# IN R0
        CLR @TCCM              ; STOP TAPE AND
EHLT10: HALT                   ; HALT WITH BAD REVERSE BLK# IN LITES.
        MOV TOG2,R0            ; 'CONT' TO FIND CORRECT BLK#
EHLT11: HALT                  ;HALT WITH CORRECT REV BLK# IN LITES.
        MOVB #3,@TCCM          ; 'CONT' TO TRY PASS AGAIN
        JSR PC,FLAG1           ; FIND FWD EZ AND
        BR EHLT11+2            ; RESTART REVERSE
        BR RERCV               ; CHECK PASS
WRTDTA: MOV #-400,@TCWC        ; WC FOR 1 BLOCK OF DATA
        MOV #DATBUF,@TCBA      ; CA INITIALIZATION
        MOVB #15,@TCCM         ; WRITE DATA TO MAKE PARITY OK
        JSR PC,FLAG            ; WAIT FOR COMPLETION OR ERROR
        DEC TOG2               ; DECREMENT BLOCK NUMBER
        BPL CHKL3              ; IF <0 FINISH UP
FINIS:  MOVB #3,@TCCM         ; FIND REVERSE EZ
        JSR PC,FLAG1           ; SKIP ON EZ
        HALT                   ; 0 SHOULD HAVE BEEN LAST BLOCK# IN REV.
        CLR @TCCM              ; STOP TAPE AND
        JSR PC,MESS3           ; PRINT MESSAGE, THEN
        JMP START              ; START OVER.  ALL FINISHED
FLAG1:  BIT #100200,@TCCM      ; TEST ERROR AND READY BITS
        BEQ FLAG1              ; WAIT FOR EITHER FLAG
        BMI .+4                ; IF ERROR CHECK FURTHER
        RTS PC                 ; IF READY-- EXIT
        TST @TCST              ; IS ERROR EZ?
        BMI .+6                ; YES -- SKIP
        JMP FLAG               ; NO -- GOTO REGULAR ERROR HALT
        ADD #2,(SP)            ; INCREMENT EXIT POINTER TO SKIP
        RTS PC                 ; EXIT
COBLKG: MOV #1101,R0           ; COMPLEMENT OBVERSE BLOCKS 1101-0
        MOV #RBN,R1            ; BUFFER POINTER INITIALIZATION
CBKL1:  MOV R0,R2              ; FETCH WORD TO BE PROCESSED
        COM R2                 ; COMPLEMENT IT
        MOV #-3,TOG1           ; COUNT OF 3
        MOV R2,R3              ; MOVE WORD INTO WORK AREA
        ROR R2                 ; SHIFT NEXT 3 BITS INTO POSITION
        ROR R2                 ; FOR MANIPULATION
        ROR R2                 ; ON NEXT PASS
        AND 1,R3
        MOV R3,-(SP)           ; STACK IT
CBKL2:  MOV R2,R3              ; MOV BYTE(3) INTO WORK AREA
        ROR R2                 ; SHIFT NEXT 3 BYTES
        ROR R2                 ; INTO
        ROR R2                 ; POSITION
        AND 7,R3
        MOV R3,-(SP)           ; STACK BYTE
        INC TOG1               ; DONE ALL?
        BNE CBKL2              ; NO
        CLR R3                 ; YES -- CLEAR WORK AREA
        ADD 6(SP),R3           ; ADD AND
        JSR R5,RTHL            ; SHIFT BYTES IN REVERSE ORDER
        ADD 4(SP),R3           ; NEXT BYTE
        JSR R5,RTHL            ; SHIFT
        ADD 2(SP),R3           ; NEXT BYTE
        JSR R5,RTHL            ; SHIFT
        ADD (SP),R3
        JSR R5,RTHL            ; SHIFT
        JSR R5,RTHL            ; HIKE
        ADD #77,R3             ; =00 FWD
        MOV R3,(R1)            ;STORE COMP.ORV. BLK IN TAB
        ADD #10,SP             ; ADVANCE STACK
        ADD #2,R1              ; ADVANCE TABLE POINTER
        DEC R0                 ; DECREMENT BLK#
        BPL CBKL1              ; LOOP TIL IT PASSES 0
        RTS PC                 ; THEN EXIT
RTHL:   CLC                    ; THREE BIT LEFT SHIFT.  CLEAR CARRY
        ROL R3                 ; SHIFT 1
        ROL R3                 ;       2
        ROL R3                 ;       3
        RTS R5                 ; THEN EXIT
WALBF:  .WORD -1               ;-1 REVERSE, 0 FWD
        .WORD -1
FBLK:   .WORD 1101             ; BLK# GOES HERE
        .WORD -1
        .WORD -1
BYST:   .BYTE 3                ; TABLE OF XDA FOR COM.OBV.
        .BYTE 3
        .BYTE 0
        .BYTE 0
        .BYTE 1
        .BYTE 1
        .BYTE 2
        .BYTE 2
FLAG:   BIT #100200,@TCCM      ; TEST READY AND ERROR BITS
        BEQ FLAG               ; TEST UNTIL ONE IS SET
        BMI .+4                ; SKIP TO ERROR IF B15
        RTS PC                 ; ELSE EXIT
        MOV @TCST,R0           ; MOVE STATUS TO R0
EHLT1:  HALT                   ; ERROR HALT!!
        BR EHLT1               ; RESTART PROGRAM!!
BLKMRK: .WORD 010101           ; INTERBLOCK SYNC=25
        .WORD 010110            ; FWD BLOCK MARK=26
        .WORD 011010            ; REVERSE GUARD=32
        .WORD 001000            ; LOCK=10
        .WORD 001000            ; REVERSE PARITY=10
        .WORD 001000            ; REVERSE FINAL=10
        .WORD 001000            ; REVERSE PRE-FINAL=10

        .REPT 374
        .WORD 111000            ; MARK DATA =70
        .ENDR

        .WORD 111011            ; PRE-FINAL=73
         .WORD 111011            ;FINAL=73
        .WORD 111011            ;PARITY=73
        .WORD 111011            ; REVERSE LOCK=73
        .WORD 101001            ;GUARD=51
        .WORD 100101            ;REVERSE BLK MARK=45
        .WORD 010101            ; INTERBLOCK SYNC=25
TOG2:   HALT
TOG1:   HALT
TCCM:   177342
TCST:   177340
TCDT:   177350
TCBA:   177346
TCWC:   177344

RBN:    .=.+2204

DATBUF: .=.+1000
MESSAG: MOV #HELLO,SAVE        ; 1'ST ENTRY POINT FOR PRINT
        BR PRINT
MESS2:  MOV #MESSA,SAVE        ; 2'ND ENTRY POINT
        BR PRINT
MESS3:  MOV #MESSB,SAVE        ; 3'RD ENTRY POINT
PRINT:  MOV R0,-(SP)           ; SAVE R0
        MOV SAVE,R0            ; USE R0 FOR OUR WORK
        TSTB TPS               ; TEST FOR PRINTER READY
        BPL .-4               ; WAIT FOR IT
PRINT1: MOVB (R0)+,TPB         ; PRINT MESSAGE ONE AT A TIME
        TSTB TPS               ; WAIT FOR PRINTER READY
        BPL .-4                ; WAITING
        CMPB #5,@R0           ; IS THIS THE END OF MESSAGE?
        BNE PRINT1             ; NO, CONTINUE
        MOV (SP)+,R0           ;YES, RESTORE R0
        RTS PC                  ; RETUURN
SAVE:   HALT
HELLO:  .BYTE CR,0,0,0,0,0,LF
        .ASCII "TAPFOR V1A/L1 -- DECTAPE FORMATTER -- LAWRENCE"
        .BYTE CR,0,0,0,0,0
        .BYTE LF
       .ASCII "MOUNT TAPE ON DT0:  SET DRIVE TO REMOTE AND WRITE ENABLE"
        .BYTE CR,0,0,0,0,0
        .BYTE LF
      .ASCII "SET WRTM AND WALL SWITCHES TO ENABLE (UP).  TYPE ANY"
	.ASCII "CHARACTER WHEN READY."
        .BYTE CR,0,0,0,0,0
        .BYTE LF
        .BYTE 5
MESSA:  .ASCII "RESET WRTM SWITCH (DOWN), LEAVE WALL UP.  HIT ANY"
	.ASCII "KEY WHEN READY."
        .BYTE CR,0,0,0,0,0
        .BYTE LF
        .BYTE 5
MESSB:  .ASCII "TAPE FORMATTING COMPLETE!"
        .BYTE CR,0,0,0,0,0
        .BYTE LF
        .BYTE 5
          .END START             ; THAT'S ALL FOLKS
