shithub: pokecrystal

Download patch

ref: 21708a2271974e35cbb3eb41fe219a49d7d40ae9
parent: 20444d2f63ffc1545d5fda81fd3883235be92a4c
author: yenatch <[email protected]>
date: Tue Jun 3 10:08:23 EDT 2014

Recomment lz deecompression.

--- a/home/decompress.asm
+++ b/home/decompress.asm
@@ -1,19 +1,14 @@
 FarDecompress:: ; b40
-; Decompress graphics data at a:hl to de
+; Decompress graphics data from a:hl to de.
 
-; put a away for a sec
 	ld [$c2c4], a
-; save bank
 	ld a, [hROMBank]
 	push af
-; bankswitch
 	ld a, [$c2c4]
 	rst Bankswitch
-	
-; what we came here for
+
 	call Decompress
-	
-; restore bank
+
 	pop af
 	rst Bankswitch
 	ret
@@ -22,259 +17,238 @@
 
 Decompress:: ; b50
 ; Pokemon Crystal uses an lz variant for compression.
+; This is mainly (but not necessarily) used for graphics.
 
-; This is mainly used for graphics, but the intro's
-; tilemaps also use this compression.
+; This function decompresses lz-compressed data from hl to de.
 
-; This function decompresses lz-compressed data at hl to de.
 
+LZ_END EQU $ff ; Compressed data is terminated with $ff.
 
-; Basic rundown:
 
-;	A typical control command consists of:
-;		-the command (bits 5-7)
-;		-the count (bits 0-4)
-;		-and any additional params
+; A typical control command consists of:
 
-;	$ff is used as a terminator.
+LZ_CMD EQU %11100000 ; command id (bits 5-7)
+LZ_LEN EQU %00011111 ; length n   (bits 0-4)
 
+; Additional parameters are read during command execution.
 
-;	Commands:
 
-;		0: literal
-;			literal data for some number of bytes
-;		1: iterate
-;			one byte repeated for some number of bytes
-;		2: alternate
-;			two bytes alternated for some number of bytes
-;		3: zero (whitespace)
-;			0x00 repeated for some number of bytes
+; Commands:
 
-;	Repeater control commands have a signed parameter used to determine the start point.
-;	Wraparound is simulated:
-;		Positive values are added to the start address of the decompressed data
-;		and negative values are subtracted from the current position.
+LZ_LITERAL   EQU 0 << 5 ; Read literal data for n bytes.
+LZ_ITERATE   EQU 1 << 5 ; Write the same byte for n bytes.
+LZ_ALTERNATE EQU 2 << 5 ; Alternate two bytes for n bytes.
+LZ_ZERO      EQU 3 << 5 ; Write 0 for n bytes.
 
-;		4: repeat
-;			repeat some number of bytes from decompressed data
-;		5: flipped
-;			repeat some number of flipped bytes from decompressed data
-;			ex: $ad = %10101101 -> %10110101 = $b5
-;		6: reverse
-;			repeat some number of bytes in reverse from decompressed data
 
-;	If the value in the count needs to be larger than 5 bits,
-;	control code 7 can be used to expand the count to 10 bits.
+; Another class of commands reuses data from the decompressed output.
+LZ_RW        EQU 2 + 5 ; bit
 
-;		A new control command is read in bits 2-4.
-;		The new 10-bit count is split:
-;			bits 0-1 contain the top 2 bits
-;			another byte is added containing the latter 8
+; These commands take a signed offset to start copying from.
+; Wraparound is simulated.
+; Positive offsets (15-bit) are added to the start address.
+; Negative offsets (7-bit) are subtracted from the current position.
 
-;		So, the structure of the control command becomes:
-;			111xxxyy yyyyyyyy
-;			 |  |  |    |
-;            |  | our new count
-;            | the control command for this count
-;            7 (this command)
+LZ_REPEAT    EQU 4 << 5 ; Repeat n bytes from the offset.
+LZ_FLIP      EQU 5 << 5 ; Repeat n bitflipped bytes.
+LZ_REVERSE   EQU 6 << 5 ; Repeat n bytes in reverse.
 
-; For more information, refer to the code below and in extras/gfx.py .
 
-; save starting output address
+; If the value in the count needs to be larger than 5 bits,
+; LZ_LONG can be used to expand the count to 10 bits.
+LZ_LONG      EQU 7 << 5
+
+; A new control command is read in bits 2-4.
+; The top two bits of the length are bits 0-1.
+; Another byte is read containing the bottom 8 bits.
+LZ_LONG_HI   EQU %00000011
+
+; In other words, the structure of the command becomes
+; 111xxxyy yyyyyyyy
+; x: the new control command
+; y: the length
+
+
+; For more information, refer to the code below and in extras/gfx.py.
+
+
+	; Save the output address
+	; for rewrite commands.
 	ld a, e
 	ld [$c2c2], a
 	ld a, d
