# Parameters for a 'dcmp' (2)-compressed resource.
# 2 bytes: Unknown meaning, doesn't appear to have any effect on the decompression algorithm. Usually zero, sometimes set to a small integer (< 10). On 'lpch' resources, the value is always nonzero, and sometimes larger than usual.
# 1 byte: Number of entries in the custom lookup table minus one. Set to zero if the default lookup table is used.
# 1 byte: Flags. See the ParameterFlags enum below for details.
STRUCT_PARAMETERS=struct.Struct(">HBB")
# Default lookup table.
# If the custom table flag is set, a custom table (usually with fewer than 256 entries) is used instead of this one.
# This table was obtained by decompressing a manually created compressed resource with the following contents:
TAGGED=1<<1# The compressed data is tagged, meaning that it consists of "blocks" of a tag byte followed by 8 table references and/or literals. See comments in the decompress function for details.
CUSTOM_TABLE=1<<0# A custom lookup table is included before the compressed data, which is used instead of the default table.
# Special case: if we are at the last byte of the compressed data, and the decompressed data has an odd length, the last byte is a single literal byte, and not a table reference.
ifdebug:
print(f"Last byte: {data[-1:]}")
parts.append(data[-1:])
break
# Compressed data is untagged, every byte is a table reference.
# Special case: if we are at the last byte of the compressed data, and the decompressed data has an odd length, the last byte is a single literal byte, and not a tag or a table reference.
ifdebug:
print(f"Last byte: {data[-1:]}")
parts.append(data[-1:])
break
# Compressed data is tagged, each tag byte is followed by 8 table references and/or literals.
tag=data[i]
ifdebug:
print(f"Tag: 0b{tag:>08b}")
i+=1
foris_refin_split_bits(tag):
ifis_ref:
# This is a table reference (a single byte that is an index into the table).
# This is a literal (two uncompressed bytes that are literally copied into the output).
# Note: if i == len(data)-1, the literal is actually only a single byte long.
# This case is handled automatically - the slice extends one byte past the end of the data, and only one byte is returned.
ifdebug:
print(f"Literal: {data[i:i+2]}")
parts.append(data[i:i+2])
i+=2
# If the end of the compressed data is reached in the middle of a chunk, all further tag bits are ignored (they should be zero) and decompression ends.