.TITLE CRUCRB .IDENT /X01.00/ ; ; Author: Gilbert J. DeLeeuw ; Date: May 3, 1984 ; Name: CRUCRB - Compress record buffer ; Function: Compress a record ; ; Algorithm: Data file compression uses imbedded control bytes which ; contain a character count and bit flag which indicates ; whether the byte following is repeated, or whether the ; byte(s) following are data values. Any time there are ; three or more successive identical bytes in the uncompressed ; record, they are converted to a control byte plus one byte ; to contain the value. ; ; ; Parameters: ; ; R1 - Compress parameter ; R2 - Size of input record ; R3 - Address of input record ; R4 - Size of work buffer ; R5 - Address of work buffer ; ; Output ; R2 - Size of output record ; R3 - Address of output record ; ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = CRUCRB:: TST R2 ;LENGTH OF INPUT BUFFER BLE 99$ ;ZERO LENGTH RECORD ; ; Set up stack MOV R5,-(SP) ;SAVE STARTING ADDRESS CLR -(SP) ;ALLOCATE SPACE ON STACK ; ; Set up registers CALL NXTR ;SET UP REGISTERS 0 AND 5 CLR R4 ;INITIALIZE BUFFER LENGTH ; ; See if there is a fixed area in beginning of record TST R1 ;Test size of initial segment BLE 25$ ;No initial uncompr segment ; ; Move characters into output buffer 10$: MOVB (R3)+,(R5)+ ;MOVE A CHARACTER ; ; Test if new segment needed DEC R0 ;DECREMENT SEGMENT SPACE BGT 15$ ;BRANCH IF OK CALL NXTS ;NEXT SEGMENT ; ; Update input counter 15$: DEC R2 ;SUBTRACT FROM COUNTER BLE 70$ ;NO MORE INPUT CHARACTERS ; ; End of loop SOB R1,10$ ;LOOP UNTIL 70$ BR 25$ ;ALREADY SET UP FOR CHARACTERS ; ; Character segment 20$: DEC R3 ;BACK UP TO NON-MATCHING CHARACTER 21$: CALL NXTS ;INITIALIZE FOR NEXT SEGMENT ; ; Character loop 25$: MOVB (R3)+,R1 ;MOVE CHARACTER TO REGISTER ; ; Check to see if we should switch to repeat segment CMP #3,R2 ;MUST BE 3 OR MORE CHARACTERS LEFT BGT 30$ ;NO TEST IF LESS THAN 3 CMPB (R3),R1 ;COMPARE NEXT CHARACTER TO CURRENT BNE 30$ ;IF NOT EQUAL, CONTINUE THIS MODE CMPB 1(R3),R1 ;COMPARE NEXT CHARACTER TO CURRENT BEQ 45$ ;SWITCH TO REPEAT MODE ; ; Move in the character 30$: MOVB R1,(R5)+ ;MOVE CHARACTER TO OUTPUT ; ; Test if new segment needed DEC R0 ;DECREMENT SEGMENT SPACE BGT 40$ ;BRANCH IF OK 35$: CALL NXTS ;NEXT SEGMENT ; End of loop 40$: SOB R2,25$ ;DECREMENT INPUT COUNT BR 70$ ; ; ; Set up for repeat mode 45$: CALL NXTS ;NEXT SEGMENT BISB #200,@(SP) ;SET REPEAT FLAG IN OUTPUT BUFFER ; ; First character in R1 MOVB R1,(R5)+ ;REPEAT CHARACTER DEC R0 ;DECREMENT SEGMENT SPACE DEC R2 ;DECREMENT INPUT COUNTER ; ; Test next character 50$: CMPB (R3)+,R1 ;COMPARE CHARACTER BNE 20$ ;SWITCH TO CHARACTER MODE ; ; Update counters DEC R0 ;DECREMENT SEGMENT SPACE BLE 35$ ;BRANCH IF MAX ; ; End of loop 55$: SOB R2,50$ ;DECREMENT INPUT COUNT ; ; Finish up last segment 70$: CALL NXTS ;LAST SEGMENT ; ; Return length of output line TST (SP)+ ;CLEAR CARRY & POP STACK MOV R4,R2 ;OUTPUT SIZE MOV (SP)+,R3 ;OUTPUT ADDRESS 99$: RTS PC ;AND BACK TO CALLER ; ; Subroutine to set up registers for next segment NXTS: NEG R0 ;OUTPUT COUNT IS 127.-R0 ADD #127.,R0 ;ADD STARTING POINT BEQ NXTE ;JUST NEED TO SET R0 ; ; Store count in control register BISB R0,@2(SP) ;STORE COUNT BGT NXTA ;REPEAT MODE WILL BE NEGATIVE MOV #1,R0 ;REPEAT MODE USES 1 BYTE ; ; Keep track of number of bytes output NXTA: INC R4 ;INCREMENT OUTPUT COUNT ADD R0,R4 ;ADD TO OUTPUT COUNT ; ; Set up registers for next segment NXTR: MOV R5,2(SP) ;COPY ADDRESS CLRB (R5)+ ;INITIALIZE CONTROL BYTE NXTE: MOV #127.,R0 ;INITIALIZE OUTPUT COUNT RTS PC .END