mirror of
https://github.com/emmanuel-marty/lzsa.git
synced 2025-01-20 10:30:51 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
e7bb1faece
@ -7,6 +7,18 @@
|
|||||||
;
|
;
|
||||||
; out:
|
; out:
|
||||||
; * LZSA_DST_LO and LZSA_DST_HI contain the last decompressed byte address, +1
|
; * LZSA_DST_LO and LZSA_DST_HI contain the last decompressed byte address, +1
|
||||||
|
;
|
||||||
|
; -----------------------------------------------------------------------------
|
||||||
|
; Backward decompression is also supported, use lzsa -r -b <original_file> <compressed_file>
|
||||||
|
; To use it, also define BACKWARD_DECOMPRESS=1 before including this code!
|
||||||
|
;
|
||||||
|
; in:
|
||||||
|
; * LZSA_SRC_LO/LZSA_SRC_HI must contain the address of the last byte of compressed data
|
||||||
|
; * LZSA_DST_LO/LZSA_DST_HI must contain the address of the last byte of the destination buffer
|
||||||
|
;
|
||||||
|
; out:
|
||||||
|
; * LZSA_DST_LO/LZSA_DST_HI contain the last decompressed byte address, -1
|
||||||
|
;
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
;
|
;
|
||||||
; Copyright (C) 2019 Emmanuel Marty
|
; Copyright (C) 2019 Emmanuel Marty
|
||||||
@ -37,10 +49,10 @@ DECODE_TOKEN
|
|||||||
|
|
||||||
AND #$70 ; isolate literals count
|
AND #$70 ; isolate literals count
|
||||||
BEQ NO_LITERALS ; skip if no literals to copy
|
BEQ NO_LITERALS ; skip if no literals to copy
|
||||||
LSR A ; shift literals count into place
|
LSR ; shift literals count into place
|
||||||
LSR A
|
LSR
|
||||||
LSR A
|
LSR
|
||||||
LSR A
|
LSR
|
||||||
CMP #$07 ; LITERALS_RUN_LEN?
|
CMP #$07 ; LITERALS_RUN_LEN?
|
||||||
BCC PREPARE_COPY_LITERALS ; if not, count is directly embedded in token
|
BCC PREPARE_COPY_LITERALS ; if not, count is directly embedded in token
|
||||||
|
|
||||||
@ -59,7 +71,8 @@ LARGE_VARLEN_LITERALS ; handle 16 bits literals count
|
|||||||
; literals count = directly these 16 bits
|
; literals count = directly these 16 bits
|
||||||
JSR GETLARGESRC ; grab low 8 bits in X, high 8 bits in A
|
JSR GETLARGESRC ; grab low 8 bits in X, high 8 bits in A
|
||||||
TAY ; put high 8 bits in Y
|
TAY ; put high 8 bits in Y
|
||||||
BYTE $A9 ; mask TAX (faster than BCS)
|
TXA
|
||||||
|
|
||||||
PREPARE_COPY_LITERALS
|
PREPARE_COPY_LITERALS
|
||||||
TAX
|
TAX
|
||||||
BEQ COPY_LITERALS
|
BEQ COPY_LITERALS
|
||||||
@ -79,7 +92,7 @@ NO_LITERALS
|
|||||||
|
|
||||||
JSR GETSRC ; get 8 bit offset from stream in A
|
JSR GETSRC ; get 8 bit offset from stream in A
|
||||||
TAX ; save for later
|
TAX ; save for later
|
||||||
LDA #$0FF ; high 8 bits
|
LDA #$FF ; high 8 bits
|
||||||
BNE GOT_OFFSET ; go prepare match
|
BNE GOT_OFFSET ; go prepare match
|
||||||
; (*like JMP GOT_OFFSET but shorter)
|
; (*like JMP GOT_OFFSET but shorter)
|
||||||
|
|
||||||
@ -96,11 +109,29 @@ PREPARE_COPY_MATCH_Y
|
|||||||
|
|
||||||
COPY_MATCH_LOOP
|
COPY_MATCH_LOOP
|
||||||
LDA $AAAA ; get one byte of backreference
|
LDA $AAAA ; get one byte of backreference
|
||||||
|
JSR PUTDST ; copy to destination
|
||||||
|
|
||||||
|
!ifdef BACKWARD_DECOMPRESS {
|
||||||
|
|
||||||
|
; Backward decompression -- put backreference bytes backward
|
||||||
|
|
||||||
|
LDA COPY_MATCH_LOOP+1
|
||||||
|
BNE GETMATCH_DONE
|
||||||
|
DEC COPY_MATCH_LOOP+2
|
||||||
|
GETMATCH_DONE
|
||||||
|
DEC COPY_MATCH_LOOP+1
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
; Forward decompression -- put backreference bytes forward
|
||||||
|
|
||||||
INC COPY_MATCH_LOOP+1
|
INC COPY_MATCH_LOOP+1
|
||||||
BNE GETMATCH_DONE
|
BNE GETMATCH_DONE
|
||||||
INC COPY_MATCH_LOOP+2
|
INC COPY_MATCH_LOOP+2
|
||||||
GETMATCH_DONE
|
GETMATCH_DONE
|
||||||
JSR PUTDST ; copy to destination
|
|
||||||
|
}
|
||||||
|
|
||||||
DEX
|
DEX
|
||||||
BNE COPY_MATCH_LOOP
|
BNE COPY_MATCH_LOOP
|
||||||
DEY
|
DEY
|
||||||
@ -111,6 +142,29 @@ GET_LONG_OFFSET ; handle 16 bit offset:
|
|||||||
JSR GETLARGESRC ; grab low 8 bits in X, high 8 bits in A
|
JSR GETLARGESRC ; grab low 8 bits in X, high 8 bits in A
|
||||||
|
|
||||||
GOT_OFFSET
|
GOT_OFFSET
|
||||||
|
|
||||||
|
!ifdef BACKWARD_DECOMPRESS {
|
||||||
|
|
||||||
|
; Backward decompression - substract match offset
|
||||||
|
|
||||||
|
STA OFFSHI ; store high 8 bits of offset
|
||||||
|
STX OFFSLO
|
||||||
|
|
||||||
|
SEC ; substract dest - match offset
|
||||||
|
LDA PUTDST+1
|
||||||
|
OFFSLO = *+1
|
||||||
|
SBC #$AA ; low 8 bits
|
||||||
|
STA COPY_MATCH_LOOP+1 ; store back reference address
|
||||||
|
LDA PUTDST+2
|
||||||
|
OFFSHI = *+1
|
||||||
|
SBC #$AA ; high 8 bits
|
||||||
|
STA COPY_MATCH_LOOP+2 ; store high 8 bits of address
|
||||||
|
SEC
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
; Forward decompression - add match offset
|
||||||
|
|
||||||
STA OFFSHI ; store high 8 bits of offset
|
STA OFFSHI ; store high 8 bits of offset
|
||||||
TXA
|
TXA
|
||||||
|
|
||||||
@ -123,6 +177,8 @@ OFFSHI = *+1
|
|||||||
ADC PUTDST+2
|
ADC PUTDST+2
|
||||||
STA COPY_MATCH_LOOP+2 ; store high 8 bits of address
|
STA COPY_MATCH_LOOP+2 ; store high 8 bits of address
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
PLA ; retrieve token from stack again
|
PLA ; retrieve token from stack again
|
||||||
AND #$0F ; isolate match len (MMMM)
|
AND #$0F ; isolate match len (MMMM)
|
||||||
ADC #$02 ; plus carry which is always set by the high ADC
|
ADC #$02 ; plus carry which is always set by the high ADC
|
||||||
@ -145,6 +201,45 @@ OFFSHI = *+1
|
|||||||
DECOMPRESSION_DONE
|
DECOMPRESSION_DONE
|
||||||
RTS
|
RTS
|
||||||
|
|
||||||
|
!ifdef BACKWARD_DECOMPRESS {
|
||||||
|
|
||||||
|
; Backward decompression -- get and put bytes backward
|
||||||
|
|
||||||
|
GETPUT
|
||||||
|
JSR GETSRC
|
||||||
|
PUTDST
|
||||||
|
LZSA_DST_LO = *+1
|
||||||
|
LZSA_DST_HI = *+2
|
||||||
|
STA $AAAA
|
||||||
|
LDA PUTDST+1
|
||||||
|
BNE PUTDST_DONE
|
||||||
|
DEC PUTDST+2
|
||||||
|
PUTDST_DONE
|
||||||
|
DEC PUTDST+1
|
||||||
|
RTS
|
||||||
|
|
||||||
|
GETLARGESRC
|
||||||
|
JSR GETSRC ; grab low 8 bits
|
||||||
|
TAX ; move to X
|
||||||
|
; fall through grab high 8 bits
|
||||||
|
|
||||||
|
GETSRC
|
||||||
|
LZSA_SRC_LO = *+1
|
||||||
|
LZSA_SRC_HI = *+2
|
||||||
|
LDA $AAAA
|
||||||
|
PHA
|
||||||
|
LDA GETSRC+1
|
||||||
|
BNE GETSRC_DONE
|
||||||
|
DEC GETSRC+2
|
||||||
|
GETSRC_DONE
|
||||||
|
DEC GETSRC+1
|
||||||
|
PLA
|
||||||
|
RTS
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
; Forward decompression -- get and put bytes forward
|
||||||
|
|
||||||
GETPUT
|
GETPUT
|
||||||
JSR GETSRC
|
JSR GETSRC
|
||||||
PUTDST
|
PUTDST
|
||||||
@ -171,3 +266,5 @@ LZSA_SRC_HI = *+2
|
|||||||
INC GETSRC+2
|
INC GETSRC+2
|
||||||
GETSRC_DONE
|
GETSRC_DONE
|
||||||
RTS
|
RTS
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -8,6 +8,18 @@
|
|||||||
;
|
;
|
||||||
; out:
|
; out:
|
||||||
; * LZSA_DST_LO and LZSA_DST_HI contain the last decompressed byte address, +1
|
; * LZSA_DST_LO and LZSA_DST_HI contain the last decompressed byte address, +1
|
||||||
|
;
|
||||||
|
; -----------------------------------------------------------------------------
|
||||||
|
; Backward decompression is also supported, use lzsa -r -b -f2 <original_file> <compressed_file>
|
||||||
|
; To use it, also define BACKWARD_DECOMPRESS=1 before including this code!
|
||||||
|
;
|
||||||
|
; in:
|
||||||
|
; * LZSA_SRC_LO/LZSA_SRC_HI must contain the address of the last byte of compressed data
|
||||||
|
; * LZSA_DST_LO/LZSA_DST_HI must contain the address of the last byte of the destination buffer
|
||||||
|
;
|
||||||
|
; out:
|
||||||
|
; * LZSA_DST_LO/LZSA_DST_HI contain the last decompressed byte address, -1
|
||||||
|
;
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
;
|
;
|
||||||
; Copyright (C) 2019 Emmanuel Marty
|
; Copyright (C) 2019 Emmanuel Marty
|
||||||
@ -41,9 +53,9 @@ DECODE_TOKEN
|
|||||||
|
|
||||||
AND #$18 ; isolate literals count (LL)
|
AND #$18 ; isolate literals count (LL)
|
||||||
BEQ NO_LITERALS ; skip if no literals to copy
|
BEQ NO_LITERALS ; skip if no literals to copy
|
||||||
LSR A ; shift literals count into place
|
LSR ; shift literals count into place
|
||||||
LSR A
|
LSR
|
||||||
LSR A
|
LSR
|
||||||
CMP #$03 ; LITERALS_RUN_LEN_V2?
|
CMP #$03 ; LITERALS_RUN_LEN_V2?
|
||||||
BCC PREPARE_COPY_LITERALS ; if less, count is directly embedded in token
|
BCC PREPARE_COPY_LITERALS ; if less, count is directly embedded in token
|
||||||
|
|
||||||
@ -90,7 +102,7 @@ NO_LITERALS
|
|||||||
|
|
||||||
; 00Z: 5 bit offset
|
; 00Z: 5 bit offset
|
||||||
|
|
||||||
LDX #$0FF ; set offset bits 15-8 to 1
|
LDX #$FF ; set offset bits 15-8 to 1
|
||||||
|
|
||||||
JSR GETCOMBINEDBITS ; rotate Z bit into bit 0, read nibble for bits 4-1
|
JSR GETCOMBINEDBITS ; rotate Z bit into bit 0, read nibble for bits 4-1
|
||||||
ORA #$E0 ; set bits 7-5 to 1
|
ORA #$E0 ; set bits 7-5 to 1
|
||||||
@ -130,6 +142,25 @@ GOT_OFFSET_LO
|
|||||||
STX OFFSHI ; store high byte of match offset
|
STX OFFSHI ; store high byte of match offset
|
||||||
|
|
||||||
REP_MATCH
|
REP_MATCH
|
||||||
|
!ifdef BACKWARD_DECOMPRESS {
|
||||||
|
|
||||||
|
; Backward decompression - substract match offset
|
||||||
|
|
||||||
|
SEC ; add dest + match offset
|
||||||
|
LDA PUTDST+1 ; low 8 bits
|
||||||
|
OFFSLO = *+1
|
||||||
|
SBC #$AA
|
||||||
|
STA COPY_MATCH_LOOP+1 ; store back reference address
|
||||||
|
LDA PUTDST+2
|
||||||
|
OFFSHI = *+1
|
||||||
|
SBC #$AA ; high 8 bits
|
||||||
|
STA COPY_MATCH_LOOP+2 ; store high 8 bits of address
|
||||||
|
SEC
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
; Forward decompression - add match offset
|
||||||
|
|
||||||
CLC ; add dest + match offset
|
CLC ; add dest + match offset
|
||||||
LDA PUTDST+1 ; low 8 bits
|
LDA PUTDST+1 ; low 8 bits
|
||||||
OFFSLO = *+1
|
OFFSLO = *+1
|
||||||
@ -140,6 +171,8 @@ OFFSHI = *+1
|
|||||||
ADC PUTDST+2
|
ADC PUTDST+2
|
||||||
STA COPY_MATCH_LOOP+2 ; store high 8 bits of address
|
STA COPY_MATCH_LOOP+2 ; store high 8 bits of address
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
PLA ; retrieve token from stack again
|
PLA ; retrieve token from stack again
|
||||||
AND #$07 ; isolate match len (MMM)
|
AND #$07 ; isolate match len (MMM)
|
||||||
ADC #$01 ; add MIN_MATCH_SIZE_V2 and carry
|
ADC #$01 ; add MIN_MATCH_SIZE_V2 and carry
|
||||||
@ -173,11 +206,29 @@ PREPARE_COPY_MATCH_Y
|
|||||||
|
|
||||||
COPY_MATCH_LOOP
|
COPY_MATCH_LOOP
|
||||||
LDA $AAAA ; get one byte of backreference
|
LDA $AAAA ; get one byte of backreference
|
||||||
|
JSR PUTDST ; copy to destination
|
||||||
|
|
||||||
|
!ifdef BACKWARD_DECOMPRESS {
|
||||||
|
|
||||||
|
; Backward decompression -- put backreference bytes backward
|
||||||
|
|
||||||
|
LDA COPY_MATCH_LOOP+1
|
||||||
|
BNE GETMATCH_DONE
|
||||||
|
DEC COPY_MATCH_LOOP+2
|
||||||
|
GETMATCH_DONE
|
||||||
|
DEC COPY_MATCH_LOOP+1
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
; Forward decompression -- put backreference bytes forward
|
||||||
|
|
||||||
INC COPY_MATCH_LOOP+1
|
INC COPY_MATCH_LOOP+1
|
||||||
BNE GETMATCH_DONE
|
BNE GETMATCH_DONE
|
||||||
INC COPY_MATCH_LOOP+2
|
INC COPY_MATCH_LOOP+2
|
||||||
GETMATCH_DONE
|
GETMATCH_DONE
|
||||||
JSR PUTDST ; copy to destination
|
|
||||||
|
}
|
||||||
|
|
||||||
DEX
|
DEX
|
||||||
BNE COPY_MATCH_LOOP
|
BNE COPY_MATCH_LOOP
|
||||||
DEY
|
DEY
|
||||||
@ -215,6 +266,45 @@ HAS_NIBBLES
|
|||||||
AND #$0F ; isolate low 4 bits of nibble
|
AND #$0F ; isolate low 4 bits of nibble
|
||||||
RTS
|
RTS
|
||||||
|
|
||||||
|
!ifdef BACKWARD_DECOMPRESS {
|
||||||
|
|
||||||
|
; Backward decompression -- get and put bytes backward
|
||||||
|
|
||||||
|
GETPUT
|
||||||
|
JSR GETSRC
|
||||||
|
PUTDST
|
||||||
|
LZSA_DST_LO = *+1
|
||||||
|
LZSA_DST_HI = *+2
|
||||||
|
STA $AAAA
|
||||||
|
LDA PUTDST+1
|
||||||
|
BNE PUTDST_DONE
|
||||||
|
DEC PUTDST+2
|
||||||
|
PUTDST_DONE
|
||||||
|
DEC PUTDST+1
|
||||||
|
RTS
|
||||||
|
|
||||||
|
GETLARGESRC
|
||||||
|
JSR GETSRC ; grab low 8 bits
|
||||||
|
TAX ; move to X
|
||||||
|
; fall through grab high 8 bits
|
||||||
|
|
||||||
|
GETSRC
|
||||||
|
LZSA_SRC_LO = *+1
|
||||||
|
LZSA_SRC_HI = *+2
|
||||||
|
LDA $AAAA
|
||||||
|
PHA
|
||||||
|
LDA GETSRC+1
|
||||||
|
BNE GETSRC_DONE
|
||||||
|
DEC GETSRC+2
|
||||||
|
GETSRC_DONE
|
||||||
|
DEC GETSRC+1
|
||||||
|
PLA
|
||||||
|
RTS
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
; Forward decompression -- get and put bytes forward
|
||||||
|
|
||||||
GETPUT
|
GETPUT
|
||||||
JSR GETSRC
|
JSR GETSRC
|
||||||
PUTDST
|
PUTDST
|
||||||
@ -241,3 +331,6 @@ LZSA_SRC_HI = *+2
|
|||||||
INC GETSRC+2
|
INC GETSRC+2
|
||||||
GETSRC_DONE
|
GETSRC_DONE
|
||||||
RTS
|
RTS
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
;
|
;
|
||||||
; Speed-optimized LZSA2 decompressor by spke (v.1 02-07/06/2019, 218 bytes)
|
; Speed-optimized LZSA2 decompressor by spke (v.1 02-07/06/2019 +patch1-30/07/2019, 213/211(hd64180) bytes)
|
||||||
;
|
;
|
||||||
; The data must be compressed using the command line compressor by Emmanuel Marty
|
; The data must be compressed using the command line compressor by Emmanuel Marty
|
||||||
; The compression is done as follows:
|
; The compression is done as follows:
|
||||||
@ -56,7 +56,7 @@
|
|||||||
ENDM
|
ENDM
|
||||||
|
|
||||||
MACRO ADD_OFFSET
|
MACRO ADD_OFFSET
|
||||||
or a : sbc hl,de
|
push hl : or a : sbc hl,de : pop de
|
||||||
ENDM
|
ENDM
|
||||||
|
|
||||||
MACRO BLOCKCOPY
|
MACRO BLOCKCOPY
|
||||||
@ -70,7 +70,7 @@
|
|||||||
ENDM
|
ENDM
|
||||||
|
|
||||||
MACRO ADD_OFFSET
|
MACRO ADD_OFFSET
|
||||||
add hl,de
|
ex de,hl : add hl,de
|
||||||
ENDM
|
ENDM
|
||||||
|
|
||||||
MACRO BLOCKCOPY
|
MACRO BLOCKCOPY
|
||||||
@ -79,16 +79,32 @@
|
|||||||
|
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
|
IFDEF HD64180
|
||||||
|
MACRO LD_IX_DE
|
||||||
|
push de : pop ix
|
||||||
|
ENDM
|
||||||
|
MACRO LD_DE_IX
|
||||||
|
push ix : pop de
|
||||||
|
ENDM
|
||||||
|
ELSE
|
||||||
|
MACRO LD_IX_DE
|
||||||
|
ld ixl,e : ld ixh,d
|
||||||
|
ENDM
|
||||||
|
MACRO LD_DE_IX
|
||||||
|
ld e,ixl : ld d,ixh
|
||||||
|
ENDM
|
||||||
|
ENDIF
|
||||||
|
|
||||||
@DecompressLZSA2:
|
@DecompressLZSA2:
|
||||||
; A' stores next nibble as %1111.... or assumed to contain trash
|
; A' stores next nibble as %1111.... or assumed to contain trash
|
||||||
; B is assumed to be 0
|
; B is assumed to be 0
|
||||||
xor a : ld b,a : exa : jr ReadToken
|
xor a : ld b,a : scf : exa : jr ReadToken
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LongerMatch: exa : jp m,.noUpdate
|
LongerMatch: scf : exa : jr nc,.noUpdate
|
||||||
|
|
||||||
ld a,(hl) : or #F0 : exa
|
ld a,(hl) : or #F0 : exa
|
||||||
ld a,(hl) : NEXT_HL : or #0F
|
ld a,(hl) : NEXT_HL : or #0F
|
||||||
@ -110,14 +126,14 @@ LongMatch: ;ld a,24 :
|
|||||||
ManyLiterals: ld a,18 :
|
ManyLiterals: ld a,18 :
|
||||||
add (hl) : NEXT_HL : jr nc,CopyLiterals
|
add (hl) : NEXT_HL : jr nc,CopyLiterals
|
||||||
ld c,(hl) : NEXT_HL
|
ld c,(hl) : NEXT_HL
|
||||||
ld a,b : ld b,(hl) : NEXT_HL
|
ld a,b : ld b,(hl)
|
||||||
jr CopyLiterals.useBC
|
jr ReadToken.useBC
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MoreLiterals: ld b,(hl) : NEXT_HL
|
MoreLiterals: ld b,(hl) : NEXT_HL
|
||||||
exa : jp m,.noUpdate
|
scf : exa : jr nc,.noUpdate
|
||||||
|
|
||||||
ld a,(hl) : or #F0 : exa
|
ld a,(hl) : or #F0 : exa
|
||||||
ld a,(hl) : NEXT_HL : or #0F
|
ld a,(hl) : NEXT_HL : or #0F
|
||||||
@ -148,13 +164,13 @@ CASE01x: cp %01100000 : rl d
|
|||||||
|
|
||||||
ReadOffsetE: ld e,(hl) : NEXT_HL
|
ReadOffsetE: ld e,(hl) : NEXT_HL
|
||||||
|
|
||||||
SaveOffset: ld ixl,e : ld ixh,d
|
SaveOffset: LD_IX_DE
|
||||||
|
|
||||||
MatchLen: inc a : and %00000111 : jr z,LongerMatch : inc a
|
MatchLen: inc a : and %00000111 : jr z,LongerMatch : inc a
|
||||||
|
|
||||||
CopyMatch: ld c,a
|
CopyMatch: ld c,a
|
||||||
.useC ex (sp),hl : push hl ; BC = len, DE = offset, HL = dest, SP ->[dest,src]
|
.useC ex (sp),hl ; BC = len, DE = offset, HL = dest, SP ->[src]
|
||||||
ADD_OFFSET : pop de ; BC = len, DE = dest, HL = dest-offset, SP->[src]
|
ADD_OFFSET ; BC = len, DE = dest, HL = dest-offset, SP->[src]
|
||||||
BLOCKCOPY : pop hl
|
BLOCKCOPY : pop hl
|
||||||
|
|
||||||
; compressed data stream contains records
|
; compressed data stream contains records
|
||||||
@ -164,7 +180,8 @@ ReadToken: ld a,(hl) : and %00011000 : jr z,NoLiterals
|
|||||||
jp pe,MoreLiterals ; 00 has already been processed; this identifies the case of 11
|
jp pe,MoreLiterals ; 00 has already been processed; this identifies the case of 11
|
||||||
rrca : rrca : rrca
|
rrca : rrca : rrca
|
||||||
|
|
||||||
ld c,a : ld a,(hl) : NEXT_HL ; token is re-read for further processing
|
ld c,a : ld a,(hl) ; token is re-read for further processing
|
||||||
|
.useBC NEXT_HL
|
||||||
BLOCKCOPY
|
BLOCKCOPY
|
||||||
|
|
||||||
; the token and literals are followed by the offset
|
; the token and literals are followed by the offset
|
||||||
@ -173,8 +190,8 @@ ReadToken: ld a,(hl) : and %00011000 : jr z,NoLiterals
|
|||||||
CASE1xx cp %11000000 : jr nc,CASE11x
|
CASE1xx cp %11000000 : jr nc,CASE11x
|
||||||
|
|
||||||
; "10x": the case of the 5-bit offset
|
; "10x": the case of the 5-bit offset
|
||||||
CASE10x: ld c,a : xor a
|
CASE10x: ld c,a
|
||||||
exa : jp m,.noUpdate
|
exa : jr nc,.noUpdate
|
||||||
|
|
||||||
ld a,(hl) : or #F0 : exa
|
ld a,(hl) : or #F0 : exa
|
||||||
ld a,(hl) : NEXT_HL : or #0F
|
ld a,(hl) : NEXT_HL : or #0F
|
||||||
@ -185,8 +202,8 @@ CASE10x: ld c,a : xor a
|
|||||||
dec d : dec d : jr ReadOffsetE
|
dec d : dec d : jr ReadOffsetE
|
||||||
|
|
||||||
; "00x": the case of the 5-bit offset
|
; "00x": the case of the 5-bit offset
|
||||||
CASE00x: ld c,a : xor a
|
CASE00x: ld c,a
|
||||||
exa : jp m,.noUpdate
|
exa : jr nc,.noUpdate
|
||||||
|
|
||||||
ld a,(hl) : or #F0 : exa
|
ld a,(hl) : or #F0 : exa
|
||||||
ld a,(hl) : NEXT_HL : or #0F
|
ld a,(hl) : NEXT_HL : or #0F
|
||||||
@ -199,7 +216,7 @@ CASE00x: ld c,a : xor a
|
|||||||
CASE11x cp %11100000 : jr c,CASE110
|
CASE11x cp %11100000 : jr c,CASE110
|
||||||
|
|
||||||
; "111": repeated offset
|
; "111": repeated offset
|
||||||
CASE111: ld e,ixl : ld d,ixh : jr MatchLen
|
CASE111: LD_DE_IX : jr MatchLen
|
||||||
|
|
||||||
; "110": 16-bit offset
|
; "110": 16-bit offset
|
||||||
CASE110: ld d,(hl) : NEXT_HL : jr ReadOffsetE
|
CASE110: ld d,(hl) : NEXT_HL : jr ReadOffsetE
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
;
|
;
|
||||||
; Size-optimized LZSA2 decompressor by spke (v.1 02-09/06/2019, 145 bytes)
|
; Size-optimized LZSA2 decompressor by spke (v.1 02-09/06/2019 +patch1-30/07/2019, 144 bytes)
|
||||||
;
|
;
|
||||||
; The data must be compressed using the command line compressor by Emmanuel Marty
|
; The data must be compressed using the command line compressor by Emmanuel Marty
|
||||||
; The compression is done as follows:
|
; The compression is done as follows:
|
||||||
@ -57,7 +57,7 @@
|
|||||||
ENDM
|
ENDM
|
||||||
|
|
||||||
MACRO ADD_OFFSET
|
MACRO ADD_OFFSET
|
||||||
or a : sbc hl,de
|
push hl : or a : sbc hl,de : pop de
|
||||||
ENDM
|
ENDM
|
||||||
|
|
||||||
MACRO BLOCKCOPY
|
MACRO BLOCKCOPY
|
||||||
@ -71,7 +71,7 @@
|
|||||||
ENDM
|
ENDM
|
||||||
|
|
||||||
MACRO ADD_OFFSET
|
MACRO ADD_OFFSET
|
||||||
add hl,de
|
ex de,hl : add hl,de
|
||||||
ENDM
|
ENDM
|
||||||
|
|
||||||
MACRO BLOCKCOPY
|
MACRO BLOCKCOPY
|
||||||
@ -80,6 +80,37 @@
|
|||||||
|
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
|
IFDEF HD64180
|
||||||
|
MACRO LD_IY_DE
|
||||||
|
push de : pop iy
|
||||||
|
ENDM
|
||||||
|
MACRO LD_DE_IY
|
||||||
|
push iy : pop de
|
||||||
|
ENDM
|
||||||
|
MACRO LD_IXL_A
|
||||||
|
exx : ld l,a : exx
|
||||||
|
ENDM
|
||||||
|
MACRO LD_A_IXL
|
||||||
|
exx : ld a,l : exx
|
||||||
|
ENDM
|
||||||
|
ELSE
|
||||||
|
MACRO LD_IY_DE
|
||||||
|
;push de : pop iy
|
||||||
|
ld iyl,e : ld iyh,d
|
||||||
|
ENDM
|
||||||
|
MACRO LD_DE_IY
|
||||||
|
;push iy : pop de
|
||||||
|
ld e,iyl : ld d,iyh
|
||||||
|
ENDM
|
||||||
|
MACRO LD_IXL_A
|
||||||
|
ld ixl,a
|
||||||
|
ENDM
|
||||||
|
MACRO LD_A_IXL
|
||||||
|
ld a,ixl
|
||||||
|
ENDM
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
|
||||||
@DecompressLZSA2:
|
@DecompressLZSA2:
|
||||||
xor a : ld b,a : exa : jr ReadToken
|
xor a : ld b,a : exa : jr ReadToken
|
||||||
|
|
||||||
@ -89,16 +120,16 @@ CASE01x: cp %01100000 : rl d
|
|||||||
|
|
||||||
OffsetReadE: ld e,(hl) : NEXT_HL
|
OffsetReadE: ld e,(hl) : NEXT_HL
|
||||||
|
|
||||||
SaveOffset: ld iyl,e : ld iyh,d
|
SaveOffset: LD_IY_DE
|
||||||
|
|
||||||
MatchLen: and %00000111 : add 2 : cp 9 : call z,ExtendedCode
|
MatchLen: and %00000111 : add 2 : cp 9 : call z,ExtendedCode
|
||||||
|
|
||||||
CopyMatch: ld c,a
|
CopyMatch: ld c,a
|
||||||
ex (sp),hl : push hl ; BC = len, DE = offset, HL = dest, SP ->[dest,src]
|
ex (sp),hl ; BC = len, DE = offset, HL = dest, SP ->[src]
|
||||||
ADD_OFFSET : pop de ; BC = len, DE = dest, HL = dest-offset, SP->[src]
|
ADD_OFFSET ; BC = len, DE = dest, HL = dest-offset, SP->[src]
|
||||||
BLOCKCOPY : pop hl
|
BLOCKCOPY : pop hl
|
||||||
|
|
||||||
ReadToken: ld a,(hl) : ld ixl,a : NEXT_HL
|
ReadToken: ld a,(hl) : LD_IXL_A : NEXT_HL
|
||||||
and %00011000 : jr z,NoLiterals
|
and %00011000 : jr z,NoLiterals
|
||||||
|
|
||||||
rrca : rrca : rrca
|
rrca : rrca : rrca
|
||||||
@ -107,7 +138,7 @@ ReadToken: ld a,(hl) : ld ixl,a : NEXT_HL
|
|||||||
ld c,a
|
ld c,a
|
||||||
BLOCKCOPY
|
BLOCKCOPY
|
||||||
|
|
||||||
NoLiterals: push de : ld a,ixl
|
NoLiterals: push de : LD_A_IXL
|
||||||
or a : jp p,CASE0xx
|
or a : jp p,CASE0xx
|
||||||
|
|
||||||
CASE1xx cp %11000000 : jr nc,CASE11x
|
CASE1xx cp %11000000 : jr nc,CASE11x
|
||||||
@ -123,7 +154,7 @@ CASE00x: call ReadNibble
|
|||||||
|
|
||||||
CASE11x cp %11100000 : jr c,CASE110
|
CASE11x cp %11100000 : jr c,CASE110
|
||||||
|
|
||||||
CASE111: ld e,iyl : ld d,iyh : jr MatchLen
|
CASE111: LD_DE_IY : jr MatchLen
|
||||||
|
|
||||||
CASE110: ld d,(hl) : NEXT_HL : jr OffsetReadE
|
CASE110: ld d,(hl) : NEXT_HL : jr OffsetReadE
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "expand_context.h"
|
#include "expand_context.h"
|
||||||
#include "expand_block_v1.h"
|
#include "expand_block_v1.h"
|
||||||
#include "expand_block_v2.h"
|
#include "expand_block_v2.h"
|
||||||
|
#include "lib.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decompress one data block
|
* Decompress one data block
|
||||||
@ -45,14 +46,31 @@
|
|||||||
* @param nOutDataOffset starting index of where to store decompressed bytes in output buffer (and size of previously decompressed bytes)
|
* @param nOutDataOffset starting index of where to store decompressed bytes in output buffer (and size of previously decompressed bytes)
|
||||||
* @param nBlockMaxSize total size of output decompression buffer, in bytes
|
* @param nBlockMaxSize total size of output decompression buffer, in bytes
|
||||||
* @param nFormatVersion version of format to use (1-2)
|
* @param nFormatVersion version of format to use (1-2)
|
||||||
|
* @param nFlags compression flags (LZSA_FLAG_xxx)
|
||||||
*
|
*
|
||||||
* @return size of decompressed data in bytes, or -1 for error
|
* @return size of decompressed data in bytes, or -1 for error
|
||||||
*/
|
*/
|
||||||
int lzsa_decompressor_expand_block(const unsigned char *pInBlock, int nBlockSize, unsigned char *pOutData, int nOutDataOffset, int nBlockMaxSize, const int nFormatVersion) {
|
int lzsa_decompressor_expand_block(unsigned char *pInBlock, int nBlockSize, unsigned char *pOutData, int nOutDataOffset, int nBlockMaxSize, const int nFormatVersion, const int nFlags) {
|
||||||
|
int nDecompressedSize;
|
||||||
|
|
||||||
|
if (nFlags & LZSA_FLAG_RAW_BACKWARD) {
|
||||||
|
lzsa_reverse_buffer(pInBlock, nBlockSize);
|
||||||
|
}
|
||||||
|
|
||||||
if (nFormatVersion == 1)
|
if (nFormatVersion == 1)
|
||||||
return lzsa_decompressor_expand_block_v1(pInBlock, nBlockSize, pOutData, nOutDataOffset, nBlockMaxSize);
|
nDecompressedSize = lzsa_decompressor_expand_block_v1(pInBlock, nBlockSize, pOutData, nOutDataOffset, nBlockMaxSize);
|
||||||
else if (nFormatVersion == 2)
|
else if (nFormatVersion == 2)
|
||||||
return lzsa_decompressor_expand_block_v2(pInBlock, nBlockSize, pOutData, nOutDataOffset, nBlockMaxSize);
|
nDecompressedSize = lzsa_decompressor_expand_block_v2(pInBlock, nBlockSize, pOutData, nOutDataOffset, nBlockMaxSize);
|
||||||
else
|
else
|
||||||
return -1;
|
nDecompressedSize = -1;
|
||||||
|
|
||||||
|
if (nDecompressedSize != -1 && (nFlags & LZSA_FLAG_RAW_BACKWARD)) {
|
||||||
|
lzsa_reverse_buffer(pOutData + nOutDataOffset, nDecompressedSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nFlags & LZSA_FLAG_RAW_BACKWARD) {
|
||||||
|
lzsa_reverse_buffer(pInBlock, nBlockSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nDecompressedSize;
|
||||||
}
|
}
|
||||||
|
@ -48,10 +48,11 @@ extern "C" {
|
|||||||
* @param nOutDataOffset starting index of where to store decompressed bytes in output buffer (and size of previously decompressed bytes)
|
* @param nOutDataOffset starting index of where to store decompressed bytes in output buffer (and size of previously decompressed bytes)
|
||||||
* @param nBlockMaxSize total size of output decompression buffer, in bytes
|
* @param nBlockMaxSize total size of output decompression buffer, in bytes
|
||||||
* @param nFormatVersion version of format to use (1-2)
|
* @param nFormatVersion version of format to use (1-2)
|
||||||
|
* @param nFlags compression flags (LZSA_FLAG_xxx)
|
||||||
*
|
*
|
||||||
* @return size of decompressed data in bytes, or -1 for error
|
* @return size of decompressed data in bytes, or -1 for error
|
||||||
*/
|
*/
|
||||||
int lzsa_decompressor_expand_block(const unsigned char *pInBlock, int nBlockSize, unsigned char *pOutData, int nOutDataOffset, int nBlockMaxSize, const int nFormatVersion);
|
int lzsa_decompressor_expand_block(unsigned char *pInBlock, int nBlockSize, unsigned char *pOutData, int nOutDataOffset, int nBlockMaxSize, const int nFormatVersion, const int nFlags);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -98,8 +98,8 @@ size_t lzsa_get_max_decompressed_size_inmem(const unsigned char *pFileData, size
|
|||||||
*
|
*
|
||||||
* @return actual decompressed size, or -1 for error
|
* @return actual decompressed size, or -1 for error
|
||||||
*/
|
*/
|
||||||
size_t lzsa_decompress_inmem(const unsigned char *pFileData, unsigned char *pOutBuffer, size_t nFileSize, size_t nMaxOutBufferSize, const unsigned int nFlags, int *pFormatVersion) {
|
size_t lzsa_decompress_inmem(unsigned char *pFileData, unsigned char *pOutBuffer, size_t nFileSize, size_t nMaxOutBufferSize, const unsigned int nFlags, int *pFormatVersion) {
|
||||||
const unsigned char *pCurFileData = pFileData;
|
unsigned char *pCurFileData = pFileData;
|
||||||
const unsigned char *pEndFileData = pCurFileData + nFileSize;
|
const unsigned char *pEndFileData = pCurFileData + nFileSize;
|
||||||
unsigned char *pCurOutBuffer = pOutBuffer;
|
unsigned char *pCurOutBuffer = pOutBuffer;
|
||||||
const unsigned char *pEndOutBuffer = pCurOutBuffer + nMaxOutBufferSize;
|
const unsigned char *pEndOutBuffer = pCurOutBuffer + nMaxOutBufferSize;
|
||||||
@ -107,7 +107,7 @@ size_t lzsa_decompress_inmem(const unsigned char *pFileData, unsigned char *pOut
|
|||||||
const int nHeaderSize = lzsa_get_header_size();
|
const int nHeaderSize = lzsa_get_header_size();
|
||||||
|
|
||||||
if (nFlags & LZSA_FLAG_RAW_BLOCK) {
|
if (nFlags & LZSA_FLAG_RAW_BLOCK) {
|
||||||
return (size_t)lzsa_decompressor_expand_block(pFileData, (int)nFileSize, pOutBuffer, 0, (int)nMaxOutBufferSize, *pFormatVersion);
|
return (size_t)lzsa_decompressor_expand_block(pFileData, (int)nFileSize, pOutBuffer, 0, (int)nMaxOutBufferSize, *pFormatVersion, nFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check header */
|
/* Check header */
|
||||||
@ -139,7 +139,7 @@ size_t lzsa_decompress_inmem(const unsigned char *pFileData, unsigned char *pOut
|
|||||||
if ((pCurFileData + nBlockDataSize) > pEndFileData)
|
if ((pCurFileData + nBlockDataSize) > pEndFileData)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
nDecompressedSize = lzsa_decompressor_expand_block(pCurFileData, nBlockDataSize, pCurOutBuffer - nPreviousBlockSize, nPreviousBlockSize, (int)(pEndOutBuffer - pCurOutBuffer + nPreviousBlockSize), *pFormatVersion);
|
nDecompressedSize = lzsa_decompressor_expand_block(pCurFileData, nBlockDataSize, pCurOutBuffer - nPreviousBlockSize, nPreviousBlockSize, (int)(pEndOutBuffer - pCurOutBuffer + nPreviousBlockSize), *pFormatVersion, nFlags);
|
||||||
if (nDecompressedSize < 0)
|
if (nDecompressedSize < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ size_t lzsa_get_max_decompressed_size_inmem(const unsigned char *pFileData, size
|
|||||||
*
|
*
|
||||||
* @return actual decompressed size, or -1 for error
|
* @return actual decompressed size, or -1 for error
|
||||||
*/
|
*/
|
||||||
size_t lzsa_decompress_inmem(const unsigned char *pFileData, unsigned char *pOutBuffer, size_t nFileSize, size_t nMaxOutBufferSize, const unsigned int nFlags, int *pFormatVersion);
|
size_t lzsa_decompress_inmem(unsigned char *pFileData, unsigned char *pOutBuffer, size_t nFileSize, size_t nMaxOutBufferSize, const unsigned int nFlags, int *pFormatVersion);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -196,7 +196,7 @@ lzsa_status_t lzsa_decompress_stream(lzsa_stream_t *pInStream, lzsa_stream_t *pO
|
|||||||
nDecompressedSize = nBlockSize;
|
nDecompressedSize = nBlockSize;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nDecompressedSize = lzsa_decompressor_expand_block(pInBlock, nBlockSize, pOutData, BLOCK_SIZE, BLOCK_SIZE, nFormatVersion);
|
nDecompressedSize = lzsa_decompressor_expand_block(pInBlock, nBlockSize, pOutData, BLOCK_SIZE, BLOCK_SIZE, nFormatVersion, nFlags);
|
||||||
if (nDecompressedSize < 0) {
|
if (nDecompressedSize < 0) {
|
||||||
nDecompressionError = LZSA_ERROR_DECOMPRESSION;
|
nDecompressionError = LZSA_ERROR_DECOMPRESSION;
|
||||||
break;
|
break;
|
||||||
|
18
src/lib.h
18
src/lib.h
@ -69,6 +69,24 @@ typedef enum _lzsa_status_t {
|
|||||||
/* Compression flags */
|
/* Compression flags */
|
||||||
#define LZSA_FLAG_FAVOR_RATIO (1<<0) /**< 1 to compress with the best ratio, 0 to trade some compression ratio for extra decompression speed */
|
#define LZSA_FLAG_FAVOR_RATIO (1<<0) /**< 1 to compress with the best ratio, 0 to trade some compression ratio for extra decompression speed */
|
||||||
#define LZSA_FLAG_RAW_BLOCK (1<<1) /**< 1 to emit raw block */
|
#define LZSA_FLAG_RAW_BLOCK (1<<1) /**< 1 to emit raw block */
|
||||||
|
#define LZSA_FLAG_RAW_BACKWARD (1<<2) /**< 1 to compress or decompress raw block backward */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse bytes in the specified buffer
|
||||||
|
*
|
||||||
|
* @param pBuffer pointer to buffer whose contents are to be reversed
|
||||||
|
* @param nBufferSize size of buffer in bytes
|
||||||
|
*/
|
||||||
|
static inline void lzsa_reverse_buffer(unsigned char *pBuffer, const int nBufferSize) {
|
||||||
|
int nMidPoint = nBufferSize / 2;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (i = 0, j = nBufferSize - 1; i < nMidPoint; i++, j--) {
|
||||||
|
unsigned char c = pBuffer[i];
|
||||||
|
pBuffer[i] = pBuffer[j];
|
||||||
|
pBuffer[j] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
36
src/lzsa.c
36
src/lzsa.c
@ -42,11 +42,12 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
|
|
||||||
#define OPT_VERBOSE 1
|
#define OPT_VERBOSE 1
|
||||||
#define OPT_RAW 2
|
#define OPT_RAW 2
|
||||||
#define OPT_FAVOR_RATIO 4
|
#define OPT_FAVOR_RATIO 4
|
||||||
|
#define OPT_RAW_BACKWARD 8
|
||||||
|
|
||||||
#define TOOL_VERSION "1.0.4"
|
#define TOOL_VERSION "1.0.6"
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
@ -109,6 +110,8 @@ static int do_compress(const char *pszInFilename, const char *pszOutFilename, co
|
|||||||
nFlags |= LZSA_FLAG_FAVOR_RATIO;
|
nFlags |= LZSA_FLAG_FAVOR_RATIO;
|
||||||
if (nOptions & OPT_RAW)
|
if (nOptions & OPT_RAW)
|
||||||
nFlags |= LZSA_FLAG_RAW_BLOCK;
|
nFlags |= LZSA_FLAG_RAW_BLOCK;
|
||||||
|
if (nOptions & OPT_RAW_BACKWARD)
|
||||||
|
nFlags |= LZSA_FLAG_RAW_BACKWARD;
|
||||||
|
|
||||||
if (nOptions & OPT_VERBOSE) {
|
if (nOptions & OPT_VERBOSE) {
|
||||||
nStartTime = do_get_time();
|
nStartTime = do_get_time();
|
||||||
@ -160,6 +163,8 @@ static int do_decompress(const char *pszInFilename, const char *pszOutFilename,
|
|||||||
nFlags = 0;
|
nFlags = 0;
|
||||||
if (nOptions & OPT_RAW)
|
if (nOptions & OPT_RAW)
|
||||||
nFlags |= LZSA_FLAG_RAW_BLOCK;
|
nFlags |= LZSA_FLAG_RAW_BLOCK;
|
||||||
|
if (nOptions & OPT_RAW_BACKWARD)
|
||||||
|
nFlags |= LZSA_FLAG_RAW_BACKWARD;
|
||||||
|
|
||||||
if (nOptions & OPT_VERBOSE) {
|
if (nOptions & OPT_VERBOSE) {
|
||||||
nStartTime = do_get_time();
|
nStartTime = do_get_time();
|
||||||
@ -308,6 +313,8 @@ static int do_compare(const char *pszInFilename, const char *pszOutFilename, con
|
|||||||
nFlags = 0;
|
nFlags = 0;
|
||||||
if (nOptions & OPT_RAW)
|
if (nOptions & OPT_RAW)
|
||||||
nFlags |= LZSA_FLAG_RAW_BLOCK;
|
nFlags |= LZSA_FLAG_RAW_BLOCK;
|
||||||
|
if (nOptions & OPT_RAW_BACKWARD)
|
||||||
|
nFlags |= LZSA_FLAG_RAW_BACKWARD;
|
||||||
|
|
||||||
if (nOptions & OPT_VERBOSE) {
|
if (nOptions & OPT_VERBOSE) {
|
||||||
nStartTime = do_get_time();
|
nStartTime = do_get_time();
|
||||||
@ -419,6 +426,8 @@ static int do_self_test(const unsigned int nOptions, const int nMinMatchSize, in
|
|||||||
nFlags |= LZSA_FLAG_FAVOR_RATIO;
|
nFlags |= LZSA_FLAG_FAVOR_RATIO;
|
||||||
if (nOptions & OPT_RAW)
|
if (nOptions & OPT_RAW)
|
||||||
nFlags |= LZSA_FLAG_RAW_BLOCK;
|
nFlags |= LZSA_FLAG_RAW_BLOCK;
|
||||||
|
if (nOptions & OPT_RAW_BACKWARD)
|
||||||
|
nFlags |= LZSA_FLAG_RAW_BACKWARD;
|
||||||
|
|
||||||
pGeneratedData = (unsigned char*)malloc(4 * BLOCK_SIZE);
|
pGeneratedData = (unsigned char*)malloc(4 * BLOCK_SIZE);
|
||||||
if (!pGeneratedData) {
|
if (!pGeneratedData) {
|
||||||
@ -477,7 +486,7 @@ static int do_self_test(const unsigned int nOptions, const int nMinMatchSize, in
|
|||||||
float fMatchProbability;
|
float fMatchProbability;
|
||||||
|
|
||||||
fprintf(stdout, "size %zd", nGeneratedDataSize);
|
fprintf(stdout, "size %zd", nGeneratedDataSize);
|
||||||
for (fMatchProbability = ((nOptions & OPT_RAW) ? 0.5f : 0); fMatchProbability <= 0.995f; fMatchProbability += fProbabilitySizeStep) {
|
for (fMatchProbability = 0; fMatchProbability <= 0.995f; fMatchProbability += fProbabilitySizeStep) {
|
||||||
int nNumLiteralValues[12] = { 1, 2, 3, 15, 30, 56, 96, 137, 178, 191, 255, 256 };
|
int nNumLiteralValues[12] = { 1, 2, 3, 15, 30, 56, 96, 137, 178, 191, 255, 256 };
|
||||||
float fXorProbability;
|
float fXorProbability;
|
||||||
|
|
||||||
@ -590,6 +599,8 @@ static int do_compr_benchmark(const char *pszInFilename, const char *pszOutFilen
|
|||||||
nFlags |= LZSA_FLAG_FAVOR_RATIO;
|
nFlags |= LZSA_FLAG_FAVOR_RATIO;
|
||||||
if (nOptions & OPT_RAW)
|
if (nOptions & OPT_RAW)
|
||||||
nFlags |= LZSA_FLAG_RAW_BLOCK;
|
nFlags |= LZSA_FLAG_RAW_BLOCK;
|
||||||
|
if (nOptions & OPT_RAW_BACKWARD)
|
||||||
|
nFlags |= LZSA_FLAG_RAW_BACKWARD;
|
||||||
|
|
||||||
if (pszDictionaryFilename) {
|
if (pszDictionaryFilename) {
|
||||||
fprintf(stderr, "in-memory benchmarking does not support dictionaries\n");
|
fprintf(stderr, "in-memory benchmarking does not support dictionaries\n");
|
||||||
@ -720,6 +731,8 @@ static int do_dec_benchmark(const char *pszInFilename, const char *pszOutFilenam
|
|||||||
nFlags = 0;
|
nFlags = 0;
|
||||||
if (nOptions & OPT_RAW)
|
if (nOptions & OPT_RAW)
|
||||||
nFlags |= LZSA_FLAG_RAW_BLOCK;
|
nFlags |= LZSA_FLAG_RAW_BLOCK;
|
||||||
|
if (nOptions & OPT_RAW_BACKWARD)
|
||||||
|
nFlags |= LZSA_FLAG_RAW_BACKWARD;
|
||||||
|
|
||||||
if (pszDictionaryFilename) {
|
if (pszDictionaryFilename) {
|
||||||
fprintf(stderr, "in-memory benchmarking does not support dictionaries\n");
|
fprintf(stderr, "in-memory benchmarking does not support dictionaries\n");
|
||||||
@ -987,6 +1000,13 @@ int main(int argc, char **argv) {
|
|||||||
else
|
else
|
||||||
bArgsError = true;
|
bArgsError = true;
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(argv[i], "-b")) {
|
||||||
|
if ((nOptions & OPT_RAW_BACKWARD) == 0) {
|
||||||
|
nOptions |= OPT_RAW_BACKWARD;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
bArgsError = true;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if (!pszInFilename)
|
if (!pszInFilename)
|
||||||
pszInFilename = argv[i];
|
pszInFilename = argv[i];
|
||||||
@ -999,6 +1019,11 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!bArgsError && (nOptions & OPT_RAW_BACKWARD) && !(nOptions & OPT_RAW)) {
|
||||||
|
fprintf(stderr, "error: -b (compress backwards) requires -r (raw block format)\n");
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
|
||||||
if (!bArgsError && cCommand == 't') {
|
if (!bArgsError && cCommand == 't') {
|
||||||
return do_self_test(nOptions, nMinMatchSize, nFormatVersion);
|
return do_self_test(nOptions, nMinMatchSize, nFormatVersion);
|
||||||
}
|
}
|
||||||
@ -1014,6 +1039,7 @@ int main(int argc, char **argv) {
|
|||||||
fprintf(stderr, " -v: be verbose\n");
|
fprintf(stderr, " -v: be verbose\n");
|
||||||
fprintf(stderr, " -f <value>: LZSA compression format (1-2)\n");
|
fprintf(stderr, " -f <value>: LZSA compression format (1-2)\n");
|
||||||
fprintf(stderr, " -r: raw block format (max. 64 Kb files)\n");
|
fprintf(stderr, " -r: raw block format (max. 64 Kb files)\n");
|
||||||
|
fprintf(stderr, " -b: compress backward (requires -r and a backward decompressor)\n");
|
||||||
fprintf(stderr, " -D <filename>: use dictionary file\n");
|
fprintf(stderr, " -D <filename>: use dictionary file\n");
|
||||||
fprintf(stderr, " -m <value>: minimum match size (3-5) (default: 3)\n");
|
fprintf(stderr, " -m <value>: minimum match size (3-5) (default: 3)\n");
|
||||||
fprintf(stderr, " --prefer-ratio: favor compression ratio (default)\n");
|
fprintf(stderr, " --prefer-ratio: favor compression ratio (default)\n");
|
||||||
|
@ -188,7 +188,6 @@ static void lzsa_optimize_matches_v2(lzsa_compressor *pCompressor, const int nSt
|
|||||||
int *cost = (int*)pCompressor->pos_data; /* Reuse */
|
int *cost = (int*)pCompressor->pos_data; /* Reuse */
|
||||||
int *prev_match = (int*)pCompressor->intervals; /* Reuse */
|
int *prev_match = (int*)pCompressor->intervals; /* Reuse */
|
||||||
lzsa_repmatch_opt *repmatch_opt = pCompressor->repmatch_opt;
|
lzsa_repmatch_opt *repmatch_opt = pCompressor->repmatch_opt;
|
||||||
lzsa_match *pBestMatch = pCompressor->best_match;
|
|
||||||
int nLastLiteralsOffset;
|
int nLastLiteralsOffset;
|
||||||
int nMinMatchSize = pCompressor->min_match_size;
|
int nMinMatchSize = pCompressor->min_match_size;
|
||||||
const int nFavorRatio = (pCompressor->flags & LZSA_FLAG_FAVOR_RATIO) ? 1 : 0;
|
const int nFavorRatio = (pCompressor->flags & LZSA_FLAG_FAVOR_RATIO) ? 1 : 0;
|
||||||
@ -805,7 +804,6 @@ static int lzsa_get_compressed_size_v2(lzsa_compressor *pCompressor, lzsa_match
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
int nTokenLiteralsLen = (nNumLiterals >= LITERALS_RUN_LEN_V2) ? LITERALS_RUN_LEN_V2 : nNumLiterals;
|
|
||||||
int nCommandSize = 8 /* token */ + lzsa_get_literals_varlen_size_v2(nNumLiterals) + (nNumLiterals << 3);
|
int nCommandSize = 8 /* token */ + lzsa_get_literals_varlen_size_v2(nNumLiterals) + (nNumLiterals << 3);
|
||||||
|
|
||||||
nCompressedSize += nCommandSize;
|
nCompressedSize += nCommandSize;
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "shrink_block_v2.h"
|
#include "shrink_block_v2.h"
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
#include "matchfinder.h"
|
#include "matchfinder.h"
|
||||||
|
#include "lib.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize compression context
|
* Initialize compression context
|
||||||
@ -188,23 +189,43 @@ void lzsa_compressor_destroy(lzsa_compressor *pCompressor) {
|
|||||||
*
|
*
|
||||||
* @return size of compressed data in output buffer, or -1 if the data is uncompressible
|
* @return size of compressed data in output buffer, or -1 if the data is uncompressible
|
||||||
*/
|
*/
|
||||||
int lzsa_compressor_shrink_block(lzsa_compressor *pCompressor, const unsigned char *pInWindow, const int nPreviousBlockSize, const int nInDataSize, unsigned char *pOutData, const int nMaxOutDataSize) {
|
int lzsa_compressor_shrink_block(lzsa_compressor *pCompressor, unsigned char *pInWindow, const int nPreviousBlockSize, const int nInDataSize, unsigned char *pOutData, const int nMaxOutDataSize) {
|
||||||
if (lzsa_build_suffix_array(pCompressor, pInWindow, nPreviousBlockSize + nInDataSize))
|
int nCompressedSize;
|
||||||
return -1;
|
|
||||||
if (nPreviousBlockSize) {
|
|
||||||
lzsa_skip_matches(pCompressor, 0, nPreviousBlockSize);
|
|
||||||
}
|
|
||||||
lzsa_find_all_matches(pCompressor, nPreviousBlockSize, nPreviousBlockSize + nInDataSize);
|
|
||||||
|
|
||||||
if (pCompressor->format_version == 1) {
|
if (pCompressor->flags & LZSA_FLAG_RAW_BACKWARD) {
|
||||||
return lzsa_optimize_and_write_block_v1(pCompressor, pInWindow, nPreviousBlockSize, nInDataSize, pOutData, nMaxOutDataSize);
|
lzsa_reverse_buffer(pInWindow + nPreviousBlockSize, nInDataSize);
|
||||||
}
|
|
||||||
else if (pCompressor->format_version == 2) {
|
|
||||||
return lzsa_optimize_and_write_block_v2(pCompressor, pInWindow, nPreviousBlockSize, nInDataSize, pOutData, nMaxOutDataSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lzsa_build_suffix_array(pCompressor, pInWindow, nPreviousBlockSize + nInDataSize))
|
||||||
|
nCompressedSize = -1;
|
||||||
else {
|
else {
|
||||||
return -1;
|
if (nPreviousBlockSize) {
|
||||||
|
lzsa_skip_matches(pCompressor, 0, nPreviousBlockSize);
|
||||||
|
}
|
||||||
|
lzsa_find_all_matches(pCompressor, nPreviousBlockSize, nPreviousBlockSize + nInDataSize);
|
||||||
|
|
||||||
|
if (pCompressor->format_version == 1) {
|
||||||
|
nCompressedSize = lzsa_optimize_and_write_block_v1(pCompressor, pInWindow, nPreviousBlockSize, nInDataSize, pOutData, nMaxOutDataSize);
|
||||||
|
if (nCompressedSize != -1 && (pCompressor->flags & LZSA_FLAG_RAW_BACKWARD)) {
|
||||||
|
lzsa_reverse_buffer(pOutData, nCompressedSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pCompressor->format_version == 2) {
|
||||||
|
nCompressedSize = lzsa_optimize_and_write_block_v2(pCompressor, pInWindow, nPreviousBlockSize, nInDataSize, pOutData, nMaxOutDataSize);
|
||||||
|
if (nCompressedSize != -1 && (pCompressor->flags & LZSA_FLAG_RAW_BACKWARD)) {
|
||||||
|
lzsa_reverse_buffer(pOutData, nCompressedSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nCompressedSize = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pCompressor->flags & LZSA_FLAG_RAW_BACKWARD) {
|
||||||
|
lzsa_reverse_buffer(pInWindow + nPreviousBlockSize, nInDataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nCompressedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -123,7 +123,7 @@ void lzsa_compressor_destroy(lzsa_compressor *pCompressor);
|
|||||||
*
|
*
|
||||||
* @return size of compressed data in output buffer, or -1 if the data is uncompressible
|
* @return size of compressed data in output buffer, or -1 if the data is uncompressible
|
||||||
*/
|
*/
|
||||||
int lzsa_compressor_shrink_block(lzsa_compressor *pCompressor, const unsigned char *pInWindow, const int nPreviousBlockSize, const int nInDataSize, unsigned char *pOutData, const int nMaxOutDataSize);
|
int lzsa_compressor_shrink_block(lzsa_compressor *pCompressor, unsigned char *pInWindow, const int nPreviousBlockSize, const int nInDataSize, unsigned char *pOutData, const int nMaxOutDataSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the number of compression commands issued in compressed data blocks
|
* Get the number of compression commands issued in compressed data blocks
|
||||||
|
@ -62,7 +62,7 @@ size_t lzsa_get_max_compressed_size_inmem(size_t nInputSize) {
|
|||||||
*
|
*
|
||||||
* @return actual compressed size, or -1 for error
|
* @return actual compressed size, or -1 for error
|
||||||
*/
|
*/
|
||||||
size_t lzsa_compress_inmem(const unsigned char *pInputData, unsigned char *pOutBuffer, size_t nInputSize, size_t nMaxOutBufferSize,
|
size_t lzsa_compress_inmem(unsigned char *pInputData, unsigned char *pOutBuffer, size_t nInputSize, size_t nMaxOutBufferSize,
|
||||||
const unsigned int nFlags, const int nMinMatchSize, const int nFormatVersion) {
|
const unsigned int nFlags, const int nMinMatchSize, const int nFormatVersion) {
|
||||||
lzsa_compressor compressor;
|
lzsa_compressor compressor;
|
||||||
size_t nOriginalSize = 0;
|
size_t nOriginalSize = 0;
|
||||||
|
@ -61,7 +61,7 @@ size_t lzsa_get_max_compressed_size_inmem(size_t nInputSize);
|
|||||||
*
|
*
|
||||||
* @return actual compressed size, or -1 for error
|
* @return actual compressed size, or -1 for error
|
||||||
*/
|
*/
|
||||||
size_t lzsa_compress_inmem(const unsigned char *pInputData, unsigned char *pOutBuffer, size_t nInputSize, size_t nMaxOutBufferSize,
|
size_t lzsa_compress_inmem(unsigned char *pInputData, unsigned char *pOutBuffer, size_t nInputSize, size_t nMaxOutBufferSize,
|
||||||
const unsigned int nFlags, const int nMinMatchSize, const int nFormatVersion);
|
const unsigned int nFlags, const int nMinMatchSize, const int nFormatVersion);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -70,6 +70,7 @@ static void lzsa_delete_file(const char *pszInFilename) {
|
|||||||
* @param pOriginalSize pointer to returned input(source) size, updated when this function is successful
|
* @param pOriginalSize pointer to returned input(source) size, updated when this function is successful
|
||||||
* @param pCompressedSize pointer to returned output(compressed) size, updated when this function is successful
|
* @param pCompressedSize pointer to returned output(compressed) size, updated when this function is successful
|
||||||
* @param pCommandCount pointer to returned token(compression commands) count, updated when this function is successful
|
* @param pCommandCount pointer to returned token(compression commands) count, updated when this function is successful
|
||||||
|
* @param pSafeDist pointer to return safe distance for raw blocks, updated when this function is successful
|
||||||
*
|
*
|
||||||
* @return LZSA_OK for success, or an error value from lzsa_status_t
|
* @return LZSA_OK for success, or an error value from lzsa_status_t
|
||||||
*/
|
*/
|
||||||
@ -127,6 +128,7 @@ lzsa_status_t lzsa_compress_file(const char *pszInFilename, const char *pszOutFi
|
|||||||
* @param pOriginalSize pointer to returned input(source) size, updated when this function is successful
|
* @param pOriginalSize pointer to returned input(source) size, updated when this function is successful
|
||||||
* @param pCompressedSize pointer to returned output(compressed) size, updated when this function is successful
|
* @param pCompressedSize pointer to returned output(compressed) size, updated when this function is successful
|
||||||
* @param pCommandCount pointer to returned token(compression commands) count, updated when this function is successful
|
* @param pCommandCount pointer to returned token(compression commands) count, updated when this function is successful
|
||||||
|
* @param pSafeDist pointer to return safe distance for raw blocks, updated when this function is successful
|
||||||
*
|
*
|
||||||
* @return LZSA_OK for success, or an error value from lzsa_status_t
|
* @return LZSA_OK for success, or an error value from lzsa_status_t
|
||||||
*/
|
*/
|
||||||
|
@ -57,6 +57,7 @@ typedef enum _lzsa_status_t lzsa_status_t;
|
|||||||
* @param pOriginalSize pointer to returned input(source) size, updated when this function is successful
|
* @param pOriginalSize pointer to returned input(source) size, updated when this function is successful
|
||||||
* @param pCompressedSize pointer to returned output(compressed) size, updated when this function is successful
|
* @param pCompressedSize pointer to returned output(compressed) size, updated when this function is successful
|
||||||
* @param pCommandCount pointer to returned token(compression commands) count, updated when this function is successful
|
* @param pCommandCount pointer to returned token(compression commands) count, updated when this function is successful
|
||||||
|
* @param pSafeDist pointer to return safe distance for raw blocks, updated when this function is successful
|
||||||
*
|
*
|
||||||
* @return LZSA_OK for success, or an error value from lzsa_status_t
|
* @return LZSA_OK for success, or an error value from lzsa_status_t
|
||||||
*/
|
*/
|
||||||
@ -80,6 +81,7 @@ lzsa_status_t lzsa_compress_file(const char *pszInFilename, const char *pszOutFi
|
|||||||
* @param pOriginalSize pointer to returned input(source) size, updated when this function is successful
|
* @param pOriginalSize pointer to returned input(source) size, updated when this function is successful
|
||||||
* @param pCompressedSize pointer to returned output(compressed) size, updated when this function is successful
|
* @param pCompressedSize pointer to returned output(compressed) size, updated when this function is successful
|
||||||
* @param pCommandCount pointer to returned token(compression commands) count, updated when this function is successful
|
* @param pCommandCount pointer to returned token(compression commands) count, updated when this function is successful
|
||||||
|
* @param pSafeDist pointer to return safe distance for raw blocks, updated when this function is successful
|
||||||
*
|
*
|
||||||
* @return LZSA_OK for success, or an error value from lzsa_status_t
|
* @return LZSA_OK for success, or an error value from lzsa_status_t
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user