;------------------------------------------------------------------------------
; bitbuster-extreme-Entpacker (LZ77 compression)
; orig. source: depack.gen (c) 2002-2003  Team Bomba, modified for Mega-Modul: A.S.
; Anpassung an Mega-Flash: V.Pohlers 2012
;------------------------------------------------------------------------------


;--------------
; in	HL: source (binary)
;       DE: destination

depack:
		ld	a,128

		exx
		ld    de,1
		exx

depack_loop:
		call 	getbits			;get compression type bit
		jr	c,output_compressed	;if set, we got lz77 compression
	;
		ldi				;copy byte from compressed data to destination (literal byte)
	;	ex   	af,af'
		call 	hl_check_adress
		ex   	af,af'
		jr	depack_loop

;handle compressed data
output_compressed:
		ld	c,(hl)			;get lowest 7 bits of offset, plus offset extension bit

	;  !!!! increment macht auch die Routine
   	;  spart noch ein Byte, da es später auch noch einmal gemacht werden muss

	;	inc	hl			;to next byte in compressed data

	;	ex   	af,af'
		call 	inc_hl_checkAdress
		ex   	af,af'

output_match:
		ld	b,0
		bit	7,c
		jr	z,output_match1		;no need to get extra bits if carry not set

		call 	getbits			;get offset bit 10 
		call 	rlbgetbits		;get offset bit 9
		call 	rlbgetbits		;get offset bit 8
		call 	rlbgetbits		;get offset bit 7

		jr	c,output_match1		;since extension mark already makes bit 7 set
		res	7,c			;only clear it if the bit should be cleared
output_match1:
		inc	bc


;return a gamma-encoded value
;length returned in HL

		exx				;to second register set!
		ld	h,d
		ld	l,e           		;initial length to 1
		ld	b,e			;bitcount to 1

;determine number of bits used to encode value

get_gamma_value_size:
		exx
		call 	getbits			;get more bits
		exx
		jr	nc,get_gamma_value_size_end;if bit not set, bitlength of remaining is known
		inc	b			;increase bitcount
		jr	get_gamma_value_size	;repeat...

get_gamma_value_bits:
		exx
		call 	getbits			;get next bit of value from bitstream
		exx

		adc	hl,hl			;insert new bit in HL
get_gamma_value_size_end:
		djnz	get_gamma_value_bits	;repeat if more bits to go

get_gamma_value_end:
		inc	hl			;length was stored as length-2 so correct this

; !!! hier kein 'call 	checkAdress'

		exx				;back to normal register set

		ret	c	;-> depack_loop verlassen
;HL' = length

		push	hl			;address compressed data on stack

		exx
		push	hl			;match length on stack
		exx

		ld	h,d
		ld	l,e			;destination address in HL...
		sbc	hl,bc			;calculate source address

		pop	bc			;match length from stack

; - - - - - - - - - -  von A.S. - - - - - - - - - - - - - - - - Anfang

		; 0.) SAVE
		ex   	af,af'

		; nur testen, noch nicht berechnen
		; der max. nur 2mal geswitch wird, ist es besser dies auf spaeter zu verschieben

		; hl = aktuelle Adresse
		; bc = anzahl der zu kopierenden Bytes

		; 1.) low Bits addieren und Carry merken .....

		ld	a, l
		add	a, c			; l+c, Carry merken

		; 2.) high Bits addieren sammt gemerktem Carry ....

		ld	a, h
		adc	a, b			; h+b+ Carry

		; 3.) Vergleich, ob schon ueber die Speichergrenze hinaus .....

; TODO f. UZ veränderliche blocksize, abwechselnd 10k und 6k

		cp	hi(bankstart+blocksize)
		jr   	c, weiter_1

		push	bc			; zu kopierende Bytes
		push 	hl			; von nach
		push	de

		ld	de, bankstart+blocksize

		;or	a,a			; wir landen ja nur hier, wenn das Carry nicht gesetzt ist ... Byte gesparrt ;-)
		ex	de,hl
		sbc	hl,de			; 0e000h - aktuelle Adresse

		ld	b,h			; bc = HL
		ld	c,l

		ld (copyspeicher-2), bc		; zu kopierende Bytes gleich an der richtigen Stelle eintragen

		pop	de
		pop	hl

		ldir 				; ersten Teil kopieren

		call 	l_nextbank

	; de bleibt ....
	; hl wieder auf Anfang des ROMs setzen

		pop	hl			; frueher BC
		ld	bc, 0000	;<- wird modifiziert
copyspeicher:

		xor	a,a			; a und Carry löschen
		sbc	hl,bc

		ld	b,h			; bc = HL
		ld	c,l

		ld	l, a			; a schon weiter oben gelöscht
		ld	h, 0c0h			; HL=C000



weiter_1:
		ldir				;transfer data
		;pop  	af
		ex   	af,af'

; - - - - - - - - - -  von A.S. - - - - - - - - - - - - - - - - Ende
	
		pop	hl		;address compressed data back from stack
		jr	depack_loop

;-------------------
;UP
;getbits: macro to get a bit from the bitstream
;carry if bit is set, nocarry if bit is clear
;must be entered with second registerset switched in!

rlbgetbits
		rl 	b
getbits
		add	a,a		;shift out new bit
		ret	nz		;if remaining value isn't zere, we're done
		ld	a,(hl)		;get 8 bits from bitstream

;  !!!! increment macht auch die Routine
; spart noch ein Byte, da es später auch noch einmal gemacht werden muss
		;inc	hl

		;ex   	af,af'
		call  	inc_hl_checkAdress
		ex   	af,af'

		rla			;(bit 0 will be set!!!!)
		ret

;----------------------
;UP
inc_hl_checkAdress:
		inc 	hl			; hl in jedem Falle erhöhen

hl_check_adress:
		ex   	af,af'
		ld   	a, hi(bankstart+blocksize)
		cp   	h
		ret	nz

		ld   	h, hi(bankstart)
	; Bank switchen
		jp 	l_nextbank		; jr statt jp -> 1 Byte gespart
;;		ret
	; ret	übernimmt l_nextbank mit
		
;------------------------------------------------------------------------------
