; ---------------------------------------------------------------------------
; aPPack decompressor
; original source by dwedit
; very slightly adapted by utopian
; optimized by Metalbrain
;
; hl = source
; de = dest
; ---------------------------------------------------------------------------
depack
    LD   IXL,128
apbranch1
    LDI
aploop0
    LD   IXH,1       ;LWM = 0
aploop
    CALL ap_getbit
    JR   NC,apbranch1
    CALL ap_getbit
    JR   NC,apbranch2
    LD   B,0
    CALL ap_getbit
    JR   NC,apbranch3
    LD   C,16        ;get an offset
apget4bits
    CALL ap_getbit
    RL   C
    JR   NC,apget4bits
    JR   NZ,apbranch4
    LD   A,B
apwritebyte
    LD   (DE),A      ;write a 0
    INC  DE
    JR   aploop0
apbranch4
    AND  A
    EX   DE,HL       ;write a previous byte (1-15 away from dest)
    SBC  HL,BC
    LD   A,(HL)
    ADD  HL,BC
    EX   DE,HL
    JR   apwritebyte
apbranch3
    LD   C,(HL)      ;use 7 bit offset, length = 2 or 3
    INC  HL
    RR   C
    RET  Z       ;if a zero is encountered here, it is EOF
    LD   A,2
    ADC  A,B
    PUSH HL
    LD   IYH,B
    LD   IYL,C
    LD   H,D
    LD   L,E
    SBC  HL,BC
    LD   C,A
    JR   ap_finishup2
apbranch2
    CALL ap_getgamma ;use a gamma code * 256 for offset, another gamma code for length
    DEC  C
    LD   A,C
    SUB  IXH
    JR   Z,ap_r0_gamma       ;if gamma code is 2, use old r0 offset,
    DEC  A
    ;do I even need this code?
    ;bc=bc*256+(hl), lazy 16bit way
    LD   B,A
    LD   C,(HL)
    INC  HL
    LD   IYH,B
    LD   IYL,C
    PUSH BC
    CALL ap_getgamma
    EX   (SP),HL     ;bc = len, hl=offs
    PUSH DE
    EX   DE,HL
    LD   A,4
    CP   D
    JR   NC,apskip2
    INC  BC
    OR   A
apskip2 
    LD   HL,127
    SBC  HL,DE
    JR   C,apskip3
    INC  BC
    INC  BC
apskip3
    POP  HL      ;bc = len, de = offs, hl=junk
    PUSH HL
    OR   A
ap_finishup
    SBC  HL,DE
    POP  DE      ;hl=dest-offs, bc=len, de = dest
ap_finishup2
    LDIR
    POP  HL
    LD   IXH,B
    JR   aploop
ap_r0_gamma 
    CALL ap_getgamma     ;and a new gamma code for length
    PUSH HL
    PUSH DE
    EX   DE,HL
    LD   D,IYH
    LD   E,IYL
    JR   ap_finishup
ap_getbit
    LD   A,IXL
    ADD  A,A
    LD   IXL,A
    RET  NZ
    LD   A,(HL)
    INC  HL
    RLA
    LD   IXL,A
    RET
ap_getgamma
    LD   BC,1
ap_getgammaloop
    CALL ap_getbit
    RL   C
    RL   B
    CALL ap_getbit
    JR   C,ap_getgammaloop
    RET
