All pastes #2047020 Raw Edit

Anonymous

public text v1 · immutable
#2047020 ·published 2011-04-16 01:14 UTC
rendered paste body
; ---------------------------------------------------------------------------
; SUBROUTINE
;
; Decompresses sprite using RBY compression (e.g. Pokemon and trainer pics)
;
; Documentation on the compression format can be found here (although the
; English is a bit hard to understand): 
; http://magicstone.de/rhwiki/article/Grafikkomprimierung_PKMN_RGBY
; ---------------------------------------------------------------------------

DecompressSprite:					; $24FD
		ld	b, a
		ld	a, [BANKNUM]
		push	af				; push bank number onto stack for later retrieval
		ld	a, b				; set bank to sprite bank
		ld	[BANKNUM], a
		ld	[BANKSWITCH], a
		ld	a, $A				
		ld	[SRAM_ENABLE], a		; enable SRAM by setting $0000 to $A
		xor	a				; (the SRAM is used to house the two $188-byte buffers)
		ld	[BANKSWITCH_U], a		; clear upper bits of bank number
		call	DS_Start			; call decompression routine
		pop	af				; retrieve bank number from stack
		ld	[BANKNUM], a		; set bank back to old bank
		ld	[BANKSWITCH], a
		ret

; ---------------------------------------------------------------------------
; Decompression routine begins here
; ---------------------------------------------------------------------------

DS_Start:						; $251A
		ld	hl, $A188			; hl = $A188
		ld	c, $10			; bc = $310
		ld	b, 3
		xor	a				; a = $0
		call	FillRAMArea			; clear $310 bytes at $A188 (for RAM buffers)
		
		ld	a, 1				; initialize decompression values
		ld	[W_DS_CURBIT], a		; current bit = 1
		ld	a, 3
		ld	[W_DS_CURBITGROUP], a	; current bit group = 3
		xor	a
		ld	[W_DS_CURYSIZE], a
		ld	[W_DS_CURXSIZE], a
		ld	[W_DS_CURBUFFER], a
		call	DS_GetNextByte		; get first byte (X/Y size)
		
		ld	b, a				; x size = (lower nybble of byte) * 8
		and	$F
		add	a, a
		add	a, a
		add	a, a
		ld	[W_DS_XSIZE], a
		
		ld	a, b				; y size = (upper nybble of byte) * 8
		swap	a
		and	$F
		add	a, a
		add	a, a
		add	a, a
		ld	[W_DS_YSIZE], a
		
		call	DS_GetNextBit		; get which RAM buffer to use (0 = RAM1, 1 = RAM2)
		ld	[W_DS_CURBUFFER], a

DS_GetCurBuffer:					; $2556
		ld	hl, S_DS_RAM1		; default buffer: RAM1
		ld	a, [W_DS_CURBUFFER]	
		bit	0, a				; is current buffer RAM2? (bit 0 = 1)
		jr	z, DS_GetInterpretation	; if not, branch
		ld	hl, S_DS_RAM2		; set buffer to RAM2

DS_GetInterpretation:				; $2563
		call	DS_SetPositions		; set pos0 and pos1 to hl (beginning of current buffer)
		ld	a, [W_DS_CURBUFFER]
		bit	1, a				; is bit 1 of current buffer set? (done at the end of first stream)
		jr	z, loc_257A			; if not, branch
		call	DS_GetNextBit		; get interpretation (either 1 or 2 bits)
		and	a
		jr	z, loc_2577			; if bit read is 0, then branch (interpretation = 0)
		call	DS_GetNextBit		; else, interpretation = (next bit + 1)
		inc	a				; this results in a interpretation range of 0 to 2 (3 total)

loc_2577:				; CODE XREF: DS_Start+57j
		ld	[W_DS_INTRP], a		; set interpretation

loc_257A:				; CODE XREF: DS_Start+51j
		call	DS_GetNextBit		; get next bit (determines whether first packet is data or RLE)
		and	a				; is bit 0?
		jr	z, DS_RLEPacket		; if yes, it's an RLE packet, so branch

DS_DataPacket:					; $2580
		call	DS_GetNextBit
		ld	c, a
		call	DS_GetNextBit
		sla	c
		or	c
		and	a
		jr	z, DS_RLEPacket
		call	sub_2649
		call	sub_25D8
		jr	DS_DataPacket
; ---------------------------------------------------------------------------

DS_RLEPacket:					; $2595
		ld	c, 0				; initialize c as 0

