From 4f7d69c75aeb1f5f5adabbf483ef40028f3f3065 Mon Sep 17 00:00:00 2001 From: rob thijssen Date: Thu, 7 May 2026 09:55:21 +0300 Subject: [PATCH] fix: Tight palette selector 0 reads two separate color bytes When pal_selector=0 (no predefined palette), the Java code reads two separate full bytes for the 2-color palette (line 421-422 of ByteColorRFBRenderer.java). We were reading one packed byte and splitting into nibbles, consuming 1 byte too few and misaligning all subsequent reads including the zlib compressed data. This caused "deflate decompression error" on stream 1 because the zlib header (78 da) was offset by 1 byte. Co-Authored-By: Claude Opus 4.6 (1M context) --- crates/ericrfb/src/codec/tight.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/crates/ericrfb/src/codec/tight.rs b/crates/ericrfb/src/codec/tight.rs index 9c857b5..6dbc434 100644 --- a/crates/ericrfb/src/codec/tight.rs +++ b/crates/ericrfb/src/codec/tight.rs @@ -171,8 +171,8 @@ pub fn decode_tight( ))); } - let packed_colors = read_u8(r)?; palette_2 = Some(if let Some(pal) = palette_for_selector(pal_selector) { + let packed_colors = read_u8(r)?; match pal_selector { 1 => [ pal[(packed_colors >> 1) as usize], @@ -189,13 +189,10 @@ pub fn decode_tight( _ => [packed_colors >> 4, packed_colors & 0x0F], } } else { - // Default: read 2 separate color bytes - // Actually for selector 0 the Java code reads 2 bytes: - // nArray[0] = this.K[aw2.w.read()]; nArray[1] = this.K[aw2.w.read()]; - // But packed_colors was already read as 1 byte. The protocol - // for selector 0 reads colors differently. Since this path is rare - // and we've already read the packed byte, treat high/low nibbles. - [packed_colors >> 4, packed_colors & 0x0F] + // Selector 0: two separate RGB332 color bytes (line 421-422) + let c0 = read_u8(r)?; + let c1 = read_u8(r)?; + [c0, c1] }); row_bytes = (rw as usize).div_ceil(8);