News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_roudoudou

Shrinkler Z80 decrunch routine

Started by roudoudou, 10:42, 31 January 18

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Hicks

-1 byte:


    ex de,hl
    ld hl,1 ; d7
shrinkler_bitsloop:
    exx
    call shrinkler_getbit
    exx
    adc hl,hl
    ld a,(de)
    sub 2
    ld (de),a
    jr nc,shrinkler_bitsloop
    ld b,h
    ld c,l
    ret


Becomes:


    ld bc,1
shrinkler_bitsloop:
    exx
    call shrinkler_getbit
    exx
    rl c : rl b
    ld a,(hl)
    sub 2
    ld (hl),a
    jr nc,shrinkler_bitsloop
    ret


Save CPU too.

roudoudou

valid! updated first post, blablabla
My pronouns are RASM and ACE

antoniovillena

-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

antoniovillena

Corrected with the Hicks code:



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)
        ld      bc, 1
shrinkler_bitsloop:
        call    shrinkler_getbit
        rl      c
        rl      b
        ld      a, (hl)
        sub     2
        ld      (hl), a
        jr      nc, shrinkler_bitsloop
        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

antoniovillena

Another -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, 2
        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)
        ld      bc, 1
shrinkler_bitsloop:
        call    shrinkler_getbit
        rl      c
        rl      b
        dec     (hl)
        dec     (hl)
        jp      p, shrinkler_bitsloop
        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

antoniovillena

Another easy -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
        ; return without carry and HL=BC
        ld      hl, 2
        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)
        ld      bc, 1
shrinkler_bitsloop:
        call    shrinkler_getbit
        rl      c
        rl      b
        dec     (hl)
        dec     (hl)
        ret     m
        jr      shrinkler_bitsloop


;--------------------------------------------------
        ; 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

roudoudou

the JP P does not work because the overflow may occur at the first DEC (hl)


BTW for short modif is it possible to post only a few lines?  ;D
My pronouns are RASM and ACE

antoniovillena

Quote from: roudoudou on 22:06, 03 February 18
the JP P does not work because the overflow may occur at the first DEC (hl)


BTW for short modif is it possible to post only a few lines?  ;D


Sorry. This is the last time I do with this -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
        ; return without carry and HL=BC
        ld      hl, 2
        sbc     hl, bc
        ld      (shrinkler_d5+1), hl
        jr      nz, shrinkler_readlength
        ret


;--------------------------------------------------
shrinkler_getnumber:
        ; Out: Number in HL
        ld      bc, 1
        ld      hl, shrinkler_d6+1
        ld      (hl), a
        dec     hl
        ld      (hl), b
shrinkler_numberloop:
        inc     (hl)
        inc     (hl)
        call    shrinkler_getbit
        jr      c, shrinkler_numberloop
        dec     (hl)
shrinkler_bitsloop:
        call    shrinkler_getbit
        rl      c
        rl      b
        dec     (hl)
        dec     (hl)
        ret     m
        jr      shrinkler_bitsloop


;--------------------------------------------------
        ; 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

roudoudou

thanks, the LD BC,1 upper works
now it's 292 bytes :)
My pronouns are RASM and ACE

antoniovillena

Another -1


        ld      a, $e0
shrinkler_shift4:
        srl     b
        rr      c
        add     a, a
        jr      c, shrinkler_shift4
        ex      hl, de

antoniovillena

About this code:




;--------------------------------------------------
shrinkler_getnumber:
        ; Out: Number in HL
        ld      bc, 1
        ld      hl, shrinkler_d6+1
        ld      (hl), a
        dec     hl
        ld      (hl), b
shrinkler_numberloop:
        inc     (hl)
        inc     (hl)
        call    shrinkler_getbit
        jr      c, shrinkler_numberloop
        dec     (hl)
shrinkler_bitsloop:
        call    shrinkler_getbit
        rl      c
        rl      b
        dec     (hl)
        dec     (hl)
        ret     m
        jr      shrinkler_bitsloop



