[lcrash/cckernel] FIX: Add support for fixed huffman compression
This commit is contained in:
parent
d81dd11837
commit
fc7520c16f
@ -150,54 +150,59 @@ uptr GzipDecompress(c8* Input, uptr InputSize, c8* Output) {
|
|||||||
case 0: { // NO COMPRESSION
|
case 0: { // NO COMPRESSION
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1: {
|
case 1: // FIXED HUFFMAN
|
||||||
// FIXED HUFFMAN
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: { // DYNAMIC HUFFMAN
|
case 2: { // DYNAMIC HUFFMAN
|
||||||
// Get huffman code counts
|
// Get huffman code counts
|
||||||
u64 OperationCount = GzipFetchBits(Stream, &BitLocation, 5) + 257;
|
u64 OperationCount = (head & 2) ? 288 : GzipFetchBits(Stream, &BitLocation, 5) + 257;
|
||||||
u64 DistanceCount = GzipFetchBits(Stream, &BitLocation, 5) + 1;
|
u64 DistanceCount = (head & 2) ? 31 : GzipFetchBits(Stream, &BitLocation, 5) + 1;
|
||||||
u64 CodeCount = GzipFetchBits(Stream, &BitLocation, 4) + 4;
|
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 };
|
if (head & 2) { // Build fixed huffman lengths
|
||||||
u8 CodeLengthLengthProto[19] = {};
|
for (int i = 0; i <= 143; i++) Lengths[i] = 8;
|
||||||
for (int i = 0; i < CodeCount; i++) {
|
for (int i = 143; i <= 255; i++) Lengths[i] = 9;
|
||||||
CodeLengthLengthProto[CodeLengthLengthOffset[i]] = GzipFetchBits(Stream, &BitLocation, 3);
|
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
|
// Build our decoding tables
|
||||||
u8 CodeLengthLengths[0x80] = {};
|
u8 CodeLengthLengths[0x80] = {};
|
||||||
u32 CodeLengthSymbols[0x80] = {};
|
u32 CodeLengthSymbols[0x80] = {};
|
||||||
GzipPopulateTable(CodeLengthLengthProto, 19, CodeLengthLengths, CodeLengthSymbols, 0x80, 7);
|
GzipPopulateTable(CodeLengthLengthProto, 19, CodeLengthLengths, CodeLengthSymbols, 0x80, 7);
|
||||||
|
|
||||||
// Collect lengths
|
// Collect lengths
|
||||||
u8 Lengths[OperationCount + DistanceCount] = {};
|
uptr CurrentLen = 0;
|
||||||
uptr CurrentLen = 0;
|
while (CurrentLen < OperationCount + DistanceCount) {
|
||||||
while (CurrentLen < OperationCount + DistanceCount) {
|
// Fetch the next op
|
||||||
// Fetch the next op
|
u64 Code = GzipFetchBits(Stream, &BitLocation, 7);
|
||||||
u64 Code = GzipFetchBits(Stream, &BitLocation, 7);
|
u64 Error = 7 - CodeLengthLengths[Code];
|
||||||
u64 Error = 7 - CodeLengthLengths[Code];
|
BitLocation -= Error;
|
||||||
BitLocation -= Error;
|
Code = CodeLengthSymbols[Code];
|
||||||
Code = CodeLengthSymbols[Code];
|
|
||||||
|
|
||||||
if (Code < 16) { // Literal
|
if (Code < 16) { // Literal
|
||||||
Lengths[CurrentLen++] = Code;
|
Lengths[CurrentLen++] = Code;
|
||||||
} else { // Repeat
|
} else { // Repeat
|
||||||
u64 RepeatCount = 0;
|
u64 RepeatCount = 0;
|
||||||
u64 RepeatedLen = 0;
|
u64 RepeatedLen = 0;
|
||||||
|
|
||||||
if (Code == 16) {
|
if (Code == 16) {
|
||||||
RepeatCount = 3 + GzipFetchBits(Stream, &BitLocation, 2);
|
RepeatCount = 3 + GzipFetchBits(Stream, &BitLocation, 2);
|
||||||
RepeatedLen = CurrentLen > 0 ? Lengths[CurrentLen - 1] : 0;
|
RepeatedLen = CurrentLen > 0 ? Lengths[CurrentLen - 1] : 0;
|
||||||
} else if (Code == 17) {
|
} else if (Code == 17) {
|
||||||
RepeatCount = 3 + GzipFetchBits(Stream, &BitLocation, 3);
|
RepeatCount = 3 + GzipFetchBits(Stream, &BitLocation, 3);
|
||||||
} else if (Code == 18) {
|
} else if (Code == 18) {
|
||||||
RepeatCount =11 + GzipFetchBits(Stream, &BitLocation, 7);
|
RepeatCount =11 + GzipFetchBits(Stream, &BitLocation, 7);
|
||||||
} else {} // Should be unreachable
|
} else {} // Should be unreachable
|
||||||
|
|
||||||
for (int i = 0; i < RepeatCount; i++) {
|
for (int i = 0; i < RepeatCount; i++) {
|
||||||
Lengths[CurrentLen++] = RepeatedLen;
|
Lengths[CurrentLen++] = RepeatedLen;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user