Linux_Matters_Speccy_Demo/dzx0_turbo.asm
2024-11-11 18:38:56 +00:00

101 lines
3.4 KiB
NASM

; -----------------------------------------------------------------------------
; ZX0 decoder by Einar Saukas & introspec
; "Turbo" version (126 bytes, 21% faster)
; -----------------------------------------------------------------------------
; Parameters:
; HL: source address (compressed data)
; DE: destination address (decompressing)
; -----------------------------------------------------------------------------
dzx0_turbo:
ld bc, $ffff ; preserve default offset 1
ld (dzx0t_last_offset+1), bc
inc bc
ld a, $80
jr dzx0t_literals
dzx0t_new_offset:
ld c, $fe ; prepare negative offset
add a, a
jp nz, dzx0t_new_offset_skip
ld a, (hl) ; load another group of 8 bits
inc hl
rla
dzx0t_new_offset_skip:
call nc, dzx0t_elias ; obtain offset MSB
inc c
ret z ; 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
ld (dzx0t_last_offset+1), bc ; preserve new offset
ld bc, 1 ; obtain length
call nc, dzx0t_elias
inc bc
dzx0t_copy:
push hl ; preserve source
dzx0t_last_offset:
ld hl, 0 ; restore offset
add hl, de ; calculate destination - offset
ldir ; copy from offset
pop hl ; restore source
add a, a ; copy from literals or new offset?
jr c, dzx0t_new_offset
dzx0t_literals:
inc c ; obtain length
add a, a
jp nz, dzx0t_literals_skip
ld a, (hl) ; load another group of 8 bits
inc hl
rla
dzx0t_literals_skip:
call nc, dzx0t_elias
ldir ; copy literals
add a, a ; copy from last offset or new offset?
jr c, dzx0t_new_offset
inc c ; obtain length
add a, a
jp nz, dzx0t_last_offset_skip
ld a, (hl) ; load another group of 8 bits
inc hl
rla
dzx0t_last_offset_skip:
call nc, dzx0t_elias
jp dzx0t_copy
dzx0t_elias:
add a, a ; interlaced Elias gamma coding
rl c
add a, a
jr nc, dzx0t_elias
ret nz
ld a, (hl) ; load another group of 8 bits
inc hl
rla
ret c
add a, a
rl c
add a, a
ret c
add a, a
rl c
add a, a
ret c
add a, a
rl c
add a, a
ret c
dzx0t_elias_loop:
add a, a
rl c
rl b
add a, a
jr nc, dzx0t_elias_loop
ret nz
ld a, (hl) ; load another group of 8 bits
inc hl
rla
jr nc, dzx0t_elias_loop
ret
; -----------------------------------------------------------------------------