From fc7520c16f3a8738b7a8816d3cdc2b28d63f3d84 Mon Sep 17 00:00:00 2001 From: xwashere Date: Wed, 17 Apr 2024 13:15:34 -0400 Subject: [PATCH] [lcrash/cckernel] FIX: Add support for fixed huffman compression --- lcrash/setup/compressed/gzip.c | 87 ++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/lcrash/setup/compressed/gzip.c b/lcrash/setup/compressed/gzip.c index 7070a80..7a55024 100644 --- a/lcrash/setup/compressed/gzip.c +++ b/lcrash/setup/compressed/gzip.c @@ -150,54 +150,59 @@ uptr GzipDecompress(c8* Input, uptr InputSize, c8* Output) { case 0: { // NO COMPRESSION break; } - case 1: { - // FIXED HUFFMAN - break; - } + case 1: // FIXED HUFFMAN case 2: { // DYNAMIC HUFFMAN // Get huffman code counts - u64 OperationCount = GzipFetchBits(Stream, &BitLocation, 5) + 257; - u64 DistanceCount = GzipFetchBits(Stream, &BitLocation, 5) + 1; - u64 CodeCount = GzipFetchBits(Stream, &BitLocation, 4) + 4; + u64 OperationCount = (head & 2) ? 288 : GzipFetchBits(Stream, &BitLocation, 5) + 257; + u64 DistanceCount = (head & 2) ? 31 : GzipFetchBits(Stream, &BitLocation, 5) + 1; + u64 CodeCount = (head & 2) ? 0 : GzipFetchBits(Stream, &BitLocation, 4) + 4; + u8 Lengths[OperationCount + DistanceCount] = {}; - const u8 CodeLengthLengthOffset[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; - u8 CodeLengthLengthProto[19] = {}; - for (int i = 0; i < CodeCount; i++) { - CodeLengthLengthProto[CodeLengthLengthOffset[i]] = GzipFetchBits(Stream, &BitLocation, 3); - } + if (head & 2) { // Build fixed huffman lengths + for (int i = 0; i <= 143; i++) Lengths[i] = 8; + for (int i = 143; i <= 255; i++) Lengths[i] = 9; + for (int i = 256; i <= 279; i++) Lengths[i] = 7; + for (int i = 280; i <= 287; i++) Lengths[i] = 8; + for (int i = 288; i <= 319; i++) Lengths[i] = 5; + } else { // Build dynamic huffman lengths + const u8 CodeLengthLengthOffset[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + u8 CodeLengthLengthProto[19] = {}; + for (int i = 0; i < CodeCount; i++) { + CodeLengthLengthProto[CodeLengthLengthOffset[i]] = GzipFetchBits(Stream, &BitLocation, 3); + } - // Build our decoding tables - u8 CodeLengthLengths[0x80] = {}; - u32 CodeLengthSymbols[0x80] = {}; - GzipPopulateTable(CodeLengthLengthProto, 19, CodeLengthLengths, CodeLengthSymbols, 0x80, 7); + // Build our decoding tables + u8 CodeLengthLengths[0x80] = {}; + u32 CodeLengthSymbols[0x80] = {}; + GzipPopulateTable(CodeLengthLengthProto, 19, CodeLengthLengths, CodeLengthSymbols, 0x80, 7); - // Collect lengths - u8 Lengths[OperationCount + DistanceCount] = {}; - uptr CurrentLen = 0; - while (CurrentLen < OperationCount + DistanceCount) { - // Fetch the next op - u64 Code = GzipFetchBits(Stream, &BitLocation, 7); - u64 Error = 7 - CodeLengthLengths[Code]; - BitLocation -= Error; - Code = CodeLengthSymbols[Code]; + // Collect lengths + uptr CurrentLen = 0; + while (CurrentLen < OperationCount + DistanceCount) { + // Fetch the next op + u64 Code = GzipFetchBits(Stream, &BitLocation, 7); + u64 Error = 7 - CodeLengthLengths[Code]; + BitLocation -= Error; + Code = CodeLengthSymbols[Code]; - if (Code < 16) { // Literal - Lengths[CurrentLen++] = Code; - } else { // Repeat - u64 RepeatCount = 0; - u64 RepeatedLen = 0; + if (Code < 16) { // Literal + Lengths[CurrentLen++] = Code; + } else { // Repeat + u64 RepeatCount = 0; + u64 RepeatedLen = 0; - if (Code == 16) { - RepeatCount = 3 + GzipFetchBits(Stream, &BitLocation, 2); - RepeatedLen = CurrentLen > 0 ? Lengths[CurrentLen - 1] : 0; - } else if (Code == 17) { - RepeatCount = 3 + GzipFetchBits(Stream, &BitLocation, 3); - } else if (Code == 18) { - RepeatCount =11 + GzipFetchBits(Stream, &BitLocation, 7); - } else {} // Should be unreachable - - for (int i = 0; i < RepeatCount; i++) { - Lengths[CurrentLen++] = RepeatedLen; + if (Code == 16) { + RepeatCount = 3 + GzipFetchBits(Stream, &BitLocation, 2); + RepeatedLen = CurrentLen > 0 ? Lengths[CurrentLen - 1] : 0; + } else if (Code == 17) { + RepeatCount = 3 + GzipFetchBits(Stream, &BitLocation, 3); + } else if (Code == 18) { + RepeatCount =11 + GzipFetchBits(Stream, &BitLocation, 7); + } else {} // Should be unreachable + + for (int i = 0; i < RepeatCount; i++) { + Lengths[CurrentLen++] = RepeatedLen; + } } } }