DS_RLEIndexLoop:					; $2597
		call	DS_GetNextBit		; c = number of bits set (index into RLE table)
		and	a				; is bit 0?
		jr	z, loc_25A0			; if so, branch
		inc	c				; increment c
		jr	DS_RLEIndexLoop		; loop
; ---------------------------------------------------------------------------

loc_25A0:				; CODE XREF: DS_Start+81j
		ld	a, c
		add	a, a
		ld	hl, DS_RLETable
		add	a, l
		ld	l, a
		jr	nc, loc_25AA
		inc	h

loc_25AA:				; CODE XREF: DS_Start+8Dj
		ldi	a, [hl]
		ld	e, a
		ld	d, [hl]
		push	de
		inc	c
		ld	e, 0
		ld	d, e

loc_25B2:				; CODE XREF: DS_Start+A4j
		call	DS_GetNextBit
		or	e
		ld	e, a
		dec	c
		jr	z, loc_25C0
		sla	e
		rl	d
		jr	loc_25B2
; ---------------------------------------------------------------------------

loc_25C0:				; CODE XREF: DS_Start+9Ej
		pop	hl
		add	hl, de
		ld	e, l
		ld	d, h

loc_25C4:				; CODE XREF: DS_Start:loc_25D4j
		ld	b, e
		xor	a
		call	sub_2649
		ld	e, b
		call	sub_25D8
		dec	de
		ld	a, d
		and	a
		jr	nz, loc_25D4
		ld	a, e
		and	a

loc_25D4:				; CODE XREF: DS_Start+B6j
		jr	nz, loc_25C4
		jr	DS_DataPacket
; End of function DS_Start


; =============== S U B	R O U T	I N E =======================================


sub_25D8:				; CODE XREF: DS_Start+76p DS_Start+B0p

; FUNCTION CHUNK AT 26BF SIZE 00000015 BYTES
; FUNCTION CHUNK AT 27C7 SIZE 00000070 BYTES
; FUNCTION CHUNK AT 2877 SIZE 00000020 BYTES

		ld	a, [W_DS_XSIZE]
		ld	b, a
		ld	a, [W_DS_CURXSIZE]
		inc	a
		cp	b
		jr	z, loc_25F6
		ld	[W_DS_CURXSIZE], a
		ld	a, [W_DS_POS0]
		inc	a
		ld	[W_DS_POS0], a
		ret	nz
		ld	a, [W_DS_POS0+1]
		inc	a
		ld	[W_DS_POS0+1], a
		ret
; ---------------------------------------------------------------------------

loc_25F6:				; CODE XREF: sub_25D8+9j
		xor	a
		ld	[W_DS_CURXSIZE], a
		ld	a, [W_DS_CURBITGROUP]
		and	a
		jr	z, loc_2610
		dec	a
		ld	[W_DS_CURBITGROUP], a
		ld	hl, W_DS_POS1
		ldi	a, [hl]
		ld	[W_DS_POS0], a
		ld	a, [hl]
		ld	[W_DS_POS0+1], a
		ret
; ---------------------------------------------------------------------------

loc_2610:				; CODE XREF: sub_25D8+26j
		ld	a, 3
		ld	[W_DS_CURBITGROUP], a
		ld	a, [W_DS_CURYSIZE]
		add	a, 8
		ld	[W_DS_CURYSIZE], a
		ld	b, a
		ld	a, [W_DS_YSIZE]
		cp	b
		jr	z, loc_2630
		ld	a, [W_DS_POS0]
		ld	l, a
		ld	a, [W_DS_POS0+1]
		ld	h, a
		inc	hl
		jp	DS_SetPositions
; ---------------------------------------------------------------------------

loc_2630:				; CODE XREF: sub_25D8+4Aj
		pop	hl
		xor	a
		ld	[W_DS_CURYSIZE], a
		ld	a, [W_DS_CURBUFFER]
		bit	1, a
		jr	nz, loc_2646
		xor	1
		set	1, a
		ld	[W_DS_CURBUFFER], a
		jp	DS_GetCurBuffer
; ---------------------------------------------------------------------------

loc_2646:				; CODE XREF: sub_25D8+62j
		jp	loc_26BF
; End of function sub_25D8


; =============== S U B	R O U T	I N E =======================================


sub_2649:				; CODE XREF: DS_Start+73p DS_Start+ACp
		ld	e, a
		ld	a, [W_DS_CURBITGROUP]
		and	a
		jr	z, loc_2664
		cp	2
		jr	c, loc_265C
		jr	z, loc_2662
		rrc	e
		rrc	e
		jr	loc_2664
