; 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