-	ld [$c2c3], a
-	
-.loop
-; get next byte
+	ld [$c2c2 + 1], a
+
+.Main
 	ld a, [hl]
-; done?
-	cp $ff ; end
+	cp LZ_END
 	ret z
 
-; get control code
-	and %11100000
-	
-; 10-bit param?
-	cp $e0 ; LZ_HI
-	jr nz, .normal
-	
-	
-; 10-bit param:
+	and LZ_CMD
 
-; get next 3 bits (%00011100)
+	cp LZ_LONG
+	jr nz, .short
+
+.long
+; The count is now 10 bits.
+
+	; Read the next 3 bits.
+	; %00011100 -> %11100000
 	ld a, [hl]
 	add a
 	add a ; << 3
 	add a
-	
-; this is our new control code
-	and %11100000
+
+        ; This is our new control code.
+	and LZ_CMD
 	push af
-	
-; get param hi
+
 	ld a, [hli]
-	and %00000011
+	and LZ_LONG_HI
 	ld b, a
-	
-; get param lo
 	ld a, [hli]
 	ld c, a
-	
-; read at least 1 byte
+
+	; read at least 1 byte
 	inc bc
-	jr .readers
-	
-	
-.normal
-; push control code
+	jr .command
+
+
+.short
 	push af
-; get param
+
 	ld a, [hli]
-	and %00011111
+	and LZ_LEN
 	ld c, a
-	ld b, $0
-; read at least 1 byte
+	ld b, 0
+
+	; read at least 1 byte
 	inc c
-	
-.readers
-; let's get started
 
-; inc loop counts since we bail as soon as they hit 0
+
+.command
+	; Increment loop counts.
+	; We bail the moment they hit 0.
 	inc b
 	inc c
-	
-; get control code
+
 	pop af
-; command type
-	bit 7, a ; 80, a0, c0
-	jr nz, .repeatertype
-	
-; literals
-	cp $20 ; LZ_ITER
-	jr z, .iter
-	cp $40 ; LZ_ALT
-	jr z, .alt
-	cp $60 ; LZ_ZERO
-	jr z, .zero
-	; else $00
-	
-; 00 ; LZ_LIT
-; literal data for bc bytes
-.loop1
-; done?
+
+	bit LZ_RW, a
+	jr nz, .rewrite
+
+	cp LZ_ITERATE
+	jr z, .Iter
+	cp LZ_ALTERNATE
+	jr z, .Alt
+	cp LZ_ZERO
+	jr z, .Zero
+
+
+.Literal
+; Read literal data for bc bytes.
+.lloop
 	dec c
-	jr nz, .next1
+	jr nz, .lnext
 	dec b
-	jp z, .loop
-	
-.next1
+	jp z, .Main
+
+.lnext
 	ld a, [hli]
 	ld [de], a
 	inc de
-	jr .loop1
-	
-	
-; 20 ; LZ_ITER
-; write byte for bc bytes
-.iter
+	jr .lloop
+
+
+.Iter
+; Write the same byte for bc bytes.
 	ld a, [hli]
-	
+
 .iterloop
 	dec c
 	jr nz, .iternext
 	dec b
-	jp z, .loop
-	
+	jp z, .Main
+
 .iternext
 	ld [de], a
 	inc de
 	jr .iterloop
-	
-	
-; 40 ; LZ_ALT
-; alternate two bytes for bc bytes
 
-; next pair
-.alt
-; done?
+
+.Alt
+; Alternate two bytes for bc bytes.
 	dec c
-	jr nz, .alt0
+	jr nz, .anext1
 	dec b
-	jp z, .altclose0
-	
-; alternate for bc
-.alt0
+	jp z, .adone1
+.anext1
 	ld a, [hli]
 	ld [de], a
 	inc de
+
 	dec c
-	jr nz, .alt1
-; done?
+	jr nz, .anext2
 	dec b
-	jp z, .altclose1
-.alt1
+	jp z, .adone2
+.anext2
 	ld a, [hld]
 	ld [de], a
 	inc de
-	jr .alt
-	
-; skip past the bytes we were alternating
-.altclose0
+
+	jr .Alt
+
+	; Skip past the bytes we were alternating.
+.adone1
 	inc hl
-.altclose1
+.adone2
 	inc hl
