1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
; initializes variables used to decompress data in DecompressData
; de = source of compressed data
; b = HIGH byte of secondary buffer ($100 bytes of buffer space)
; also clears this $100 byte space
InitDataDecompression:
ld hl, wDecompSourcePosPtr
ld [hl], e
inc hl
ld [hl], d
ld hl, wDecompNumCommandBitsLeft
ld [hl], 1
inc hl
xor a
ld [hli], a ; wDecompCommandByte
ld [hli], a ; wDecompRepeatModeToggle
ld [hli], a ; wDecompRepeatLengths
ld [hli], a ; wDecompNumBytesToRepeat
ld [hl], b ; wDecompSecondaryBufferPtrHigh
inc hl
ld [hli], a ; wDecompRepeatSeqOffset
ld [hl], LOW(wDecompressionSecondaryBufferStart) ; wDecompSecondaryBufferPtrLow
; clear buffer
ld h, b
ld l, LOW(wDecompressionSecondaryBuffer)
xor a
.loop
ld [hl], a
inc l
jr nz, .loop
ret
; decompresses data
; uses values initialized by InitDataDecompression
; wDecompSourcePosPtr holds the pointer for compressed source
; input:
; bc = row width
; de = buffer to place decompressed data
DecompressData:
push hl
push de
.loop
push bc
call .Decompress
ld [de], a
inc de
pop bc
dec bc
ld a, c
or b
jr nz, .loop
pop de
pop hl
ret
; decompression works as follows:
; first a command byte is read that will dictate how the
; following bytes will be copied
; the position will then move to the next byte (0xXY), and
; the command byte's bits are read from higher to lower bit
; - if command bit is set, then copy 0xXY to buffer;
; - if command bit is not set, then decompression enters "repeat mode,"
; which means it stores 0xXY in memory as number of bytes to repeat
; from a given offset. This offset is in the next byte in the data,
; 0xZZ, which tells the offset to start repeating. A toggle is switched
; each time the algorithm hits "repeat mode":
; - if off -> on it reads 0xXY and stores it,
; then repeats (0x0X + 2) bytes from the offset starting at 0xZZ;
; - if on -> off, then the data only provides the offset,
; and the previous byte read for number of bytes to repeat, 0xXY, is reused
; in which case (0x0Y + 2) bytes are repeated starting from the offset.
.Decompress:
ld hl, wDecompNumBytesToRepeat
ld a, [hl]
or a
jr z, .read_command
; still repeating sequence
dec [hl]
inc hl
.repeat_byte
ld b, [hl] ; wDecompSecondaryBufferPtrHigh
inc hl
ld c, [hl] ; wDecompRepeatSeqOffset
inc [hl]
inc hl
ld a, [bc]
ld c, [hl] ; wDecompSecondaryBufferPtrLow
inc [hl]
ld [bc], a
ret
.read_command
ld hl, wDecompSourcePosPtr
ld c, [hl]
inc hl
ld b, [hl]
inc hl ; wDecompNumCommandBitsLeft
dec [hl]
inc hl ; wDecompCommandByte
jr nz, .read_command_bit
dec hl ; wDecompNumCommandBitsLeft
ld [hl], 8 ; number of bits
inc hl ; wDecompCommandByte
ld a, [bc]
inc bc
ld [hl], a
.read_command_bit
rl [hl]
ld a, [bc]
inc bc
jr nc, .repeat_command
; copy 1 byte literally
ld hl, wDecompSourcePosPtr
ld [hl], c
inc hl
ld [hl], b
ld hl, wDecompSecondaryBufferPtrHigh
ld b, [hl]
inc hl
inc hl
ld c, [hl] ; wDecompSecondaryBufferPtrLow
inc [hl]
ld [bc], a
ret
.repeat_command
ld [wDecompRepeatSeqOffset], a ; save the offset to repeat from
ld hl, wDecompRepeatModeToggle
bit 0, [hl]
jr nz, .repeat_mode_toggle_on
set 0, [hl]
inc hl
; read byte for num of bytes to read
; and use its higher nybble
ld a, [bc]
inc bc
ld [hli], a ; wDecompRepeatLengths
swap a
.get_sequence_len
and $f
inc a ; number of times to repeat
ld [hli], a ; wDecompNumBytesToRepeat
push hl
ld hl, wDecompSourcePosPtr
ld [hl], c
inc hl
ld [hl], b
pop hl
jr .repeat_byte
.repeat_mode_toggle_on
; get the previous byte (num of bytes to repeat)
; and use its lower nybble
res 0, [hl]
inc hl
ld a, [hli] ; wDecompRepeatLengths
jr .get_sequence_len
|