; Memory locations BIT_BUFFER equ $c106 ; Current byte being read bit-by-bit DEST_ADDR_LO equ $c109 ; Low byte of original destination address DEST_ADDR_HI equ $c10a ; High byte of original destination address ; Main decompression entry point ; Input: DE = destination address, HL = pointer to compressed data header Decompress: DecompressEntry: ; Save original destination address for bounds checking ld a, e ld [DEST_ADDR_LO], a ld a, d ld [DEST_ADDR_HI], a ; Read decompressed size from header (2 bytes) ld c, [hl] inc hl ld b, [hl] inc hl push hl ; Calculate end address (DE = destination + size) ld h, d ld l, e add hl, bc ld d, h ld e, l pop hl ; Read compressed data offset (2 bytes) ld c, [hl] inc hl ld b, [hl] ; Position HL to start of compressed data add hl, bc ; Load first byte of compressed stream and initialize bit buffer ld a, [hl-] ld [BIT_BUFFER], a push hl ; Set carry flag to mark buffer as having 8 bits available ld hl, BIT_BUFFER scf rl [hl] ; Check if we're already at destination (edge case) jr c, CheckDecompressionDone ; Main decompression loop - copy literal bytes CopyLiteralBytes: call DecodeOffsetLength DecodeLiteralByte: xor a ; Start with zero ; Read 8 bits to build a complete byte call ReadBit adc a call ReadBit adc a call ReadBit adc a call ReadBit adc a call ReadBit adc a call ReadBit adc a call ReadBit adc a call ReadBit adc a ; Write decoded byte to output dec de ld [de], a ; Decrement remaining byte count dec bc ld a, b or c jr nz, DecodeLiteralByte ; Check if decompression is complete ld a, [DEST_ADDR_HI] cp d jr nz, CheckDecompressionDone ld a, [DEST_ADDR_LO] cp e jr c, CheckDecompressionDone jr DecompressionComplete ; Read next control bit and branch accordingly ReadControlBit: call ReadBit jr nc, CopyLiteralBytes ; Handle back-reference (copy from previously decompressed data) CheckDecompressionDone: call DecodeOffsetLength ; Store length in temporary location inc l ld [hl], c inc l ld [hl], b dec l dec l call DecodeOffsetLength push hl ; Adjust length (add 3 for minimum match) inc bc inc bc inc bc push bc ; Read offset from temporary storage inc l ld c, [hl] inc l ld b, [hl] ; Calculate source address (current pos - 1 - offset) ld h, d ld l, e dec hl add hl, bc pop bc ; Copy BC bytes from HL to DE (backwards) CopyMatchData: ld a, [hl-] dec de ld [de], a dec bc ld a, b or c jr nz, CopyMatchData pop hl ; Check if decompression is complete ld a, [DEST_ADDR_HI] cp d jr nz, ReadControlBit ld a, [DEST_ADDR_LO] cp e jr c, ReadControlBit DecompressionComplete: pop hl ret ; Decode variable-length offset or length value ; Returns: BC = decoded value DecodeOffsetLength: xor a ld b, a ld c, a ; Read 2 control bits to determine encoding type call ReadBitHL adc a call ReadBitHL adc a jr z, ReadFourBits_Type3 dec a jr z, ReadFourBits_Type2 dec a jr z, ReadFourBits_Type1 ; Type 0: Read 4 bits ReadFourBits_Type0: ld a, $04 ReadBitsLoop_Type0: call ReadBitHL rl c rl b dec a jr nz, ReadBitsLoop_Type0 ReadFourBits_Type1: ld a, $04 ReadBitsLoop_Type1: call ReadBitHL rl c rl b dec a jr nz, ReadBitsLoop_Type1 ReadFourBits_Type2: ld a, $04 ReadBitsLoop_Type2: call ReadBitHL rl c rl b dec a jr nz, ReadBitsLoop_Type2 ReadFourBits_Type3: ld a, $04 ReadBitsLoop_Type3: call ReadBitHL rl c rl b dec a jr nz, ReadBitsLoop_Type3 ret ; Read one bit from bitstream into carry flag ; Used during literal byte decoding ReadBit: sla [hl] ; Shift left, MSB -> carry ret nz ; Return if bits remain in buffer ; Buffer empty, reload from stream di ; Disable interrupts push af push hl add sp, $06 ; Adjust stack to access return address pop hl ld a, [hl-] ; Read next compressed byte from stream ld [BIT_BUFFER], a push hl add sp, -$06 ; Restore stack pop hl pop af rl [hl] ; Set bit 0 to 1 (marks 8 bits available) ei ; Enable interrupts ret ; Read one bit from bitstream into carry flag ; Used during offset/length decoding ReadBitHL: sla [hl] ; Shift left, MSB -> carry ret nz ; Return if bits remain in buffer ; Buffer empty, reload from stream di ; Disable interrupts push af push hl add sp, $08 ; Adjust stack to access return address pop hl ld a, [hl-] ; Read next compressed byte from stream ld [BIT_BUFFER], a push hl add sp, -$08 ; Restore stack pop hl pop af rl [hl] ; Set bit 0 to 1 (marks 8 bits available) ei ; Enable interrupts ret ; Dead code below (unreachable) add sp, -$08 pop hl pop af rl [hl] ei ret ld d, $fb ret