Never fails. Because you only need to load up to 16 bits in bc and with positive range you have up to 63 (positive range is between 0 and 127)

roudoudou


i can't get it work with my test file. Maybe i miss a modif?
My pronouns are RASM and ACE

antoniovillena

Quote from: roudoudou on 23:03, 03 February 18
i can't get it work with my test file. Maybe i miss a modif?


Send me your file and I can try. Another -1




        ld      a, $e1
shrinkler_shift4:
        srl     b
        rr      c
        add     a, a
        jr      c, shrinkler_shift4
        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, 0
        ld      l, h
shrinkler_muluw:
        add     hl, hl

antoniovillena

Attached my test. It's a ZX Spectrum screen. Use sjasmplus as assembler

roudoudou

Quote from: antoniovillena on 23:16, 03 February 18
Attached my test. It's a ZX Spectrum screen. Use sjasmplus as assembler
there is no manic.shr in the archive


here is my shr. Expect 16384 bytes in output (Amstrad screen)
My pronouns are RASM and ACE

antoniovillena

#40
I can not decompress 32k. Check if the first 14k are ok. manic.shr is generated by compressor.


I will migrate in the future to Ticks

http://retrolandia.net/foro/showthread.php?tid=43&pid=654#pid654

Because I would like to release a speed optimized version and this tool count the Z80 cycles of the whole execution. Also generate files to compare if the file is good extracted.

roudoudou

I get it, that changed the carry (always setted to always reset) now it works!


288 bytes
My pronouns are RASM and ACE

antoniovillena

Quote from: roudoudou on 23:42, 03 February 18
I get it, that changed the carry (always setted to always reset) now it works!


288 bytes


Now tested with Ticks. It costs 21.642.848 cycles decrounch your file. Attached if can be useful for you.

roudoudou

Quote from: antoniovillena on 00:01, 04 February 18

Now tested with Ticks. It costs 21.642.848 cycles decrounch your file. Attached if can be useful for you.


CPC emulators can "tick" on demand.
On Amstrad machines we have wait-states so the final count is higher. 5.834.708 nops that to say 23.338.832 cycles
My pronouns are RASM and ACE

antoniovillena

#44
Quote from: roudoudou on 00:09, 04 February 18

CPC emulators can "tick" on demand.
On Amstrad machines we have wait-states so the final count is higher. 5.834.708 nops that to say 23.338.832 cycles


Yes. Also Spectrum emulators have contention. But it's a good number for compare with other algorithms.



The next one compares compression ratio with other algorithms.
Numbers are filesizes in bytes.


Size    Shrinkler Exomizer    aPLib   saukav     zx7b  BBuster
lena1k        776      812      872      873      902      905
lena16k     13796    13581    14635    14649    14689    14798
lena32k     28368    28019    29991    30071    30272    30446
alice1k       548      613      617      611      631      636
alice16k     6872     7266     7659     7738     8175     8429
alice32k    12868    13461    14473    14535    16074    16570
128rom1k      840      884      889      913      923      925
128rom16k   11848    12260    12434    12728    12806    12882
128rom32k   23648    24415    24820    26157    26524    26708



This last table compares speed with other algorithms.
Numbers are execution cycles.


           Shrinkler  deexov4    aPLib  BBuster  zx7mega   saukav   zx7bf2
--------------------------------------------------------------------------
lena1k      13757267   303436   176642   106746    95255    76547    81040
lena16k    238317371  4407913  2961621  1908398  1727095  1646032  1462568
lena32k    484967405  8443253  5820921  3651800  3300486  3231882  2803116
alice1k     10060954   274111   136224    98914    89385    70869    73459
alice16k   131592504  2973592  2143122  1812259  1614225  1338287  1328886
alice32k   249719379  5378511  4189855  3614393  3230255  2550243  2654236
128rom1k    13773150   249124   131667    82637    74110    60222    62000
128rom16k  197319929  3571407  2292945  1550682  1407478  1392317  1180569
128rom32k  394594060  7355277  4583902  3107867  2825773  1926027  2381847
--------------------------------------------------------------------------
routine size     288      201      197      168      244     ~200      191