; ---------------------------------------------------------------------------

loc_265C:				; CODE XREF: sub_2649+9j
		sla	e
		sla	e
		jr	loc_2664
; ---------------------------------------------------------------------------

loc_2662:				; CODE XREF: sub_2649+Bj
		swap	e

loc_2664:				; CODE XREF: sub_2649+5j sub_2649+11j	...
		ld	a, [W_DS_POS0]
		ld	l, a
		ld	a, [W_DS_POS0+1]
		ld	h, a
		ld	a, [hl]
		or	e
		ld	[hl], a
		ret
; End of function sub_2649


; ---------------------------------------------------------------------------
; SUBROUTINE
;
; Gets next bit of stream into a, increments position pointer and gets new
; byte if necessary
; ---------------------------------------------------------------------------

DS_GetNextBit:					; $2670
		ld	a, [W_DS_CURBIT]
		dec	a
		jr	nz, loc_267E
		call	DS_GetNextByte
		ld	[W_DS_CURBYTE], a
		ld	a, 8

loc_267E:				; CODE XREF: DS_GetNextBit+4j
		ld	[W_DS_CURBIT], a
		ld	a, [W_DS_CURBYTE]
		rlca
		ld	[W_DS_CURBYTE], a
		and	1
		ret
; End of function DS_GetNextBit


; ---------------------------------------------------------------------------
; SUBROUTINE
;
; Gets next byte of stream into a, increments position pointer
; ---------------------------------------------------------------------------

DS_GetNextByte:					; $268B
		ld	a, [W_DS_CURPOS]		; hl = current position
		ld	l, a
		ld	a, [W_DS_CURPOS+1]
		ld	h, a
		ld	a, [hl+]			; b = [hl+]			
		ld	b, a
		ld	a, l				; current position = hl (now incremented)
		ld	[W_DS_CURPOS], a		
		ld	a, h
		ld	[W_DS_CURPOS+1], a
		ld	a, b				; a = b (new byte)
		ret
; End of function DS_GetNextByte

; ---------------------------------------------------------------------------
; DATA
;
; RLE lookup table - the number of 1 bits (n) read at the start of an RLE packet
; is the index into this table. Then, an additional value (n+1 bits long) is
; read, and added to the value lifted from this table to get the total number
; of 00-bit groups to write.
; ---------------------------------------------------------------------------

DS_RLETable:					; $269F
		dw 1				
		dw 3
		dw 7
		dw $F
		dw $1F
		dw $3F
		dw $7F
		dw $FF
		dw $1FF
		dw $3FF
		dw $7FF
		dw $FFF
		dw $1FFF
		dw $3FFF
		dw $7FFF
		dw $FFFF

; ---------------------------------------------------------------------------
; START	OF FUNCTION CHUNK FOR sub_25D8

loc_26BF:				; CODE XREF: sub_25D8:loc_2646j
		ld	a, [W_DS_INTRP]
		cp	2
		jp	z, loc_2877
		and	a
		jp	nz, loc_27C7
		ld	hl, $A188
		call	sub_26D4
		ld	hl, $A310
; END OF FUNCTION CHUNK	FOR sub_25D8

; =============== S U B	R O U T	I N E =======================================


sub_26D4:				; CODE XREF: sub_25D8+F6p
					; sub_25D8+201p ...
		xor	a
		ld	[W_DS_CURYSIZE], a
		ld	[W_DS_CURXSIZE], a
		call	DS_SetPositions
		ld	a, [$D0AA]
		and	a
		jr	z, loc_26EC
		ld	hl, DS_BitTable1M
		ld	de, DS_BitTable2M
		jr	loc_26F2
; ---------------------------------------------------------------------------

loc_26EC:				; CODE XREF: sub_26D4+Ej
		ld	hl, DS_BitTable1
		ld	de, DS_BitTable2

loc_26F2:				; CODE XREF: sub_26D4+16j
		ld	a, l
		ld	[$D0B1], a
		ld	a, h
		ld	[$D0B2], a
		ld	a, e
		ld	[$D0B3], a
		ld	a, d
		ld	[$D0B4], a
		ld	e, 0

