1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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
|