https://github.com/antoniovillena/zx7b

antoniovillena

Another -1




        ld      hl, (shrinkler_d2)
        xor     a
        sbc     hl, de
        pop     bc
        jr      c, shrinkler_one


shrinkler_zero:
        ; oneprob = oneprob * (1 - adjust) = oneprob - oneprob * adjust
        ld      (shrinkler_d2), hl
        ld      hl, (shrinkler_d3)
        sbc     hl, de
        jr      shrinkler_d3ret


shrinkler_one:
        ; onebrob = 1 - (1 - oneprob) * (1 - adjust) = oneprob - oneprob * adjust + adjust
        ; move+add out of order!
        ld      a, (bc)
        sub     1
        ld      (bc), a
        inc     bc
        ld      a, (bc)
        sbc     a, $f0                  ; (a1)+#FFF
        ld      (bc), a
        ex      de, hl
shrinkler_d3ret:
        ld      (shrinkler_d3), hl
        exx
        ret

antoniovillena

Another -1




        ld      de, (shrinkler_d3)
; input: DE x BC
; output: DEHL
        sbc     hl, hl
shrinkler_muluw:
        add     hl, hl



Total: 286 bytes

roudoudou

Quote from: antoniovillena on 00:36, 04 February 18

Size    Shrinkler Exomizer    aPLib   saukav     zx7b  BBuster



Didn't know about saukav vs zx7b and his performance, i will add it to my assembler for on the fly data/code compression
My pronouns are RASM and ACE

antoniovillena

Another -1. I'm sorry this time I put whole code because reordering. Basically you can avoid the final ret by putting dummy routine.




shrinkler_getnumber:
        ; Out: Number in HL
        ld      bc, 1
        ld      hl, shrinkler_d6+1
        ld      (hl), a
        dec     hl
        ld      (hl), b
shrinkler_numberloop:
        inc     (hl)
        inc     (hl)
        call    shrinkler_getbit
        jr      c, shrinkler_numberloop
        dec     (hl)
shrinkler_bitsloop:
        call    shrinkler_getbit
        rl      c
        rl      b
        dec     (hl)
        dec     (hl)
        ret     m
        jr      shrinkler_bitsloop


;--------------------------------------------------
        ; 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
        rl      (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, $e1
shrinkler_shift4:
        srl     b
        rr      c
        add     a, a
        jr      c, shrinkler_shift4
        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
        sbc     hl, hl
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
        pop     bc
        jr      c, shrinkler_one




shrinkler_zero:
        ; oneprob = oneprob * (1 - adjust) = oneprob - oneprob * adjust
        ld      (shrinkler_d2), hl
        ld      hl, (shrinkler_d3)
        sbc     hl, de
        jr      shrinkler_d3ret




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, 8
        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
        ; return without carry and HL=BC
        ld      hl, 2
        sbc     hl, bc
        ld      (shrinkler_d5+1), hl
        jr      nz, shrinkler_readlength


shrinkler_one:
        ; onebrob = 1 - (1 - oneprob) * (1 - adjust) = oneprob - oneprob * adjust + adjust
        ; move+add out of order!
        ld      a, (bc)
        sub     1
        ld      (bc), a
        inc     bc
        ld      a, (bc)
        sbc     a, $f0                  ; (a1)+#FFF
        ld      (bc), a
        ex      de, hl
shrinkler_d3ret:
        ld      (shrinkler_d3), hl
        exx
        ret

roudoudou

But the shrinkler_one function is not dummy since it will makes 2 writes in adress 2 and adress 3


So i switch shrinkler_zero, shrinkler_one and the JR Then only shrinkler_d3 is written with garbage, not the memory elsewhere
My pronouns are RASM and ACE

Powered by SMFPacks Menu Editor Mod