.TITLE COMPRESS - Compress Input Record .IDENT /1.0/ .ENABL LC ;+ ; ; Free software BY ; Project Software & Development, Inc. ; ; This software is furnished for free and may be used and copied as ; desired. This software or any other copies thereof may be provided or ; otherwise made available to any other person. No title to and ; ownership of the software is hereby transferred or allowed. ; ; The information in this software is subject to change without notice ; and should not be construed as a commitment by PROJECT SOFTWARE ; AND DEVELOPMENT, INC. ; ; PROJECT SOFTWARE assumes no responsibility for the use or reliability ; of this software on any equipment whatsoever. ; ; Project Software & Development, Inc. ; 14 Story St. ; Cambridge, Ma. 02138 ; 617-661-1444 ; ; ; Title: COMPRESS.MAC ; Author: Robin Miller ; Date: October 18, 1982 ; ; Description: ; ; These routines compress an input record into the String Control ; Bytes (SCB's) necessary for the HASP protocol. ; ; ; Modification History: ; ;- .ENABL AMA .NLIST BEX .SBTTL Format Of The String Control Byte (SCB) ;+ ; ; The format of the String Contol Byte (SCB) is: ; ; 80 40 20 10 8 4 2 1 (Hex) ; 7 6 5 4 3 2 1 0 ; --------------------------------- ; ! O ! K ! L ! J ! J ! J ! J ! J ! ; --------------------------------- ; ! ! ! ! ! ! ! ! ; ! !------------------------ ; ! K = 0 = Duplicate Character String: ; ! L = 0 = Duplicate Character is blank. ; ! L = 1 = Duplicate character is nonblank (and follows SCB). ; ! JJJJJ = Duplication count. ; ! ; ! K = 1 = Nonduplicate Character String. ; ! LJJJJJ = Character string length. ; ! ; !-> O = 0 = End of record (K L J J J J J = 0) ; O = 1 = All other SCB's. ; ; A String Control Byte with just bit 7 set means the record is ; continued in the next block. ; ;- ; String Control Byte bit definitions: B.MBON = 200 ; Must be on bit. B.NDUP = 100 ; Non-duplicate character string. B.NBLA = 40 ; Duplicate character is non-blank. ; Local Equates: SPACE = 40 ; ASCII for SPACE. MAXDUP = 37 ; Maximum duplicate count. MAXCNT = 77 ; Maximum non-duplicate count. BUFSIZ = 400. ; Maximum size of transmit buffer. BUFSAV = 7 ; Number of bytes to save at the. ; end of the buffer for protocol: ; SCB RCB DLE ETB BCC BCC BUFEND = BUFSIZ-BUFSAV ; End of the transmit buffer. ; Offsets for argument block: O.RADR = 2 ; Address of the input record. O.RLEN = 4 ; Address of the record length. O.BADR = 6 ; Address of the transmit buffer. O.BLEN = 10 ; Address of the transmit length. O.MAX = 12 ; Address of the maximum buffer. O.STAT = 14 ; Address to return the status. ; Local storage: SCBADR: .WORD 0 ; Address of the last SCB. .SBTTL COMPRESS - Compress Record Into A Transmit Buffer ;+ ; ; COMPRESS - Compress record into a transmit buffer. ; ; This routine compresses the input record into the appropriate String ; Control Bytes (SCB's) and appends them to the transmit buffer. ; ; Inputs: ; R5 = Pointer to argument block (Fortran convention): ; ; Argument block format: ; ; .BYTE 6,0 ; Argument count. ; .WORD recadr ; Address of the input record. ; .WORD reclen ; Address of input record length. ; .WORD bufadr ; Address of the transmit buffer. ; .WORD buflen ; Address of transmit buffer length. ; .WORD maxsiz ; Address of maximum size of buffer. ; .WORD status ; Address for return status. ; ; recadr: .BLKB recsiz ; Storage for input record. ; reclen: .WORD 0 ; The input record length. ; bufadr: .BLKB bufsiz ; Storage for the transmit buffer. ; buflen: .WORD 0 ; Current transmit buffer length. ; maxsiz: .WORD bufend ; Maximum size of transmit buffer. ; status: .WORD 0 ; Return status goes here. ; ; Outputs: ; Return status, 0/1 = buffer full/not full. ; The updated record address and length and the updated ; output buffer address and length are passed back. ; ;- COMPRESS:: CALL $SAVAL ; Save all registers. MOV O.RADR(R5),R0 ; Copy the record address. MOV @O.RLEN(R5),R1 ; Copy the record length. MOV O.BADR(R5),R2 ; Copy the transmit buffer address. MOV @O.BLEN(R5),R3 ; Copy the current buffer length. ; CLR R4 ; Initialize the SCB length. ; Make the initial SCB (default = non-duplicate string). 10$: CALL MAKSCB ; Make the initial SCB. 20$: TST R1 ; End of the input record ? BEQ 100$ ; If EQ, yes (end of record) CALL CHKEND ; Check for end of transmit buffer. BCS 100$ ; If CS, end of buffer. CLR -(SP) ; Allocate space on the stack. MOVB (R0)+,(SP) ; Copy the next input character. DEC R1 ; Adjust the input record length. BEQ 30$ ; If EQ, non-duplicate character. CMPB (R0),(SP) ; Is this a duplicate character ? BEQ 40$ ; If EQ, yes ; Non-duplicate character string. 30$: MOVB (SP)+,(R2)+ ; Copy character to transmit buffer. INC R3 ; Adjust the tranmit buffer length. INC R4 ; Adjust the SCB length. CMP R4,#MAXCNT ; At maximum non-duplicate count. BLO 20$ ; If LO, no (do the next character) CALL FINSCB ; Fill in the SCB length. BR 10$ ; And make the next SCB. ; Duplicate character string. 40$: CALL FINSCB ; Finish the current SCB (if any). BCS 50$ ; If CS, there was no SCB to finish. CALL MAKSCB ; Else, make the next SCB. 50$: BICB #B.NDUP,@SCBADR ; Convert SCB to duplicate string. INC R4 ; Adjust SCB length (for above). ; Calculate the duplicate character string length. 60$: CMPB (R0),(SP) ; Another duplicate character ? BNE 70$ ; If NE, no (finished) INC R0 ; Adjust the record buffer address. INC R4 ; Adjust the SCB length. DEC R1 ; Adjust the input record length. BEQ 70$ ; If EQ, at end of record. CMP R4,#MAXDUP ; At maximum duplication count ? BLO 60$ ; If LO, no (still have room) ; End of string or end of duplicate string. 70$: BISB R4,@SCBADR ; Fill in the SCB length. MOVB (SP)+,(R2) ; Copy the duplicate character. CMPB (R2),#SPACE ; Was duplicate character a space ? BEQ 10$ ; If EQ, yes (make the next SCB) ; Duplicate character was non-blank. 80$: INC R2 ; Adjust the buffer address. INC R3 ; and the buffer length. BISB #B.NBLA,@SCBADR ; Show non-blank duplicate character. BR 10$ ; And make the next SCB. ; Finished with this record or the output buffer is full. 100$: CALL FINSCB ; Finish the current SCB (if any). BCS 110$ ; If CS, there was no SCB finished. CALL MAKSCB ; Else, make the next SCB. ; Generate a continuation or end of record SCB. 110$: CLRB @SCBADR ; Presume end of record SCB. TST R1 ; Did we finish the input record ? BEQ 120$ ; If EQ, yes MOVB #B.MBON,@SCBADR ; No, generate a continuation SCB. 120$: MOV R0,O.RADR(R5) ; Pass back the updated record address MOV R1,@O.RLEN(R5) ; and the updated record length. MOV R2,O.BADR(R5) ; Pass back the updated buffer address. MOV R3,@O.BLEN(R5) ; and the updated buffer length. ; Pass back the appropriate status. CLR @O.STAT(R5) ; Presume output buffer is full. CALL CHKEND ; Did we presume right ? BCS 130$ ; If CS, yes MOV #1,@O.STAT(R5) ; Else, show it is not full. 130$: RETURN .SBTTL CHKEND - Check For End Of Transmit Buffer. ;+ ; ; CHKEND - Check for end of transmit buffer. ; ; Inputs: ; R5 = the address of the argument block. ; R3 = the current transmit buffer length. ; ; Outputs: ; C bit clear/set = not at end/ at end of buffer. ; ; All registers are preserved. ; ;- CHKEND::CMP R3,@O.MAX(R5) ; At end of transmit block ? BHIS 90$ ; If HIS, yes. CLC ; Show not at end of buffer. BR 100$ ; Use common return ... 90$: SEC ; Show at end of buffer. 100$: RETURN .SBTTL FINSCB - Finish The Current SCB. ;+ ; ; FINSCB - Finish the current SCB (if there is one). ; ; This routine fills in the current SCB length (if any). ; ; Inputs: ; SCBADR = the current SCB address. ; R4 = the SCB length (zero if none). ; ; Outputs: ; C bit clear/set = SCB finished / SCB not finished. ; On success, ; the length is filled in the SCB. ; ;- FINSCB::TST R4 ; Is there an SCB length ? BEQ 90$ ; If EQ, no (C bit cleared by TST) BISB R4,@SCBADR ; Yes, fill in the SCB length. BR 100$ ; And use common return ... 90$: SEC ; Show the SCB wasn't finished. 100$: RETURN .SBTTL MAKSCB - Make The Initial SCB ;+ ; ; MAKSCB - Make the initial SCB. ; ; The routine inserts the initial SCB into the transmit buffer. The SCB ; is initialized to a non-duplicate character string. ; ; Inputs: ; R2 = the transmit buffer address. ; R3 = the current transmit buffer length. ; ; Outputs: ; R2 = the updated transmit buffer address. ; R3 = the updated transmit buffer length. ; R4 = the SCB length is initialized to zero. ; ; C bit clear/set = not at end/ at end of buffer. ; ;- MAKSCB::MOV R2,SCBADR ; Save this SCB address. MOVB #B.MBON!B.NDUP,(R2)+ ; Initialize to non-duplicate SCB. INC R3 ; Update the transmit buffer length. CLR R4 ; Initialize the SCB length to zero. CALL CHKEND ; Check for end of output buffer. RETURN .END