From f550c9654195b4014e124155ac2cf083f8388560 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Mon, 2 Jan 2023 23:35:09 -0800 Subject: [PATCH] Take some cues from libmspack --- .../Quantum/Decompressor.cs | 51 +++--- BurnOutSharp.Compression/Quantum/State.cs | 150 ++++++++++-------- 2 files changed, 102 insertions(+), 99 deletions(-) diff --git a/BurnOutSharp.Compression/Quantum/Decompressor.cs b/BurnOutSharp.Compression/Quantum/Decompressor.cs index 4d5736fd..c4814afe 100644 --- a/BurnOutSharp.Compression/Quantum/Decompressor.cs +++ b/BurnOutSharp.Compression/Quantum/Decompressor.cs @@ -41,33 +41,33 @@ namespace BurnOutSharp.Compression.Quantum while (togo > 0) { - selector = (byte)GET_SYMBOL(state.Model7, ref H, ref L, ref C, inbuf, ref inpos, ref bitsleft, ref bitbuf); + selector = (byte)GET_SYMBOL(state.SelectorModel, ref H, ref L, ref C, inbuf, ref inpos, ref bitsleft, ref bitbuf); switch (selector) { // Selector 0 = literal model, 64 entries, 0x00-0x3F case 0: - sym = (byte)GET_SYMBOL(state.Model7Submodel00, ref H, ref L, ref C, inbuf, ref inpos, ref bitsleft, ref bitbuf); + sym = (byte)GET_SYMBOL(state.Model0, ref H, ref L, ref C, inbuf, ref inpos, ref bitsleft, ref bitbuf); state.Window[window + windowPosition++] = sym; togo--; break; // Selector 1 = literal model, 64 entries, 0x40-0x7F case 1: - sym = (byte)GET_SYMBOL(state.Model7Submodel40, ref H, ref L, ref C, inbuf, ref inpos, ref bitsleft, ref bitbuf); + sym = (byte)GET_SYMBOL(state.Model1, ref H, ref L, ref C, inbuf, ref inpos, ref bitsleft, ref bitbuf); state.Window[window + windowPosition++] = sym; togo--; break; // Selector 2 = literal model, 64 entries, 0x80-0xBF case 2: - sym = (byte)GET_SYMBOL(state.Model7Submodel80, ref H, ref L, ref C, inbuf, ref inpos, ref bitsleft, ref bitbuf); + sym = (byte)GET_SYMBOL(state.Model2, ref H, ref L, ref C, inbuf, ref inpos, ref bitsleft, ref bitbuf); state.Window[window + windowPosition++] = sym; togo--; break; // Selector 3 = literal model, 64 entries, 0xC0-0xFF case 3: - sym = (byte)GET_SYMBOL(state.Model7SubmodelC0, ref H, ref L, ref C, inbuf, ref inpos, ref bitsleft, ref bitbuf); + sym = (byte)GET_SYMBOL(state.Model3, ref H, ref L, ref C, inbuf, ref inpos, ref bitsleft, ref bitbuf); state.Window[window + windowPosition++] = sym; togo--; break; @@ -75,28 +75,28 @@ namespace BurnOutSharp.Compression.Quantum // Selector 4 = fixed length of 3 case 4: sym = (byte)GET_SYMBOL(state.Model4, ref H, ref L, ref C, inbuf, ref inpos, ref bitsleft, ref bitbuf); - extra = (int)Q_READ_BITS(state.q_extra_bits[sym], inbuf, ref inpos, ref bitsleft, ref bitbuf); - matchOffset = (uint)(state.q_position_base[sym] + extra + 1); + extra = (int)Q_READ_BITS(state.ExtraBits[sym], inbuf, ref inpos, ref bitsleft, ref bitbuf); + matchOffset = (uint)(state.PositionSlotBases[sym] + extra + 1); matchLength = 3; break; // Selector 5 = fixed length of 4 case 5: sym = (byte)GET_SYMBOL(state.Model5, ref H, ref L, ref C, inbuf, ref inpos, ref bitsleft, ref bitbuf); - extra = (int)Q_READ_BITS(state.q_extra_bits[sym], inbuf, ref inpos, ref bitsleft, ref bitbuf); - matchOffset = (uint)(state.q_position_base[sym] + extra + 1); + extra = (int)Q_READ_BITS(state.ExtraBits[sym], inbuf, ref inpos, ref bitsleft, ref bitbuf); + matchOffset = (uint)(state.PositionSlotBases[sym] + extra + 1); matchLength = 4; break; // Selector 6 = variable length case 6: sym = (byte)GET_SYMBOL(state.Model6Length, ref H, ref L, ref C, inbuf, ref inpos, ref bitsleft, ref bitbuf); - extra = (int)Q_READ_BITS(state.q_length_extra[sym], inbuf, ref inpos, ref bitsleft, ref bitbuf); - matchLength = state.q_length_base[sym] + extra + 5; + extra = (int)Q_READ_BITS(state.LengthExtraBits[sym], inbuf, ref inpos, ref bitsleft, ref bitbuf); + matchLength = state.LengthBases[sym] + extra + 5; sym = (byte)GET_SYMBOL(state.Model6Position, ref H, ref L, ref C, inbuf, ref inpos, ref bitsleft, ref bitbuf); - extra = (int)Q_READ_BITS(state.q_extra_bits[sym], inbuf, ref inpos, ref bitsleft, ref bitbuf); - matchOffset = (uint)(state.q_position_base[sym] + extra + 1); + extra = (int)Q_READ_BITS(state.ExtraBits[sym], inbuf, ref inpos, ref bitsleft, ref bitbuf); + matchOffset = (uint)(state.PositionSlotBases[sym] + extra + 1); break; default: @@ -189,28 +189,13 @@ namespace BurnOutSharp.Compression.Quantum state.WindowSize = windowSize; state.WindowPosition = 0; - // Initialize static slot/extrabits tables - for (i = 0, j = 0; i < 27; i++) - { - state.q_length_extra[i] = (byte)((i == 26) ? 0 : (i < 2 ? 0 : i - 2) >> 2); - state.q_length_base[i] = (byte)j; - j += (uint)(1 << ((i == 26) ? 5 : state.q_length_extra[i])); - } - - for (i = 0, j = 0; i < 42; i++) - { - state.q_extra_bits[i] = (byte)((i < 2 ? 0 : i - 2) >> 1); - state.q_position_base[i] = j; - j += (uint)(1 << state.q_extra_bits[i]); - } - // Initialize arithmetic coding models - state.Model7 = CreateModel(state.Model7Symbols, 7, 0); + state.SelectorModel = CreateModel(state.SelectorModelSymbols, 7, 0); - state.Model7Submodel00 = CreateModel(state.Model7Submodel00Symbols, 0x40, 0x00); - state.Model7Submodel40 = CreateModel(state.Model7Submodel40Symbols, 0x40, 0x40); - state.Model7Submodel80 = CreateModel(state.Model7Submodel80Symbols, 0x40, 0x80); - state.Model7SubmodelC0 = CreateModel(state.Model7SubmodelC0Symbols, 0x40, 0xC0); + state.Model0 = CreateModel(state.Model0Symbols, 0x40, 0x00); + state.Model1 = CreateModel(state.Model1Symbols, 0x40, 0x40); + state.Model2 = CreateModel(state.Model2Symbols, 0x40, 0x80); + state.Model3 = CreateModel(state.Model3Symbols, 0x40, 0xC0); // Model 4 depends on table size, ranges from 20 to 24 state.Model4 = CreateModel(state.Model4Symbols, (msz < 24) ? msz : 24, 0); diff --git a/BurnOutSharp.Compression/Quantum/State.cs b/BurnOutSharp.Compression/Quantum/State.cs index 4aee4912..d7f1a6ff 100644 --- a/BurnOutSharp.Compression/Quantum/State.cs +++ b/BurnOutSharp.Compression/Quantum/State.cs @@ -2,6 +2,7 @@ using BurnOutSharp.Models.Compression.Quantum; namespace BurnOutSharp.Compression.Quantum { + /// /// public class State { @@ -28,122 +29,139 @@ namespace BurnOutSharp.Compression.Quantum #region Models /// - /// Model for Model 4 + /// Symbol table for selector model + /// + public ModelSymbol[] SelectorModelSymbols = new ModelSymbol[7 + 1]; + + /// + /// Model for selector values + /// + public Model SelectorModel; + + /// + /// Model for Selector 0 + /// + public Model Model0; + + /// + /// Model for Selector 1 + /// + public Model Model1; + + /// + /// Model for Selector 2 + /// + public Model Model2; + + /// + /// Model for Selector 3 + /// + public Model Model3; + + /// + /// Model for Selector 4 /// public Model Model4; /// - /// Model for Model 5 + /// Model for Selector 5 /// public Model Model5; /// - /// Model for Model 6 Position + /// Model for Selector 6 Position /// public Model Model6Position; /// - /// Model for Model 6 Length + /// Model for Selector 6 Length /// public Model Model6Length; - /// - /// Model for Model 7 - /// - public Model Model7; - - /// - /// Model for Model 7, Submodel 00 - /// - public Model Model7Submodel00; - - /// - /// Model for Model 7, Submodel 40 - /// - public Model Model7Submodel40; - - /// - /// Model for Model 7, Submodel 80 - /// - public Model Model7Submodel80; - - /// - /// Model for Model 7, Submodel C0 - /// - public Model Model7SubmodelC0; - #endregion #region Symbol Tables /// - /// Symbol table for Model 4 + /// Symbol table for Selector 0 + /// + public ModelSymbol[] Model0Symbols = new ModelSymbol[0x40 + 1]; + + /// + /// Symbol table for Selector 1 + /// + public ModelSymbol[] Model1Symbols = new ModelSymbol[0x40 + 1]; + + /// + /// Symbol table for Selector 2 + /// + public ModelSymbol[] Model2Symbols = new ModelSymbol[0x40 + 1]; + + /// + /// Symbol table for Selector 3 + /// + public ModelSymbol[] Model3Symbols = new ModelSymbol[0x40 + 1]; + + /// + /// Symbol table for Selector 4 /// public ModelSymbol[] Model4Symbols = new ModelSymbol[0x18 + 1]; /// - /// Symbol table for Model 5 + /// Symbol table for Selector 5 /// public ModelSymbol[] Model5Symbols = new ModelSymbol[0x24 + 1]; /// - /// Symbol table for Model 6 Position + /// Symbol table for Selector 6 Position /// public ModelSymbol[] Model6PositionSymbols = new ModelSymbol[0x2a + 1]; /// - /// Symbol table for Model 6 Length + /// Symbol table for Selector 6 Length /// public ModelSymbol[] Model6LengthSymbols = new ModelSymbol[0x1b + 1]; - /// - /// Symbol table for Model 7 - /// - public ModelSymbol[] Model7Symbols = new ModelSymbol[7 + 1]; - - /// - /// Symbol table for Model 7, Submodel 00 - /// - public ModelSymbol[] Model7Submodel00Symbols = new ModelSymbol[0x40 + 1]; - - /// - /// Symbol table for Model 7, Submodel 40 - /// - public ModelSymbol[] Model7Submodel40Symbols = new ModelSymbol[0x40 + 1]; - - /// - /// Symbol table for Model 7, Submodel 80 - /// - public ModelSymbol[] Model7Submodel80Symbols = new ModelSymbol[0x40 + 1]; - - /// - /// Symbol table for Model 7, Submodel C0 - /// - public ModelSymbol[] Model7SubmodelC0Symbols = new ModelSymbol[0x40 + 1]; - #endregion #region Decompression Tables /// - /// XXXXX + /// An index to the position slot bases /// - public byte[] q_length_base = new byte[27]; + public uint[] PositionSlotBases = new uint[42] + { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152, + 65536, 98304, 131072, 196608, 262144, 393216, 524288, 786432, 1048576, 1572864 + }; /// - /// XXXXX + /// How many bits of offset-from-base data is needed /// - public byte[] q_length_extra = new byte[27]; + public byte[] ExtraBits = new byte[42] + { + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, + 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19 + }; /// - /// XXXXX + /// An index to the position slot bases [Selector 6] /// - public byte[] q_extra_bits = new byte[42]; + public byte[] LengthBases = new byte[27] + { + 0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 14, 18, 22, 26, + 30, 38, 46, 54, 62, 78, 94, 110, 126, 158, 190, 222, 254 + }; /// - /// XXXXX + /// How many bits of offset-from-base data is needed [Selector 6] /// - public uint[] q_position_base = new uint[42]; + public byte[] LengthExtraBits = new byte[27] + { + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 + }; #endregion }