-	jr .loop
-	
-	
-; 60 ; LZ_ZERO
-; write 00 for bc bytes
-.zero
+	jr .Main
+
+
+.Zero
+; Write 0 for bc bytes.
 	xor a
-	
-.zeroloop
+
+.zloop
 	dec c
-	jr nz, .zeronext
+	jr nz, .znext
 	dec b
-	jp z, .loop
-	
-.zeronext
+	jp z, .Main
+
+.znext
 	ld [de], a
 	inc de
-	jr .zeroloop
-	
-	
-; repeats
-; 80, a0, c0
-; repeat decompressed data from output
-.repeatertype
+	jr .zloop
+
+
+.rewrite
+; Repeat decompressed data from output.
 	push hl
 	push af
-; get next byte
+
 	ld a, [hli]
-; absolute?
-	bit 7, a
-	jr z, .absolute
-	
-; relative
-; a = -a
-	and %01111111 ; forget the bit we just looked at
+	bit 7, a ; sign
+	jr z, .positive
+
+.negative
+; hl = de - a
+	; Since we can't subtract a from de,
+	; Make it negative and add de.
+	and %01111111
 	cpl
-; add de (current output address)
 	add e
 	ld l, a
-	ld a, $ff ; -1
+	ld a, -1
 	adc d
 	ld h, a
-	jr .repeaters
-	
-.absolute
-; get next byte (lo)
+	jr .ok
+
+.positive
+; Positive offsets are two bytes.
 	ld l, [hl]
-; last byte (hi)
 	ld h, a
-; add starting output address
+	; add to starting output address
 	ld a, [$c2c2]
 	add l
 	ld l, a
@@ -281,87 +255,87 @@
 	ld a, [$c2c3]
 	adc h
 	ld h, a
-	
-.repeaters
+
+.ok
 	pop af
-	cp $80 ; LZ_REPEAT
-	jr z, .repeat
-	cp $a0 ; LZ_FLIP
-	jr z, .flip
-	cp $c0 ; LZ_REVERSE
-	jr z, .reverse
-	
-; e0 -> 80
-	
-; 80 ; LZ_REPEAT
-; repeat some decompressed data
-.repeat
-; done?
+
+	cp LZ_REPEAT
+	jr z, .Repeat
+	cp LZ_FLIP
+	jr z, .Flip
+	cp LZ_REVERSE
+	jr z, .Reverse
+
+; Since LZ_LONG is command 7,
+; only commands 0-6 are passed in.
+; This leaves room for an extra command 7.
+; However, lengths longer than 768
+; would be interpreted as LZ_END.
+
+; For now, it defaults to LZ_REPEAT.
+
+
+.Repeat
+; Copy decompressed data for bc bytes.
 	dec c
-	jr nz, .repeatnext
+	jr nz, .rnext
 	dec b
-	jr z, .cleanup
-	
-.repeatnext
+	jr z, .donerw
+
+.rnext
 	ld a, [hli]
 	ld [de], a
 	inc de
-	jr .repeat
-	
-	
-; a0 ; LZ_FLIP
-; repeat some decompressed data w/ flipped bit order
-.flip
+	jr .Repeat
+
+
+.Flip
+; Copy bitflipped decompressed data for bc bytes.
 	dec c
-	jr nz, .flipnext
+	jr nz, .fnext
 	dec b
-	jp z, .cleanup
-	
-.flipnext
+	jp z, .donerw
+
+.fnext
 	ld a, [hli]
 	push bc
-	ld bc, $0008
-	
-.fliploop
+	lb bc, 0, 8
+
+.floop
 	rra
 	rl b
 	dec c
-	jr nz, .fliploop
+	jr nz, .floop
 	ld a, b
 	pop bc
 	ld [de], a
 	inc de
-	jr .flip
-	
-	
-; c0 ; LZ_REVERSE
-; repeat some decompressed data in reverse
-.reverse
+	jr .Flip
+
+
+.Reverse
+; Copy reversed decompressed data for bc bytes.
 	dec c
-	jr nz, .reversenext
-	
+	jr nz, .rvnext
+
 	dec b
-	jp z, .cleanup
-	
-.reversenext
+	jp z, .donerw
+
+.rvnext
 	ld a, [hld]
 	ld [de], a
 	inc de
-	jr .reverse
-	
-	
-.cleanup
-; get type of repeat we just used
+	jr .Reverse
+
+
+.donerw
 	pop hl
-; was it relative or absolute?
+
 	bit 7, [hl]
 	jr nz, .next
-
-; skip two bytes for absolute
-	inc hl
-; skip one byte for relative
+	inc hl ; positive offset is two bytes
 .next
 	inc hl
-	jp .loop
+	jp .Main
 ; c2f