loc_2704:				; CODE XREF: sub_26D4+71j sub_26D4+92j
		ld	a, [W_DS_POS0]
		ld	l, a
		ld	a, [W_DS_POS0+1]
		ld	h, a
		ld	a, [hl]
		ld	b, a
		swap	a
		and	$F
		call	sub_276D
		swap	a
		ld	d, a
		ld	a, b
		and	$F
		call	sub_276D
		or	d
		ld	b, a
		ld	a, [W_DS_POS0]
		ld	l, a
		ld	a, [W_DS_POS0+1]
		ld	h, a
		ld	a, b
		ld	[hl], a
		ld	a, [W_DS_XSIZE]
		add	a, l
		jr	nc, loc_2731
		inc	h

loc_2731:				; CODE XREF: sub_26D4+5Aj
		ld	[W_DS_POS0], a
		ld	a, h
		ld	[W_DS_POS0+1], a
		ld	a, [W_DS_CURYSIZE]
		add	a, 8
		ld	[W_DS_CURYSIZE], a
		ld	b, a
		ld	a, [W_DS_YSIZE]
		cp	b
		jr	nz, loc_2704
		xor	a
		ld	e, a
		ld	[W_DS_CURYSIZE], a
		ld	a, [W_DS_CURXSIZE]
		inc	a
		ld	[W_DS_CURXSIZE], a
		ld	b, a
		ld	a, [W_DS_XSIZE]
		cp	b
		jr	z, loc_2768
		ld	a, [W_DS_POS1]
		ld	l, a
		ld	a, [W_DS_POS1+1]
		ld	h, a
		inc	hl
		call	DS_SetPositions
		jr	loc_2704
; ---------------------------------------------------------------------------

loc_2768:				; CODE XREF: sub_26D4+84j
		xor	a
		ld	[W_DS_CURXSIZE], a
		ret
; End of function sub_26D4


; =============== S U B	R O U T	I N E =======================================


sub_276D:				; CODE XREF: sub_26D4+3Ep sub_26D4+47p
		srl	a
		ld	c, 0
		jr	nc, loc_2775
		ld	c, 1

loc_2775:				; CODE XREF: sub_276D+4j
		ld	l, a
		ld	a, [$D0AA]
		and	a
		jr	z, loc_2780
		bit	3, e
		jr	loc_2782
; ---------------------------------------------------------------------------

loc_2780:				; CODE XREF: sub_276D+Dj
		bit	0, e

loc_2782:				; CODE XREF: sub_276D+11j
		ld	e, l
		jr	nz, loc_278E
		ld	a, [$D0B1]
		ld	l, a
		ld	a, [$D0B2]
		jr	loc_2795
; ---------------------------------------------------------------------------

loc_278E:				; CODE XREF: sub_276D+16j
		ld	a, [$D0B3]
		ld	l, a
		ld	a, [$D0B4]

loc_2795:				; CODE XREF: sub_276D+1Fj
		ld	h, a
		ld	a, e
		add	a, l
		ld	l, a
		jr	nc, loc_279C
		inc	h

loc_279C:				; CODE XREF: sub_276D+2Cj
		ld	a, [hl]
		bit	0, c
		jr	nz, loc_27A3
		swap	a

loc_27A3:				; CODE XREF: sub_276D+32j
		and	$F
		ld	e, a
		ret
; End of function sub_276D

; ---------------------------------------------------------------------------
DS_BitTable1:	db   1			; DATA XREF: sub_26D4:loc_26ECo
		db $32 ; 2
		db $76 ; v
		db $45 ; E
		db $FE ; þ
		db $CD ; Í
		db $89 ; ‰
		db $BA ; º
DS_BitTable2:	db $FE ; þ		; DATA XREF: sub_26D4+1Bo
		db $CD ; Í
		db $89 ; ‰
		db $BA ; º
		db   1
		db $32 ; 2
		db $76 ; v
		db $45 ; E
DS_BitTable1M:	db   8			; DATA XREF: sub_26D4+10o
		db $C4 ; Ä
		db $E6 ; æ
		db $2A ; *
		db $F7 ; ÷
		db $3B ; ;
		db $19
		db $D5 ; Õ
DS_BitTable2M:	db $F7 ; ÷		; DATA XREF: sub_26D4+13o
		db $3B ; ;
		db $19
		db $D5 ; Õ
		db   8
		db $C4 ; Ä
		db $E6 ; æ
		db $2A ; *
; ---------------------------------------------------------------------------
; START	OF FUNCTION CHUNK FOR sub_25D8

