decompCode1Begin:
phase 00008h
readBit: ; RST 08H:
srl c ; read a compressed bit to carry
ret nz
rst 010h ; read next byte to shift register
rra
ld c, a
ret
; -----------------------------------------------------------------------------
if $ < 00010h
block 00010h - $, 000h
endif
readByte: ; RST 10H:
exx ; read a compressed byte to A
ld a, b
ld b, c ; use a 2-byte buffer
dec hl
ld c, (hl)
exx
if NO_BORDER_FX == 0
out (081h), a
endif
ret
decompressData_1:
sbc hl, de ; calculate and store
ld (readLength.l1 + 1), hl ; 2's complement of start address
jr decompressData_2
; -----------------------------------------------------------------------------
if $ < 00020h
block 00020h - $, 000h
endif
readLength: ; RST 20H: read and decode length value
; NOTE: B should be set to zero
.l1: ld hl, 00000h ; * 2's complement of start address
add hl, de ; check write address:
jr c, readLength_.l2
jr decompressDone ; all data has been decompressed
; -----------------------------------------------------------------------------
if $ < 00028h
block 00028h - $, 000h
endif
decompressData: ; RST 28H: load compressed data to DE
call readWordFromFile ; get compressed data size
xor a
ld l, a
ld h, a
jr decompressData_1
dephase
decompCode1End:
; -----------------------------------------------------------------------------
decompCode2Begin:
phase 00060h
readLength_:
.l1: inc b ; read prefix
.l2: rst 008h
jr c, .l1
readBits_:
dec b ; read B (can be 0) bits to HL, and
.l1: ld hl, 1 ; add a leading '1' bit
inc b ; (e.g. B=7 would read 1xxxxxxxb)
ret z
readBits:
.l1: rst 008h ; shift B (must be > 0) bits to HL
adc hl, hl ; HL is expected to be initialized
.l2: djnz .l1 ; to 0 or 1
ret
decompressDone:
pop de ; pop return address of readLength
pop de
.l1: ld l, e ; DE = HL = last write address + 1
ld h, d
xor a ; A = 0 (no error)
ld c, a ; BC = 0 (all data has been loaded)
if NO_BORDER_FX == 0
out (081h), a ; reset border color
endif
ei
ret
decompressData_2:
inc a ; A = 1 (input file channel number)
exos 6 ; read compressed data
call readWordFromFile ; get uncompressedSize - compressedSize
ld a, c
or b
jr z, decompressDone.l1 ; uncompressed data ?
di
push de
exx
pop hl ; HL' = compressed data read addr. + 1
exx
ex de, hl
add hl, bc
push hl
dec hl
ex de, hl ; DE = decompressed data write address
ld bc, 00001h ; initialize shift register
rst 010h ; fill input buffer (2 bytes)
rst 010h
.l1: rst 020h ; read literal sequence length
.l2: rst 010h ; copy literal data
ld (de), a
dec de
dec hl
ld a, l
or h
jr nz, .l2
.l3: rst 020h ; get match length - 1
push hl
ld a, l
ld l, b
ld b, 4
dec a
or h
jr z, .l5 ; match length = 2 bytes ?
call readBits ; read offset prefix (4 bits)
ld b, l
call readBits_ ; read offset bits
.l4: add hl, de ; calculate source address
ld a, c ; save shift register
ldd
pop bc ; BC = match length - 1
lddr ; expand match
ld c, a
rst 008h ; read flag bit:
jr nc, .l1 ; 0: literal sequence
jr .l3 ; 1: LZ77 match
.l5: call readBits.l2 ; special case for 2-byte matches:
ld b, l ; prefix length = 3 bits,
call readBits_.l1 ; encoding is 12345678, max offset: 510
dec hl
jr .l4
readWordFromFile: ; read a 16-bit LSB first word
call .l1 ; from the input file to BC
ld l, b
.l1: push de
ld a, 1
exos 5
pop de
ld c, l
ret
dephase
decompCode2End: