; dan0.s
;-----------------------------------------------------------
; DAN0 VRAM Depacker v1.0 by Daniel Bienvenu, March 2010.
; Compiled version : 128 bytes
;-----------------------------------------------------------
; USAGE : dan0(vram_offset, tblcodes);
;         tblcodes = pointer to tbldata +AND+ table of RLE & Huffman codes
;         tbldata = bytes to output
;         vram_offset = address in VRAM
;-----------------------------------------------------------
; RLE codes
; =========
; 00h = END
; 01h-7Eh = 2 to 127 times 1 byte to output
; 7Fh = 256 times 1 byte to ouput
; 80h = 256 bytes to output
; 81h-FFh = 1 to 127 bytes to output
;-----------------------------------------------------------
; BIT codes ( fixed Huffman table )
; =======================================
; [0] = get next byte in tbldata
; [1000] = get 1st previous byte    [101110] = get 11th previous byte
; [1010] = get 2nd previous byte    [101111] = get 12th previous byte
; [1100] = get 3rd previous byte    [110100] = get 13th previous byte
; [1110] = get 4th previous byte    [110101] = get 14th previous byte
; [100100] = get 5th previous byte  [110110] = get 15th previous byte
; [100101] = get 6th previous byte  [110111] = get 16th previous byte
; [100110] = get 7th previous byte  [111100] = get 17th previous byte
; [100111] = get 8th previous byte  [111101] = get 18th previous byte
; [101100] = get 9th previous byte  [111110] = get 19th previous byte
; [101101] = get 10th previous byte [111111] = get 20th previous byte
;-----------------------------------------------------------

    .module dan0

    .globl  _dan0, dan0
    ; void dan0 (unsigned vram_offset, void *tblcodes);

    .area _CODE

_dan0:

    pop bc
    pop de
    pop hl
    push hl
    push de
    push bc
    
    ; DE = VRAM OFFSET
    ; HL = CTRL_TABLE POINTER - 2 ( for the data_table pointer stored first )

dan0:
    ; OFFSET VRAM
    ld  c,#0xbf
    out (c),e
    set 6,d
    out (c),d
    ; GET DATA_TABLE POINTER IN DE
    ld e,(hl)
    inc hl
    ld d,(hl)
    inc hl    
    dec c ;ld c,#0xbe
    
    ; IN :
    ; HL = CTRL_TABLE POINTER
    ; DE = DATA_TABLE POINTER
    ; C = I/O PORT
    
    ld a,#0x80
    ex af,af'
    ld  a,(de)
    or a
    push af ;; push flag Z
    jr nz, dan0_main
    inc de
    
    ;;  DE = tbldata ptr
    ;;  HL = tblcodes ptr
    ;;  A' = 0x80
    ;;  C = 0xBE
    ;;  Z FLAG PUSHED
    
dan0_main:
    ld a,(hl)
    inc hl
    bit 7,a
    jr nz, dan0_raw
    or a
    jr z, dan0_end
    inc a
    and #0x7f
    ld b,a
    pop af
    push af
    call dan0_readnextbyte
    
dan0_rle_loop:
    out (c),a
    djnz dan0_rle_loop
    jr dan0_main
    
dan0_raw:
    and #0x7f
    ld b,a
    
dan0_raw_loop:
    pop af
    push af
    call dan0_readnextbyte
    out (c),a
    djnz dan0_raw_loop
    jr dan0_main

    ; OUT =
    ; HL = POINTER TO AFTER THE END OF CTRL_TABLE
    ; DE = POINTER TO AFTER THE END OF DATA_TABLE
    ; C = I/O PORT
    ; AF, AF', B = GARBAGE

dan0_end:
    pop af
    ret
    
dan0_readnextbyte:
    jr  nz, dan0_compression
    ld a,(de)
    inc de
    ret
    
dan0_compression:
    push bc
    ld bc,#0x0000
    ex af,af'
    call dan0_getbit
    ex de,hl
    jr nc, dan0_getbyte
    ex de,hl
    call dan0_getbit
    call dan0_rlcgetbit
    call dan0_rlcgetbit
    jr nc, dan0_set_buffer_ptr
    call dan0_getbit
    call dan0_rlcgetbit
    rl c
    inc c    
    inc c    
    inc c    
    inc c    
dan0_set_buffer_ptr:
    inc c
    ex de,hl
    sbc hl,bc
    dec c
    
dan0_getbyte:
    ex af,af'
    ld a,(hl)
    add hl,bc
    ex de,hl
    inc de
    pop bc
    ret
    
dan0_rlcgetbit:
    rl c
    
dan0_getbit:
    add a,a
    ret nz
    ld a,(hl)
    inc hl
    rla
    ret