loc_27C7:				; CODE XREF: sub_25D8+F0j
					; sub_25D8+2BCj
		xor	a
		ld	[W_DS_CURYSIZE], a
		ld	[W_DS_CURXSIZE], a
		call	sub_2841
		ld	a, [W_DS_POS0]
		ld	l, a
		ld	a, [W_DS_POS0+1]
		ld	h, a
		call	sub_26D4
		call	sub_2841
		ld	a, [W_DS_POS0]
		ld	l, a
		ld	a, [W_DS_POS0+1]
		ld	h, a
		ld	a, [W_DS_POS1]
		ld	e, a
		ld	a, [W_DS_POS1+1]
		ld	d, a

loc_27EF:				; CODE XREF: sub_25D8+245j
					; sub_25D8+258j
		ld	a, [$D0AA]
		and	a
		jr	z, loc_280B
		push	de
		ld	a, [de]
		ld	b, a
		swap	a
		and	$F
		call	sub_2837
		swap	a
		ld	c, a
		ld	a, b
		and	$F
		call	sub_2837
		or	c
		pop	de
		ld	[de], a

loc_280B:				; CODE XREF: sub_25D8+21Bj
		ldi	a, [hl]
		ld	b, a
		ld	a, [de]
		xor	b
		ld	[de], a
		inc	de
		ld	a, [W_DS_CURXSIZE]
		inc	a
		ld	[W_DS_CURXSIZE], a
		ld	b, a
		ld	a, [W_DS_XSIZE]
		cp	b
		jr	nz, loc_27EF
		xor	a
		ld	[W_DS_CURXSIZE], a
		ld	a, [W_DS_CURYSIZE]
		add	a, 8
		ld	[W_DS_CURYSIZE], a
		ld	b, a
		ld	a, [W_DS_YSIZE]
		cp	b
		jr	nz, loc_27EF
		xor	a
		ld	[W_DS_CURYSIZE], a
		ret
; END OF FUNCTION CHUNK	FOR sub_25D8

; =============== S U B	R O U T	I N E =======================================


sub_2837:				; CODE XREF: sub_25D8+224p
					; sub_25D8+22Dp
		ld	de, Intp2Table
		add	a, e
		ld	e, a
		jr	nc, loc_283F
		inc	d

loc_283F:				; CODE XREF: sub_2837+5j
		ld	a, [de]
		ret
; End of function sub_2837


; =============== S U B	R O U T	I N E =======================================


sub_2841:				; CODE XREF: sub_25D8+1F6p
					; sub_25D8+204p ...
		ld	a, [W_DS_CURBUFFER]
		bit	0, a
		jr	nz, loc_2850
		ld	de, $A188
		ld	hl, $A310
		jr	loc_2856
; ---------------------------------------------------------------------------

loc_2850:				; CODE XREF: sub_2841+5j
		ld	de, $A310
		ld	hl, $A188

loc_2856:				; CODE XREF: sub_2841+Dj
		ld	a, l
		ld	[W_DS_POS0], a
		ld	a, h
		ld	[W_DS_POS0+1], a
		ld	a, e
		ld	[W_DS_POS1], a
		ld	a, d
		ld	[W_DS_POS1+1], a
		ret
; End of function sub_2841

; ---------------------------------------------------------------------------
Intp2Table:	db   0			; DATA XREF: sub_2837o
		db   8
		db   4
		db  $C
		db   2
		db  $A
		db   6
		db  $E
		db   1
		db   9
		db   5
		db  $D
		db   3
		db  $B
		db   7
		db  $F
; ---------------------------------------------------------------------------
; START	OF FUNCTION CHUNK FOR sub_25D8

loc_2877:				; CODE XREF: sub_25D8+ECj
		call	sub_2841
		ld	a, [$D0AA]
		push	af
		xor	a
		ld	[$D0AA], a
		ld	a, [W_DS_POS1]
		ld	l, a
		ld	a, [W_DS_POS1+1]
		ld	h, a
		call	sub_26D4
		call	sub_2841
		pop	af
		ld	[$D0AA], a
		jp	loc_27C7
; END OF FUNCTION CHUNK	FOR sub_25D8

; ---------------------------------------------------------------------------
; SUBROUTINE
;
; Sets POS0 and POS1 to the address in hl
; ---------------------------------------------------------------------------

DS_SetPositions:					; $2897
		ld	a, l
		ld	[W_DS_POS0], a
		ld	[W_DS_POS1], a
		ld	a, h
		ld	[W_DS_POS0+1], a
		ld	[W_DS_POS1+1], a
		ret
; End of function DS_SetPositions

; ---------------------------------------------------------------------------