[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