aboutsummaryrefslogtreecommitdiff
path: root/tools/rasm/decrunch/unlzsa2_fast.asm
diff options
context:
space:
mode:
authorJuan J. Martinez <jjm@usebox.net>2022-09-06 07:37:20 +0100
committerJuan J. Martinez <jjm@usebox.net>2022-09-06 07:37:20 +0100
commit30bf0f51335e87812ffeb54e9437f0b6a1514d67 (patch)
tree9c85a2de53b4da69fcfaa84488cc6c12ebd3e5d0 /tools/rasm/decrunch/unlzsa2_fast.asm
parentd8990284057e6401d0374f439df51879595d804d (diff)
downloadubox-msx-lib-30bf0f51335e87812ffeb54e9437f0b6a1514d67.tar.gz
ubox-msx-lib-30bf0f51335e87812ffeb54e9437f0b6a1514d67.zip
Updated rasm to 1.7
Diffstat (limited to 'tools/rasm/decrunch/unlzsa2_fast.asm')
-rwxr-xr-xtools/rasm/decrunch/unlzsa2_fast.asm189
1 files changed, 189 insertions, 0 deletions
diff --git a/tools/rasm/decrunch/unlzsa2_fast.asm b/tools/rasm/decrunch/unlzsa2_fast.asm
new file mode 100755
index 0000000..8c6b5b1
--- /dev/null
+++ b/tools/rasm/decrunch/unlzsa2_fast.asm
@@ -0,0 +1,189 @@
+;
+; Speed-optimized LZSA2 decompressor by spke & uniabis (216 bytes)
+;
+
+ DEFINE UNROLL_LONG_MATCHES ; uncomment for faster decompression of very compressible data (+38 bytes)
+; DEFINE BACKWARD_DECOMPRESS ; uncomment for data compressed with option -b
+
+ IFNDEF BACKWARD_DECOMPRESS
+
+ MACRO NEXT_HL
+ inc hl
+ ENDM
+
+ MACRO ADD_OFFSET
+ ex de,hl : add hl,de
+ ENDM
+
+ MACRO COPY1
+ ldi
+ ENDM
+
+ MACRO COPYBC
+ ldir
+ ENDM
+
+ ELSE
+
+ MACRO NEXT_HL
+ dec hl
+ ENDM
+
+ MACRO ADD_OFFSET
+ ex de,hl : ld a,e : sub l : ld l,a
+ ld a,d : sbc h : ld h,a ; 4*4+3*4 = 28t / 7 bytes
+ ENDM
+
+ MACRO COPY1
+ ldd
+ ENDM
+
+ MACRO COPYBC
+ lddr
+ ENDM
+
+ ENDIF
+
+
+macro DecompressLZSA2
+@lzsa2
+ ; A' stores next nibble as %1111.... or assumed to contain trash
+ ; B is assumed to be 0
+ ld b,0 : scf : exa : jr .ReadToken
+
+.ManyLiterals: ld a,18 : add (hl) : NEXT_HL : jr nc,.CopyLiterals
+ ld c,(hl) : NEXT_HL
+ ld a,b : ld b,(hl)
+ jr .NEXTHLuseBC
+
+
+.MoreLiterals: ld b,(hl) : NEXT_HL
+ scf : exa : jr nc,.noUpdatemoar
+
+ ld a,(hl) : or #F0 : exa
+ ld a,(hl) : NEXT_HL : or #0F
+ rrca : rrca : rrca : rrca
+
+.noUpdatemoar ;sub #F0-3 : cp 15+3 : jr z,ManyLiterals
+ inc a : jr z,.ManyLiterals : sub #F0-3+1
+
+.CopyLiterals: ld c,a : ld a,b : ld b,0
+ COPYBC
+ push de : or a : jp p,.CASE0xx ;: jr CASE1xx
+
+ cp %11000000 : jr c,.CASE10x
+
+.CASE11x cp %11100000 : jr c,.CASE110
+
+ ; "111": repeated offset
+.CASE111: ld de,ix : jr .MatchLen
+
+
+.Literals0011: jr nz,.MoreLiterals
+
+ ; if "LL" of the byte token is equal to 0,
+ ; there are no literals to copy
+.NoLiterals: or (hl) : NEXT_HL
+ push de : jp m,.CASE1xx
+
+ ; short (5 or 9 bit long) offsets
+.CASE0xx ld d,#FF : cp %01000000 : jr c,.CASE00x
+
+ ; "01x": the case of the 9-bit offset
+.CASE01x: cp %01100000 : rl d
+
+.ReadOffsetE ld e,(hl) : NEXT_HL
+
+.SaveOffset: LD ix,de
+
+.MatchLen: inc a : and %00000111 : jr z,.LongerMatch : inc a
+
+.CopyMatch: ld c,a
+;.useC
+ ex (sp),hl ; BC = len, DE = offset, HL = dest, SP ->[dest,src]
+ ADD_OFFSET ; BC = len, DE = dest, HL = dest-offset, SP->[src]
+ COPY1
+ COPYBC
+.popSrc pop hl
+
+ ; compressed data stream contains records
+ ; each record begins with the byte token "XYZ|LL|MMM"
+.ReadToken: ld a,(hl) : and %00011000 : jp pe,.Literals0011 ; process the cases 00 and 11 separately
+
+ rrca : rrca : rrca
+
+ ld c,a : ld a,(hl) ; token is re-read for further processing
+.NEXTHLuseBC NEXT_HL
+ COPYBC
+
+ ; the token and literals are followed by the offset
+ push de : or a : jp p,.CASE0xx
+
+.CASE1xx cp %11000000 : jr nc,.CASE11x
+
+ ; "10x": the case of the 13-bit offset
+.CASE10x: ld c,a : exa : jr nc,.noUpdatecase10x
+
+ ld a,(hl) : or #F0 : exa
+ ld a,(hl) : NEXT_HL : or #0F
+ rrca : rrca : rrca : rrca
+
+.noUpdatecase10x ld d,a : ld a,c
+ cp %10100000 : dec d : rl d : jr .ReadOffsetE
+
+
+
+ ; "110": 16-bit offset
+.CASE110: ld d,(hl) : NEXT_HL : jr .ReadOffsetE
+
+
+
+
+ ; "00x": the case of the 5-bit offset
+.CASE00x: ld c,a : exa : jr nc,.noUpdatecase00x
+
+ ld a,(hl) : or #F0 : exa
+ ld a,(hl) : NEXT_HL : or #0F
+ rrca : rrca : rrca : rrca
+
+.noUpdatecase00x ld e,a : ld a,c
+ cp %00100000 : rl e : jp .SaveOffset
+
+
+.LongerMatch: scf : exa : jr nc,.noUpdatelongermatch
+
+ ld a,(hl) : or #F0 : exa
+ ld a,(hl) : NEXT_HL : or #0F
+ rrca : rrca : rrca : rrca
+
+.noUpdatelongermatch sub #F0-9 : cp 15+9 : jr c,.CopyMatch
+
+
+.LongMatch: add (hl) : NEXT_HL : jr c,.VeryLongMatch
+
+ ld c,a
+.useC ex (sp),hl
+ ADD_OFFSET
+ COPY1
+
+ ; this is an unrolled equivalent of LDIR
+ xor a : sub c
+ and 32-1 : add a
+ ld (.jrOffset),a : jr nz,$+2
+.jrOffset EQU $-1
+.fastLDIR repeat 32
+ COPY1
+ rend
+ jp pe,.fastLDIR
+ jp .popSrc
+
+.VeryLongMatch: ld c,(hl) : NEXT_HL
+ ld b,(hl) : NEXT_HL : jr nz,.useC
+ pop de : ret
+
+mend
+
+
+
+
+