*
* ORCA/M Format!!
* LZ4 Decompress by Brutal Deluxe!!!
*
 case on
 longa on
 longi on

Dummy1 start ASMCODE
	end

*
* int LZ4_Unpack(u8* pDest, u8* pPackedSource);
*

LZ4_Unpack start ASMCODE

pDest equ 5
pPackedSource equ 9

    phb
    phk
    plb

    sep #$20
    lda pPackedSource+2,s    ; Pull out the src/dst banks
    xba
    lda pDest+2,s   		 ; Pull out the src/dst banks

    rep #$31
    tax                      ; Temp save in X

    lda pDest,s
    sta LZ4_Dst+1

    lda pPackedSource+1,s    ; address of packed source + 4, is the unpacked len
    sta upl+2
	
    lda pPackedSource,s
    adc #12
    sta upl+1
	
upl lda >0                  ; packed length
	adc #16 				; 16 bytes for packed buffer header
    adc pPackedSource,s 	; start of packed buffer
    tay                     ; y has the pack data stop address
	
    anop ; 1st packed Byte offset
    lda pPackedSource,s     ; skip 16 byte header on the source
    adc #16
    pha
    txa
    plx
	
    jsr ASM_LZ4_Unpack
    tay
	
    anop ; Copy the Return address
    lda 1,s
    sta pPackedSource,s
    lda 3,s
    sta pPackedSource+2,s
		
    tsc
	sec
    sbc #-8
    tcs
    tya    ; return length	

    plb
    rtl

*-------------------------------------------------------------------------------
ASM_LZ4_Unpack   STA  LZ4_Literal_3+1   ; Uncompress a LZ4 Packed Data buffer (64 KB max)
                 SEP  #$20              ; A = Bank Src,Bank Dst
                 STA  LZ4_Match_5+1     ; X = Header Size = 1st Packed Byte offset
                 STA  LZ4_Match_5+2     ; Y = Pack Data Size
                 XBA                    ;  => Return in A the length of unpacked Data
                 STA  LZ4_ReadToken+3   
                 STA  LZ4_Match_1+3     
                 STA  LZ4_GetLength_1+3 
                 REP  #$30 
                 STY  LZ4_Limit+1
*--
LZ4_Dst          LDY  #$0000            ; Init Target unpacked Data offset
LZ4_ReadToken    LDA  >$AA0000,X        ; Read Token Byte
                 INX
                 STA  LZ4_Match_2+1
*----------------
LZ4_Literal      AND  #$00F0            ; >>> Process Literal Bytes <<<
                 BEQ  LZ4_Limit         ; No Literal
                 CMP  #$00F0
                 BNE  LZ4_Literal_1
                 JSR  LZ4_GetLengthLit  ; Compute Literal Length with next bytes
                 BRA  LZ4_Literal_2
LZ4_Literal_1    LSR  A                 ; Literal Length use the 4 bit
                 LSR  A
                 LSR  A
                 LSR  A
*--
LZ4_Literal_2    DEC  A                 ; Copy A+1 Bytes
LZ4_Literal_3    MVN  $AA,$BB           ; Copy Literal Bytes from packed data buffer
                 PHK                    ; X and Y are auto incremented
                 PLB
*----------------
LZ4_Limit        CPX  #$AAAA            ; End Of Packed Data buffer ?
                 BEQ  LZ4_End
*----------------
LZ4_Match        TYA                    ; >>> Process Match Bytes <<<
                 SEC
LZ4_Match_1      SBC  >$AA0000,X         ; Match Offset
                 INX
                 INX
                 STA  LZ4_Match_4+1
*--
LZ4_Match_2      LDA  #$0000            ; Current Token Value
                 AND  #$000F
                 CMP  #$000F
                 BNE  LZ4_Match_3
                 JSR  LZ4_GetLengthMat  ; Compute Match Length with next bytes
LZ4_Match_3      CLC
                 ADC  #$0003            ; Minimum Match Length is 4 (-1 for the MVN)
*--
                 PHX
LZ4_Match_4      LDX  #$AAAA            ; Match Byte Offset
LZ4_Match_5      MVN  $BB,$BB           ; Copy Match Bytes from unpacked data buffer
                 PHK                    ; X and Y are auto incremented
                 PLB
                 PLX
*----------------
                 BRA  LZ4_ReadToken
*----------------
LZ4_GetLengthLit LDA  #$000F            ; Compute Variable Length (Literal or Match)
LZ4_GetLengthMat STA  LZ4_GetLength_2+1
LZ4_GetLength_1  LDA  >$AA0000,X         ; Read Length Byte
                 INX
                 AND  #$00FF
                 CMP  #$00FF
                 BNE  LZ4_GetLength_3
                 CLC
LZ4_GetLength_2  ADC  #$000F
                 STA  LZ4_GetLength_2+1
                 BRA  LZ4_GetLength_1
LZ4_GetLength_3  ADC  LZ4_GetLength_2+1
                 RTS
*----------------
LZ4_End          TYA                    ; A = Length of Unpack Data
                 RTS
*-------------------------------------------------------------------------------
                 end

