aboutsummaryrefslogtreecommitdiff
path: root/tools/rasm/decrunch
diff options
context:
space:
mode:
authorJuan J. Martinez <jjm@usebox.net>2020-12-30 19:07:31 +0000
committerJuan J. Martinez <jjm@usebox.net>2020-12-30 19:23:41 +0000
commit2682bc5d1d864341aaeb42a449db73c3ecd16d70 (patch)
tree9116764364b4ee0ce7f6037305077807b57776de /tools/rasm/decrunch
downloadubox-msx-lib-2682bc5d1d864341aaeb42a449db73c3ecd16d70.tar.gz
ubox-msx-lib-2682bc5d1d864341aaeb42a449db73c3ecd16d70.zip
Initial import1.0
Diffstat (limited to 'tools/rasm/decrunch')
-rw-r--r--tools/rasm/decrunch/aplib_z80_todo.asm190
-rw-r--r--tools/rasm/decrunch/deexo.asm118
-rw-r--r--tools/rasm/decrunch/dzx7_turbo.asm80
-rw-r--r--tools/rasm/decrunch/exomizer3megachur.asm210
-rw-r--r--tools/rasm/decrunch/lz48decrunch_v006.asm113
-rw-r--r--tools/rasm/decrunch/lz49decrunch_v001.asm138
-rw-r--r--tools/rasm/decrunch/lz4_docent.asm118
7 files changed, 967 insertions, 0 deletions
diff --git a/tools/rasm/decrunch/aplib_z80_todo.asm b/tools/rasm/decrunch/aplib_z80_todo.asm
new file mode 100644
index 0000000..6843a14
--- /dev/null
+++ b/tools/rasm/decrunch/aplib_z80_todo.asm
@@ -0,0 +1,190 @@
+;Z80 Version by Dan Weiss
+;Call depack.
+;hl = source
+;de = dest
+
+ap_bits: .db 0
+ap_byte: .db 0
+lwm: .db 0
+r0: .dw 0
+
+ap_getbit:
+ push bc
+ ld bc,(ap_bits)
+ rrc c
+ jr nc,ap_getbit_continue
+ ld b,(hl)
+ inc hl
+ap_getbit_continue:
+ ld a,c
+ and b
+ ld (ap_bits),bc
+ pop bc
+ ret
+
+ap_getbitbc: ;doubles BC and adds the read bit
+ sla c
+ rl b
+ call ap_getbit
+ ret z
+ inc bc
+ ret
+
+ap_getgamma:
+ ld bc,1
+ap_getgammaloop:
+ call ap_getbitbc
+ call ap_getbit
+ jr nz,ap_getgammaloop
+ ret
+
+
+depack:
+ ;hl = source
+ ;de = dest
+ ldi
+ xor a
+ ld (lwm),a
+ inc a
+ ld (ap_bits),a
+
+aploop:
+ call ap_getbit
+ jp z, apbranch1
+ call ap_getbit
+ jr z, apbranch2
+ call ap_getbit
+ jr z, apbranch3
+ ;LWM = 0
+ xor a
+ ld (lwm),a
+ ;get an offset
+ ld bc,0
+ call ap_getbitbc
+ call ap_getbitbc
+ call ap_getbitbc
+ call ap_getbitbc
+ ld a,b
+ or c
+ jr nz,apbranch4
+ xor a ;write a 0
+ ld (de),a
+ inc de
+ jr aploop
+apbranch4:
+ ex de,hl ;write a previous bit (1-15 away from dest)
+ push hl
+ sbc hl,bc
+ ld a,(hl)
+ pop hl
+ ld (hl),a
+ inc hl
+ ex de,hl
+ jr aploop
+apbranch3:
+ ;use 7 bit offset, length = 2 or 3
+ ;if a zero is encountered here, it's EOF
+ ld c,(hl)
+ inc hl
+ rr c
+ ret z
+ ld b,2
+ jr nc,ap_dont_inc_b
+ inc b
+ap_dont_inc_b:
+ ;LWM = 1
+ ld a,1
+ ld (lwm),a
+
+ push hl
+ ld a,b
+ ld b,0
+ ;R0 = c
+ ld (r0),bc
+ ld h,d
+ ld l,e
+ or a
+ sbc hl,bc
+ ld c,a
+ ldir
+ pop hl
+ jr aploop
+apbranch2:
+ ;use a gamma code * 256 for offset, another gamma code for length
+ call ap_getgamma
+ dec bc
+ dec bc
+ ld a,(lwm)
+ or a
+ jr nz,ap_not_lwm
+ ;bc = 2?
+ ld a,b
+ or c
+ jr nz,ap_not_zero_gamma
+ ;if gamma code is 2, use old r0 offset, and a new gamma code for length
+ call ap_getgamma
+ push hl
+ ld h,d
+ ld l,e
+ push bc
+ ld bc,(r0)
+ sbc hl,bc
+ pop bc
+ ldir
+ pop hl
+ jr ap_finishup
+
+ap_not_zero_gamma:
+ dec bc
+ap_not_lwm:
+ ;do I even need this code?
+ ;bc=bc*256+(hl), lazy 16bit way
+ ld b,c
+ ld c,(hl)
+ inc hl
+ ld (r0),bc
+ push bc
+ call ap_getgamma
+ ex (sp),hl
+ ;bc = len, hl=offs
+ push de
+ ex de,hl
+ ;some comparison junk for some reason
+ ld hl,31999
+ or a
+ sbc hl,de
+ jr nc,skip1
+ inc bc
+skip1:
+ ld hl,1279
+ or a
+ sbc hl,de
+ jr nc,skip2
+ inc bc
+skip2:
+ ld hl,127
+ or a
+ sbc hl,de
+ jr c,skip3
+ inc bc
+ inc bc
+skip3:
+ ;bc = len, de = offs, hl=junk
+ pop hl
+ push hl
+ or a
+ sbc hl,de
+ pop de
+ ;hl=dest-offs, bc=len, de = dest
+ ldir
+ pop hl
+ap_finishup:
+ ld a,1
+ ld (lwm),a
+ jp aploop
+
+apbranch1:
+ ldi
+ xor a
+ ld (lwm),a
+ jp aploop
diff --git a/tools/rasm/decrunch/deexo.asm b/tools/rasm/decrunch/deexo.asm
new file mode 100644
index 0000000..6a4a7ac
--- /dev/null
+++ b/tools/rasm/decrunch/deexo.asm
@@ -0,0 +1,118 @@
+;Exomizer 2 Z80 decoder
+; by Metalbrain
+;
+; optimized by Antonio Villena and Urusergi (169 bytes)
+;
+; compression algorithm by Magnus Lind
+
+;input: hl=compressed data start
+; de=uncompressed destination start
+;
+; you may change exo_mapbasebits to point to any free buffer
+;
+;ATTENTION!
+;A huge speed boost (around 14%) can be gained at the cost of only 5 bytes.
+;If you want this, replace all instances of "call exo_getbit" with "srl a" followed by
+;"call z,exo_getbit", and remove the first two instructions in exo_getbit routine.
+
+Macro Mizoumizeur
+
+@deexo: ld iy, @exo_mapbasebits+11
+ ld a, (hl)
+ inc hl
+ ld b, 52
+ push de
+ cp a
+@exo_initbits: ld c, 16
+ jr nz, @exo_get4bits
+ ld ixl, c
+ ld de, 1 ;DE=b2
+@exo_get4bits: srl a: call z, @exo_getbit ;get one bit
+ rl c
+ jr nc, @exo_get4bits
+ inc c
+ push hl
+ ld hl, 1
+ ld (iy+41), c ;bits[i]=b1 (and opcode 41 == add hl,hl)
+@exo_setbit: dec c
+ jr nz, @exo_setbit-1 ;jump to add hl,hl instruction
+ ld (iy-11), e
+ ld (iy+93), d ;base[i]=b2
+ add hl, de
+ ex de, hl
+ inc iy
+ pop hl
+ dec ixl
+ djnz @exo_initbits
+ pop de
+ jr @exo_mainloop
+@exo_literalrun: ld e, c ;DE=1
+@exo_getbits: dec b
+ ret z
+@exo_getbits1: srl a : call z,@exo_getbit
+ rl e
+ rl d
+ jr nc, @exo_getbits
+ ld b, d
+ ld c, e
+ pop de
+@exo_literalcopy:ldir
+@exo_mainloop: inc c
+ srl a : call z,@exo_getbit ;literal?
+ jr c, @exo_literalcopy
+ ld c, 239
+@exo_getindex: srl a : call z,@exo_getbit
+ inc c
+ jr nc,@exo_getindex
+ ret z
+ push de
+ ld d, b
+ jp p, @exo_literalrun
+ ld iy, @exo_mapbasebits-229
+ call @exo_getpair
+ push de
+ rlc d
+ jr nz, @exo_dontgo
+ dec e
+ ld bc, 512+32 ;2 bits, 48 offset
+ jr z, @exo_goforit
+ dec e ;2?
+@exo_dontgo: ld bc, 1024+16 ;4 bits, 32 offset
+ jr z, @exo_goforit
+ ld de, 0
+ ld c, d ;16 offset
+@exo_goforit: call @exo_getbits1
+ ld iy, @exo_mapbasebits+27
+ add iy, de
+ call @exo_getpair
+ pop bc
+ ex (sp), hl
+ push hl
+ sbc hl, de
+ pop de
+ ldir
+ pop hl
+ jr @exo_mainloop ;Next!
+
+@exo_getpair: add iy, bc
+ ld e, d
+ ld b, (iy+41)
+ call @exo_getbits
+ ex de, hl
+ ld c, (iy-11)
+ ld b, (iy+93)
+ add hl, bc ;Always clear C flag
+ ex de, hl
+ ret
+
+@exo_getbit: ; srl a
+ ;ret nz
+ ld a, (hl)
+ inc hl
+ rra
+ ret
+
+@exo_mapbasebits: defs 156 ;tables for bits, baseL, baseH
+
+Mend
+
diff --git a/tools/rasm/decrunch/dzx7_turbo.asm b/tools/rasm/decrunch/dzx7_turbo.asm
new file mode 100644
index 0000000..779ced5
--- /dev/null
+++ b/tools/rasm/decrunch/dzx7_turbo.asm
@@ -0,0 +1,80 @@
+; -----------------------------------------------------------------------------
+; ZX7 decoder by Einar Saukas & Urusergi
+; "Turbo" version (88 bytes, 25% faster)
+; -----------------------------------------------------------------------------
+; Parameters:
+; HL: source address (compressed data)
+; DE: destination address (decompressing)
+; -----------------------------------------------------------------------------
+
+dzx7_turbo:
+ ld a, $80
+dzx7t_copy_byte_loop:
+ ldi ; copy literal byte
+dzx7t_main_loop:
+ add a, a ; check next bit
+ call z, dzx7t_load_bits ; no more bits left?
+ jr nc, dzx7t_copy_byte_loop ; next bit indicates either literal or sequence
+
+; determine number of bits used for length (Elias gamma coding)
+ push de
+ ld bc, 1
+ ld d, b
+dzx7t_len_size_loop:
+ inc d
+ add a, a ; check next bit
+ call z, dzx7t_load_bits ; no more bits left?
+ jr nc, dzx7t_len_size_loop
+ jp dzx7t_len_value_start
+
+; determine length
+dzx7t_len_value_loop:
+ add a, a ; check next bit
+ call z, dzx7t_load_bits ; no more bits left?
+ rl c
+ rl b
+ jr c, dzx7t_exit ; check end marker
+dzx7t_len_value_start:
+ dec d
+ jr nz, dzx7t_len_value_loop
+ inc bc ; adjust length
+
+; determine offset
+ ld e, (hl) ; load offset flag (1 bit) + offset value (7 bits)
+ inc hl
+ defb $cb, $33 ; opcode for undocumented instruction "SLL E" aka "SLS E"
+ jr nc, dzx7t_offset_end ; if offset flag is set, load 4 extra bits
+ add a, a ; check next bit
+ call z, dzx7t_load_bits ; no more bits left?
+ rl d ; insert first bit into D
+ add a, a ; check next bit
+ call z, dzx7t_load_bits ; no more bits left?
+ rl d ; insert second bit into D
+ add a, a ; check next bit
+ call z, dzx7t_load_bits ; no more bits left?
+ rl d ; insert third bit into D
+ add a, a ; check next bit
+ call z, dzx7t_load_bits ; no more bits left?
+ ccf
+ jr c, dzx7t_offset_end
+ inc d ; equivalent to adding 128 to DE
+dzx7t_offset_end:
+ rr e ; insert inverted fourth bit into E
+
+; copy previous sequence
+ ex (sp), hl ; store source, restore destination
+ push hl ; store destination
+ sbc hl, de ; HL = destination - offset - 1
+ pop de ; DE = destination
+ ldir
+dzx7t_exit:
+ pop hl ; restore source address (compressed data)
+ jp nc, dzx7t_main_loop
+
+dzx7t_load_bits:
+ ld a, (hl) ; load another group of 8 bits
+ inc hl
+ rla
+ ret
+
+; -----------------------------------------------------------------------------
diff --git a/tools/rasm/decrunch/exomizer3megachur.asm b/tools/rasm/decrunch/exomizer3megachur.asm
new file mode 100644
index 0000000..ea1973e
--- /dev/null
+++ b/tools/rasm/decrunch/exomizer3megachur.asm
@@ -0,0 +1,210 @@
+;Exomizer 2 Z80 decoder
+;Copyright (C) 2008-2016 by Jaime Tejedor Gomez (Metalbrain)
+;
+;Optimized by Antonio Villena and Urusergi (169 bytes)
+;
+;Compression algorithm by Magnus Lind
+;
+; This depacker is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2.1 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;
+;
+;input- hl=compressed data start
+; de=uncompressed destination start
+;
+; you may change exo_mapbasebits to point to any free buffer
+;
+;ATTENTION!
+;A huge speed boost (around 14%) can be gained at the cost of only 5 bytes.
+;If you want this, replace all instances of "call exo_getbit" with "srl a" followed by
+;"call z,exo_getbit", and remove the first two instructions in exo_getbit routine.
+; ---------------------------
+; modified by Megachur in 2018
+; ---------------------------
+; hl -> compressed data start
+; de -> uncompressed destination start
+; ---------------------------
+
+;EXO_BACKWARD equ 1
+ENABLE_MEXO_GETBIT equ 1
+
+list:EXOMIZER_ADDRESS:nolist
+; ---------------------------
+MACRO MEXO_GETBIT
+ srl a
+ jr nz,@1
+ ld a,(hl)
+ IFDEF EXO_BACKWARD
+ dec hl
+ ELSE
+ inc hl
+ ENDIF
+ rra
+@1
+ENDM
+
+deexo:
+ ld iy,exo_mapbasebits+11
+ ld a,(hl)
+
+ IFDEF EXO_BACKWARD
+ dec hl
+ ELSE
+ inc hl
+ ENDIF
+
+ ld b,52
+ push de
+ cp a
+
+exo_initbits:
+ ld c,16
+ jr nz,exo_get4bits
+ ld ixl,c
+ ld de,1 ;DE=b2
+
+exo_get4bits:
+ IFDEF ENABLE_MEXO_GETBIT
+ MEXO_GETBIT
+ ELSE
+ srl a:call z,exo_getbit ;call exo_getbit ;get one bit
+ ENDIF
+ rl c
+ jr nc,exo_get4bits
+ inc c
+ push hl
+ ld hl,1
+ ld (iy+41),c ;bits[i]=b1 (and opcode 41 == add hl,hl)
+
+exo_setbit:
+ dec c
+ jr nz,exo_setbit-1 ;jump to add hl,hl instruction
+ ld (iy-11),e
+ ld (iy+93),d ;base[i]=b2
+ add hl,de
+ ex de,hl
+ inc iy
+ pop hl
+ dec ixl
+ djnz exo_initbits
+ pop de
+ jr exo_mainloop
+
+exo_literalrun:
+ ld e,c ;DE=1
+
+exo_getbits:
+ dec b
+ ret z
+
+exo_getbits1:
+ IFDEF ENABLE_MEXO_GETBIT
+ MEXO_GETBIT
+ ELSE
+ srl a:call z,exo_getbit ;call exo_getbit
+ ENDIF
+ rl e
+ rl d
+ jr nc,exo_getbits
+ ld b,d
+ ld c,e
+ pop de
+
+exo_literalcopy:
+ IFDEF EXO_BACKWARD
+ lddr
+ ELSE
+ ldir
+ ENDIF
+exo_mainloop:
+ inc c
+ IFDEF ENABLE_MEXO_GETBIT
+ MEXO_GETBIT
+ ELSE
+ srl a:call z,exo_getbit ;call exo_getbit ;literal?
+ ENDIF
+ jr c,exo_literalcopy
+ ld c,239
+exo_getindex:
+ IFDEF ENABLE_MEXO_GETBIT
+ MEXO_GETBIT
+ ELSE
+ srl a:call z,exo_getbit ;call exo_getbit
+ ENDIF
+ inc c
+ jr nc,exo_getindex
+ ret z
+ push de
+ ld d,b
+ jp p,exo_literalrun
+ ld iy,exo_mapbasebits-229
+ call exo_getpair
+ push de
+ rlc d
+ jr nz,exo_dontgo
+ dec e
+ ld bc,512+32 ;2 bits,48 offset
+ jr z,exo_goforit
+ dec e ;2?
+exo_dontgo:
+ ld bc,1024+16 ;4 bits,32 offset
+ jr z,exo_goforit
+ ld de,0
+ ld c,d ;16 offset
+exo_goforit:
+ call exo_getbits1
+ ld iy,exo_mapbasebits+27
+ add iy,de
+ call exo_getpair
+ pop bc
+ ex (sp),hl
+ IFDEF EXO_BACKWARD
+ ex de,hl
+ add hl,de
+ lddr
+ ELSE
+ push hl
+ sbc hl,de
+ pop de
+ ldir
+ ENDIF
+ pop hl
+ jr exo_mainloop ;Next!
+exo_getpair:
+ add iy,bc
+ ld e,d
+ ld b,(iy+41)
+ call exo_getbits
+ ex de,hl
+ ld c,(iy-11)
+ ld b,(iy+93)
+ add hl,bc ;Always clear C flag
+ ex de,hl
+ ret
+
+ IFDEF ENABLE_MEXO_GETBIT
+ ELSE
+exo_getbit:
+; srl a
+; ret nz
+ ld a,(hl)
+ inc hl
+ rra
+ ret
+ ENDIF
+
+exo_mapbasebits:
+ ds 156,#00 ;tables for bits,baseL,baseH
+; ---------------------------
+list:EXOMIZER_ADDRESS_LENGTH equ $-EXOMIZER_ADDRESS:nolist \ No newline at end of file
diff --git a/tools/rasm/decrunch/lz48decrunch_v006.asm b/tools/rasm/decrunch/lz48decrunch_v006.asm
new file mode 100644
index 0000000..750b571
--- /dev/null
+++ b/tools/rasm/decrunch/lz48decrunch_v006.asm
@@ -0,0 +1,113 @@
+;
+; LZ48 decrunch
+;
+; hl compressed data adress
+; de output adress of data
+;
+
+
+org #8000
+
+; CALL #8000,source,destination
+di
+
+; parameters
+ld h,(ix+3)
+ld l,(ix+2)
+ld d,(ix+1)
+ld e,(ix+0)
+
+call LZ48_decrunch
+
+ei
+ret
+
+
+
+
+
+LZ48_decrunch
+ldi
+ld b,0
+
+nextsequence
+ld a,(hl)
+inc hl
+ld lx,a
+and #F0
+jr z,lzunpack ; no litteral bytes
+rrca
+rrca
+rrca
+rrca
+
+ld c,a
+cp 15 ; more bytes for length?
+jr nz,copyliteral
+
+getadditionallength
+ld a,(hl)
+inc hl
+inc a
+jr nz,lengthnext
+inc b
+dec bc
+jr getadditionallength
+lengthnext
+dec a
+add a,c
+ld c,a
+ld a,b
+adc a,0
+ld b,a ; bc=length
+
+copyliteral
+ldir
+
+lzunpack
+ld a,lx
+and #F
+add 3
+ld c,a
+cp 18 ; more bytes for length?
+jr nz,readoffset
+
+getadditionallengthbis
+ld a,(hl)
+inc hl
+inc a
+jr nz,lengthnextbis
+inc b
+dec bc
+jr getadditionallengthbis
+lengthnextbis
+dec a
+add a,c
+ld c,a
+ld a,b
+adc a,0
+ld b,a ; bc=length
+
+readoffset
+; read encoded offset
+ld a,(hl)
+inc a
+ret z ; LZ48 end with zero offset
+inc hl
+push hl
+ld l,a
+ld a,e
+sub l
+ld l,a
+ld a,d
+sbc a,0
+ld h,a
+; source=dest-copyoffset
+
+copykey
+ldir
+
+pop hl
+jr nextsequence
+
+
diff --git a/tools/rasm/decrunch/lz49decrunch_v001.asm b/tools/rasm/decrunch/lz49decrunch_v001.asm
new file mode 100644
index 0000000..7f811b5
--- /dev/null
+++ b/tools/rasm/decrunch/lz49decrunch_v001.asm
@@ -0,0 +1,138 @@
+;
+; LZ48 decrunch
+; input
+; hl compressed data adress
+; de output adress of data
+;
+; output
+; hl last adress of compressed data read (you must inc once for LZ48 stream)
+; de last adress of decrunched data write +1
+; bc always 3
+; a always zero
+; lx undetermined
+; flags (inc a -> 0)
+
+org #8000
+
+; CALL #8000,source,destination
+di
+
+; parameters
+ld h,(ix+3)
+ld l,(ix+2)
+ld d,(ix+1)
+ld e,(ix+0)
+
+call LZ49_decrunch
+
+ei
+ret
+
+
+
+
+
+LZ49_decrunch
+ldi
+ld b,0
+
+nextsequence
+ld a,(hl)
+inc hl
+ld lx,a
+and #70
+jr z,lzunpack ; no litteral bytes
+rrca
+rrca
+rrca
+rrca
+
+ld c,a
+cp 7 ; more bytes for length?
+jr nz,copyliteral
+
+getadditionallength
+ld a,(hl)
+inc hl
+inc a
+jr nz,lengthnext
+inc b
+dec bc
+jr getadditionallength
+lengthnext
+dec a
+add a,c
+ld c,a
+ld a,b
+adc a,0
+ld b,a ; bc=length
+
+copyliteral
+ldir
+
+lzunpack
+ld a,lx
+and #F
+add 3
+ld c,a
+cp 18 ; more bytes for length?
+jr nz,readoffset
+
+getadditionallengthbis
+ld a,(hl)
+inc hl
+inc a
+jr nz,lengthnextbis
+inc b
+dec bc
+jr getadditionallengthbis
+lengthnextbis
+dec a
+add a,c
+ld c,a
+ld a,b
+adc a,0
+ld b,a ; bc=length
+
+readoffset
+ld a,lx
+add a
+jr c,extendedoffset
+; read encoded offset
+ld a,(hl)
+inc a
+ret z ; LZ48 end with zero offset
+inc hl
+push hl
+ld l,a
+ld a,e
+sub l
+ld l,a
+ld a,d
+sbc a,0
+ld h,a
+; source=dest-copyoffset
+ldir
+pop hl
+jr nextsequence
+
+extendedoffset
+ld a,(hl)
+inc hl
+push hl
+inc a
+ld l,a
+ld a,e
+sub l
+ld l,a
+ld a,d
+sbc a,1
+ld h,a
+; source=dest-copyoffset
+ldir
+pop hl
+jr nextsequence
+
+
+
+
diff --git a/tools/rasm/decrunch/lz4_docent.asm b/tools/rasm/decrunch/lz4_docent.asm
new file mode 100644
index 0000000..a0b2188
--- /dev/null
+++ b/tools/rasm/decrunch/lz4_docent.asm
@@ -0,0 +1,118 @@
+; decompress raw lz4 data packet
+; on entry hl - start of packed buffer, de - destination buffer, bc - size of packed data
+LZ4_decompress_raw:
+ push de ; store original destination pointer
+ push hl ; store start of compressed data source
+ add hl,bc ; calculate end address of compressed block
+ ld b,h ; move end address of compressed data to bc
+ ld c,l
+ pop hl ; restore start of compressed data source
+ push bc ; store end address of compessed data
+; now hl - start of packed buffer, de - destination, bc - end of packed buffer
+ ld b,0 ; clear b, c is set later
+
+; get decompression token
+LZ4_GetToken:
+ xor a ; reset c flag for sbc later
+ ld a,(hl) ; read token
+ inc hl
+ push af ; store token
+; unpack 4 high bits to get the length of literal
+ rlca
+ rlca
+ rlca
+ rlca
+; copy literals
+ and #f ; token can be max 15 - mask out unimportant bits
+ jr z,LZ4_skipcalc ; there is no literals, skip calculation of literal size
+ ld c,a ; set the count for calculation
+ cp #f ; if literal size <15
+ jr nz, LZ4_copyliterals ; copy literal, else
+; calculate total literal size by adding contents of following bytes
+ push de ; store destination
+ ex de,hl
+; a = size of literal to copy, de=pointer to data to be added
+ ld h,0 ; set hl with size of literal to copy
+ ld l,a
+
+LZ4_calcloop:
+ ld a,(de) ; get additional literal size to add
+ inc de
+ ld c,a ; set bc to the length of literal
+ add hl,bc ; add it to the total literal length
+ cp #ff ; if literal=255
+ jr z,LZ4_calcloop ; continue calculating the total literal size
+ ld b,h ; store total literal size to copy in bc
+ ld c,l
+ ex de,hl ; hl now contains current compressed data pointer
+ pop de ; restore destination to de
+
+LZ4_copyliterals:
+ ldir ; copy literal to destination
+
+LZ4_skipcalc:
+; check for end of compressed data
+ pop af ; restore token, carry is cleared because of xor a at the beginning of GetToken
+ pop bc ; restore end address of compressed data
+ push hl ; store current compressed data pointer
+ sbc hl, bc ; check if we reached the end of compressed data buffer
+ pop hl ; restore current compressed data pointer
+ jr z,LZ4_decompress_success ; decompression finished
+ push bc ; store end address of compressed data
+
+; Copy Matches
+ and #f ; token can be max 15 - mask out unimportant bits. resets also c flag for sbc later
+; get the offset
+ ld c,(hl)
+ inc hl
+ ld b,(hl) ; bc now contains the offset
+ inc hl
+ push hl ; store current compressed data pointer
+ push de ; store destination pointer
+
+ ex de,hl
+ sbc hl,bc ; calculate from the offset the new decompressed data source to copy from
+; hl contains new copy source, de source ptr
+
+ ld b,0 ; load bc with the token
+ ld c,a
+ cp #f ; if matchlength <15
+ jr nz, LZ4_copymatches ; copy matches. else
+
+; calculate total matchlength by adding additional bytes
+ push hl ; store current decompressed data source
+; a = size of match to copy, de= pointer to data to be added
+ ld h,0 ; set hl with initial matchlength to copy
+ ld l,a
+LZ4_calcloop2:
+ ld a,(de) ; get additional matchlength to add
+ inc de
+ ld c,a ; set bc to the matchlength
+ add hl,bc ; add it to the total match length
+ cp #ff ; if matchlength=255
+ jr z,LZ4_calcloop2 ; continue calculating the total match length
+ ld b,h ; store total matchlength to copy in bc
+ ld c,l
+ pop hl ; restore current decompressed data source
+ pop af ; set stack to proper position by restoring destination pointer temporarily into af
+ ex de,hl
+ ex (sp),hl ; update current compressed data pointer on the stack to the new value from de
+ ex de,hl
+ push af ; restore stack
+
+LZ4_copymatches:
+ pop de ; restore destination pointer
+ inc bc ; add base length of 4 to get the correct size of matchlength
+ inc bc
+ inc bc
+ inc bc
+ ldir ; copy match
+ pop hl ; restore current compressed data source
+ jr LZ4_GetToken ; continue decompression
+LZ4_decompress_success:
+ pop hl ; store destination pointer
+ sbc hl,de ; calculate the number of decompressed bytes
+ xor a ; clear exit code
+ ret
+
+