Alchemy
Loading...
Searching...
No Matches

decompress.c

Go to the documentation of this file.
1/// @file
2/// LZ decompression.
3/// Part of field.c, the field object, compiled only through it.
4
5#include "../field_internal.h"
6
7/// Decompresses an LZ stream from source into destination and returns
8/// destination. The stream starts with a little-endian halfword: the offset of
9/// its command bytes, or 0 for an uncompressed block, whose data (source + 2)
10/// is returned as it is. The literal bytes follow that halfword. Each command
11/// byte gives eight flags, low bit first: 1 copies the next literal byte; 0
12/// reads a big-endian halfword whose low 12 bits are a distance and high 4
13/// bits a length - 2 (or, when 0, the next byte + 16 + 2), and copies that many
14/// bytes from the literals' start minus the distance. A zero halfword ends the
15/// stream. Called only by Sprite_ComposeAnimationFrame, for a codec 3 (LZ)
16/// layer that has a draw parameter, into a 0x400-byte scratch buffer.
17u8 *Resource_DecompressLz(const u8 *source, u8 *destination) {
18 s32 token;
19 u32 length;
20 u32 control;
21 u8 *start;
22 const u8 *base;
23 const u8 *command;
24 const u8 *copy;
25 const u8 *literal;
26
27 // Uncompressed blocks borrow their payload; compressed blocks use the output.
28 token = source[0] | (source[1] << 8);
29 literal = source + 2;
30 if (token == 0)
31 return (u8 *)literal;
32 command = source + token;
33 control = *command;
34 base = literal;
35 start = destination;
36 command++;
37 // A marker bit, shifted down as the flags are read.
38 control |= 0x100;
39 // Consume literals or copy runs until the zero token ends the stream.
40 for (;;) {
41 if ((control & 1) != 0) {
42 // Only the marker left means: read the next command byte.
43 if (control != 1)
44 *destination++ = *literal++;
45 } else {
46 token = *command++ << 8;
47 token |= *command++;
48 if (token == 0)
49 break;
50 length = token >> 12;
51 if (length == 0) {
52 length = *command + 16;
53 command++;
54 }
55 length += 2;
56 // XXX: a run copies from before the literals' start, not from the
57 // output written so far; a codec 3 layer with a draw parameter would
58 // show whether its streams ever use a copy run.
59 copy = base - (token & 0x0fff);
60 while (length != 0) {
61 *destination++ = *copy++;
62 length--;
63 }
64 }
65 control >>= 1;
66 if (control == 0) {
67 control = *command;
68 command++;
69 control |= 0x100;
70 }
71 }
72 return start;
73}
u8 * Resource_DecompressLz(const u8 *source, u8 *destination)
Decompresses an LZ stream from source into destination and returns destination.
Definition decompress.c:17
What every part of the field object shares: its includes and the few names more than one part uses.
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
unsigned char u8
Definition types.h:11