-2 bytes. But without apply the last -1
shrinkler_decrunch:
ld (shrinkler_a5+1), hl
; Init range decoder state
ld hl, shrinkler_dr+1536*2+8
ld bc, 1536*2
ld (hl), c
inc hl
ld (hl), $80
ld de, shrinkler_dr+1536*2+7
lddr
ld c, $08
dec hl
lddr
inc (hl)
shrinkler_lit:
; Literal
scf
shrinkler_getlit:
call nc, shrinkler_getbit
ld hl, shrinkler_d6
rl (hl)
jr nc, shrinkler_getlit
shrinkler_a5:
ld de, $1234
ldi
; After literal
call shrinkler_getkind
jr nc, shrinkler_lit
; Reference
sbc hl, hl
call shrinkler_altgetbit
jr nc, shrinkler_readoffset
shrinkler_readlength:
ld a, 4
call shrinkler_getnumber
shrinkler_d5:
ld hl, $0101
ld de, (shrinkler_a5+1)
add hl, de
ldir
; After reference
call shrinkler_getkind
jr nc, shrinkler_lit
shrinkler_readoffset:
ld a, 3
call shrinkler_getnumber
; retour systématique avec carry et HL=BC
ld hl, 3
sbc hl, bc
ld (shrinkler_d5+1), hl
jr nz, shrinkler_readlength
ret
;--------------------------------------------------
shrinkler_getnumber:
; Out: Number in HL
ld hl, shrinkler_d6+1
ld (hl), a
dec hl
ld (hl), 0
shrinkler_numberloop:
inc (hl)
inc (hl)
call shrinkler_getbit
jr c, shrinkler_numberloop
dec (hl)
ex de, hl
ld hl, 1 ; d7
shrinkler_bitsloop:
call shrinkler_getbit
adc hl, hl
ld a, (de)
sub 2
ld (de), a
jr nc, shrinkler_bitsloop
ld b, h
ld c, l
ret
;--------------------------------------------------
; Out: Bit in C
shrinkler_readbit:
ld hl, (shrinkler_d4)
add hl, hl
ex de, hl
ld hl, (shrinkler_d4+2) ; lu en little endian
adc hl, hl
ex af, af'
ld a, h
or l
or d
or e
jr nz, shrinkler_nonewword
; HL=DE=0
ld e, 4
add ix, de
ld l, (ix-1)
ld h, (ix-2)
ld e, (ix-3)
ld d, (ix-4) ; DEHL=(a4) nouvelle valeur lue en big endian!
ex af, af' ; injecte la CARRY précédente
adc hl, hl
ex hl, de
adc hl, hl
ex af, af' ; save carry
shrinkler_nonewword:
ld (shrinkler_d4), de
ld (shrinkler_d4+2), hl ; mais écrite en little endian
ld hl, shrinkler_d3
sla (hl)
inc hl
rl (hl)
inc hl
ex af, af' ; retrieve previous carry
rl (hl)
inc hl
rl (hl)
jr shrinkler_getbit1
;--------------------------------------------------
shrinkler_getkind:
;Use parity as context
ld (shrinkler_a5+1), de
xor a
ld l, a
inc a
and e
ld h, a
shrinkler_altgetbit:
ld (shrinkler_d6), hl
shrinkler_getbit:
exx
shrinkler_getbit1:
ld a, (shrinkler_d3+1) ; obligé de relire les 8 bits forts la valeur...
add a, a
jr nc, shrinkler_readbit
ld hl, (shrinkler_d6)
add hl, hl
ld de, shrinkler_pr+2 ; cause -1 context
add hl, de
push hl
ld e, (hl)
inc hl
ld d, (hl)
; D1 = One prob
push de
ld b, d
ld c, e ; bc=de=d1 / hl=a1
ld a, 4
shrinkler_shift4:
srl b
rr c
dec a
jr nz, shrinkler_shift4
xor a
ex hl, de
sbc hl, bc ; hl=d1-d1/16
ex hl, de
ld (hl), d
dec hl
ld (hl), e
pop bc ; bc=d1 initial
ld de, (shrinkler_d3)
; input: DE x BC
; output: DEHL
ld h, a
ld l, a
ld a, 16
shrinkler_muluw:
add hl, hl
rl e
rl d
jr nc, shrinkler_cont
add hl, bc
jr nc, shrinkler_cont
inc de
shrinkler_cont:
dec a
jr nz, shrinkler_muluw
ld hl, (shrinkler_d2)
xor a
sbc hl, de
jr c, shrinkler_one
shrinkler_zero:
; oneprob = oneprob * (1 - adjust) = oneprob - oneprob * adjust
ld (shrinkler_d2), hl
ld hl, (shrinkler_d3)
sbc hl, de
pop de
jr shrinkler_d3ret
shrinkler_one:
; onebrob = 1 - (1 - oneprob) * (1 - adjust) = oneprob - oneprob * adjust + adjust
; move+add out of order!
pop hl
dec a
add a, (hl)
ld (hl), a
inc hl
ld a, (hl)
adc a, $0f ; (a1)+#FFF
ld (hl), a
scf ; SET CARRY
ex de, hl
shrinkler_d3ret:
ld (shrinkler_d3), hl
exx
ret