Created
February 2, 2026 12:38
-
-
Save cs127/358494e220a68b04a0443413df91a7e9 to your computer and use it in GitHub Desktop.
Impulse Tracker sample decompressor in Godot
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Impulse Tracker sample decompressor | |
| # based on kb's decompressor | |
| # cs127 2025-12-12 | |
| class_name ITSEx | |
| extends RefCounted | |
| @warning_ignore_start("integer_division") | |
| @warning_ignore_start("shadowed_variable") | |
| enum ReadIndex {ERROR, DATA} | |
| class Block: | |
| var cmp_buf: PackedByteArray | |
| var cmp_length: int | |
| var cmp_bit_pos: int = 0 | |
| var b16: bool | |
| var it215: bool | |
| var decmp_length: int | |
| var decmp_pos: int = 0 | |
| var width: int | |
| var d1: int = 0 | |
| var d2: int = 0 | |
| var error: Error = Error.OK | |
| static func to_signed(x: int, b16: bool) -> int: | |
| x &= 0xFFFF if b16 else 0xFF | |
| if x & (0x8000 if b16 else 0x80): x |= -0x10000 if b16 else -0x100 | |
| return x | |
| func read_bits(n: int) -> int: | |
| var bits := 0 | |
| if n == 0: return 0 | |
| if cmp_bit_pos + n > cmp_length * 8: | |
| error = Error.ERR_FILE_EOF | |
| return 0 | |
| var cmp_byte_pos := cmp_bit_pos >> 3 | |
| var cmp_bit_pos_rel := cmp_bit_pos & 7 | |
| bits = cmp_buf.decode_u32(cmp_byte_pos) | |
| bits >>= cmp_bit_pos_rel | |
| bits &= (1 << n) - 1 | |
| cmp_bit_pos += n | |
| return bits | |
| func decompress() -> PackedByteArray: | |
| var decmp := PackedByteArray() | |
| decmp.resize(decmp_length * (2 if b16 else 1)) | |
| var bit_depth := 16 if b16 else 8 | |
| while decmp_pos < decmp_length: | |
| var value := read_bits(width) | |
| if width <= 6: # method 1 (1..6 bits) | |
| if value == 1 << (width - 1): | |
| # read new width and expand | |
| value = read_bits(4 if b16 else 3) + 1 | |
| width = value + (0 if value < width else 1) | |
| continue | |
| elif width <= bit_depth: # method 2 (7..8/16 bits) | |
| var all_bits := 0xFFFF if b16 else 0xFF | |
| var border := (all_bits >> (bit_depth + 1 - width)) - (bit_depth / 2) & all_bits | |
| if value > border and value <= border + bit_depth: | |
| # convert and expand width | |
| value -= border | |
| width = value + (0 if value < width else 1) | |
| continue | |
| elif width == bit_depth + 1: # method 3 (9/17 bits) | |
| if value & (1 << bit_depth): | |
| # new width | |
| width = (value + 1) & 0xFF | |
| continue | |
| else: # invalid method | |
| error = Error.ERR_INVALID_DATA | |
| return [] | |
| var shift: int = max(bit_depth - width, 0) | |
| value = to_signed(value << shift, b16) >> shift | |
| d1 += value | |
| if it215: d2 += d1 # integrate a second time for 215 | |
| var smp: int = to_signed(d2 if it215 else d1, b16) | |
| if b16: | |
| smp &= 0xFFFF | |
| decmp[decmp_pos * 2 + 0] = (smp >> 0) & 0xFF | |
| decmp[decmp_pos * 2 + 1] = (smp >> 8) & 0xFF | |
| else: | |
| smp &= 0xFF | |
| decmp[decmp_pos] = smp | |
| decmp_pos += 1 | |
| return decmp | |
| func _init(src: StreamPeer, decmp_length_left: int, b16: bool, it215: bool) -> void: | |
| if src.get_position() + 2 > src.get_size(): | |
| error = Error.ERR_FILE_EOF | |
| return | |
| var read := src.get_data(src.get_u16()) | |
| if read[ReadIndex.ERROR]: | |
| error = read[ReadIndex.ERROR] | |
| return | |
| cmp_buf = read[ReadIndex.DATA] | |
| cmp_length = cmp_buf.size() | |
| cmp_buf.append_array([0, 0, 0]) | |
| self.b16 = b16 | |
| self.it215 = it215 | |
| decmp_length = min(decmp_length_left, 0x4000 if b16 else 0x8000) | |
| width = 17 if b16 else 9 | |
| static func decompress(src: StreamPeer, dst: PackedByteArray, length: int, b16: bool, it215: bool) -> Error: | |
| src.big_endian = false | |
| dst.clear() | |
| while length: | |
| var block := Block.new(src, length, b16, it215) | |
| if block.error: return block.error | |
| var decmp := block.decompress() | |
| if not decmp: return block.error | |
| dst.append_array(decmp) | |
| length -= block.decmp_length | |
| return Error.OK | |
| @warning_ignore_restore("integer_division") | |
| @warning_ignore_restore("shadowed_variable") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment