; ; Speed-optimized MegaLZ decompressor (v.2 31/07/2019, 233 bytes) ; ; The only decompressor for MegaLZ that I know of is a relocatable ; 110 byte version written by Fyrex^MhM ; ; This non-relocatible version was optimized for speed by spke ; ; The decompression is done in the standard way: ; ; ld hl,CompressedData ; ld de,WhereToDecompress ; call DecompressMegaLZ ; ; The decompressor only modifies AF, BC, DE, HL and, possibly, IX (see below) ; ; Drop me an email if you have any comments/ideas/suggestions: zxintrospec@gmail.com ; DEFINE AllowUsingIX MACRO GET_BIT add a : call z,ReloadByte ENDM @DecompressMegaLZ: IFDEF AllowUsingIX ld ix,MainLoop ENDIF ld a,128 : jr CASE1 ReloadByte3 ld a,(hl) : inc hl : rla : jr c,CASE001 CASE000: ; "000"+ooo is a very close 1-byte match ld bc,#FFFF DUP 3 GET_BIT : rl c EDUP push hl : ld h,d : ld l,e add hl,bc ldi pop hl ; 10 + 11+4+4+11+16+10 = 66t IFDEF AllowUsingIX jp (ix) ELSE jp MainLoop ENDIF ReloadByte1 ld a,(hl) : inc hl : rla : jr nc,ProcessMatch1 DUP 2 ldi : add a : jr nc,ProcessMatch1 EDUP ; ; case "0"+BYTE: copy a single literal CASE1: ldi ; first byte is always copied as literal ; ; main decompressor loop MainLoop: add a : jr z,ReloadByte1 : jr c,CASE1 ; "1"+BYTE = copy literal ProcessMatch1 add a : jr z,ReloadByte2 : jr c,CASE01x ProcessMatch2 add a : jr z,ReloadByte3 : jr nc,CASE000 CASE001: ; "001"+[OFFSET] is a close 2-byte match ld b,#FF : ld c,(hl) : inc hl push hl : ld h,d : ld l,e add hl,bc ldi ldi pop hl IFDEF AllowUsingIX jp (ix) ELSE jp MainLoop ENDIF ReloadByte2 ld a,(hl) : inc hl : rla : jr nc,ProcessMatch2 CASE01x: ; "01" could be a 3-byte match or longer match add a : jr z,ReloadByte4 : jr c,CASE011 CASE010: ; "010" is a 3-byte match ld b,#FF GET_BIT : jr nc,ShortOffset1 DUP 4 GET_BIT : rl b EDUP dec b ShortOffset1 ld c,(hl) : inc hl ; DE = -offset push hl : ld h,d : ld l,e add hl,bc ldi ldi ldi pop hl IFDEF AllowUsingIX jp (ix) ELSE jp MainLoop ENDIF ReloadByte4 ld a,(hl) : inc hl : rla : jr nc,CASE010 CASE011: ; "011" are general length matches ld bc,1 ; BC = 1 GET_BIT : jr c,ShortLength ; significant speed-up ReadLogLength GET_BIT : inc b jr nc,ReadLogLength ReadLength GET_BIT : rl c djnz ReadLength ret c ; overflow signals the end of the data ShortLength GET_BIT inc c : rl c ; BC = len = 3 push de ld d,#FF GET_BIT : jr nc,ShortOffset2 DUP 4 GET_BIT : rl d EDUP dec d ShortOffset2 ld e,(hl) : inc hl ; DE = -offset ex (sp),hl ; HL = dest, (SP) = src ex de,hl : add hl,de ; DE = dest, HL = dest-offset ldir pop hl IFDEF AllowUsingIX jp (ix) ELSE jp MainLoop ENDIF ; ; pretty usual getbit for mixed datastreams ReloadByte: ld a,(hl) : inc hl rla : ret