I can't find any more optimizations, so this afternoon I started to think about a possible evolution of the format, and again, I had a new crazy idea.
What if we don't discard the last offset and use the stack as a stack & buffer mix? I'm not sure if this can improve compression but I had nothing else to do
so, I created this forward standard decompressor mod:
Code: Select all
; -----------------------------------------------------------------------------
; ZXX decoder by Einar Saukas & Urusergi
; "Standard" version (93 bytes only)
; -----------------------------------------------------------------------------
; Parameters:
; HL: source address (compressed data)
; DE: destination address (decompressing)
; -----------------------------------------------------------------------------
dzxx_standard:
pop iy ; safeguard the return of the routine
ld bc, $ffff ; preserve default offset 1
push bc
inc bc
ld a, $80
dzxxs_literals:
call dzxxs_elias ; obtain length
ldir ; copy literals
add a, a ; copy from old offset or new offset?
jr c, dzxxs_new_offset
call dzxxs_elias ; obtain buffer index
push bc
pop ix
add ix, ix ; x2 being 16 bits
add ix, sp ; ix points to old offset LSB
ld c, (ix + 0)
ld b, (ix + 1)
push bc ; buffer updated
ld bc, 1
call dzxxs_elias ; obtain length
dzxxs_copy:
ex (sp), hl ; preserve source, restore offset
push hl ; preserve offset
add hl, de ; calculate destination - offset
ldir ; copy from offset
pop hl ; restore offset
ex (sp), hl ; preserve offset, restore source
add a, a ; copy from literals or new offset?
jr nc, dzxxs_literals
dzxxs_new_offset:
ld c, $fe ; prepare negative offset
call dzxxs_elias_loop ; obtain offset MSB
inc c
jr z, dzxx_exit ; check end marker
ld b, c
ld c, (hl) ; obtain offset LSB
inc hl
rr b ; last offset bit becomes first length bit
rr c
push bc ; preserve new offset
ld bc, 1 ; obtain length
call nc, dzxxs_elias_backtrack
inc bc
jr dzxxs_copy
dzxxs_elias:
inc c ; interlaced Elias gamma coding
dzxxs_elias_loop:
add a, a
jr nz, dzxxs_elias_skip
ld a, (hl) ; load another group of 8 bits
inc hl
rla
dzxxs_elias_skip:
ret c
dzxxs_elias_backtrack:
add a, a
rl c
rl b
jr dzxxs_elias_loop
dzxx_exit:
push iy
ret
; -----------------------------------------------------------------------------
Naturally, the stack will increase quite a bit, so the hypothetical compressor should report the final size of the buffer to have control.