mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-07-18 23:05:11 +00:00
Finalize Quantum port to C# (pass 1)
This commit is contained in:
@@ -1,20 +1,144 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using BurnOutSharp.Models.Compression.Quantum;
|
||||
using static BurnOutSharp.Models.Compression.Quantum.Constants;
|
||||
|
||||
namespace BurnOutSharp.Compression.Quantum
|
||||
{
|
||||
/// <see href="https://github.com/wine-mirror/wine/blob/master/dlls/cabinet/cabinet.h"/>
|
||||
/// <see href="https://github.com/wine-mirror/wine/blob/master/dlls/cabinet/fdi.c"/>
|
||||
/// <see href="https://github.com/wine-mirror/wine/blob/master/include/fdi.h"/>
|
||||
public class Decompressor
|
||||
{
|
||||
// TODO: Implement Quantum decompression
|
||||
|
||||
/// <summary>
|
||||
/// Decompress a byte array using a given State
|
||||
/// </summary>
|
||||
public static bool Decompress(State state, int inlen, byte[] inbuf, int outlen, byte[] outbuf)
|
||||
{
|
||||
// Port from MicrosoftCabinet.fdi.Quantum.cs
|
||||
return false;
|
||||
int inpos = 0; // inbuf[0]
|
||||
int window = 0; // state.Window[0]
|
||||
int runsrc, rundest;
|
||||
uint window_posn = state.WindowPosition;
|
||||
uint window_size = state.WindowSize;
|
||||
|
||||
int extra, togo = outlen, match_length = 0, copy_length;
|
||||
byte selector, sym;
|
||||
uint match_offset = 0;
|
||||
|
||||
ushort H = 0xFFFF, L = 0;
|
||||
|
||||
// Read initial value of C
|
||||
Q_INIT_BITSTREAM(out int bitsleft, out uint bitbuf);
|
||||
ushort C = Q_READ_BITS_UINT16(16, inbuf, ref inpos, ref bitsleft, ref bitbuf);
|
||||
|
||||
// Apply 2^x-1 mask
|
||||
window_posn &= window_size - 1;
|
||||
|
||||
// Runs can't straddle the window wraparound
|
||||
if ((window_posn + togo) > window_size)
|
||||
return false;
|
||||
|
||||
while (togo > 0)
|
||||
{
|
||||
selector = (byte)GET_SYMBOL(state.Model7, ref H, ref L, ref C, inbuf, ref inpos, ref bitsleft, ref bitbuf);
|
||||
switch (selector)
|
||||
{
|
||||
case 0:
|
||||
sym = (byte)GET_SYMBOL(state.Model7Submodel00, ref H, ref L, ref C, inbuf, ref inpos, ref bitsleft, ref bitbuf);
|
||||
state.Window[window + window_posn++] = sym;
|
||||
togo--;
|
||||
break;
|
||||
case 1:
|
||||
sym = (byte)GET_SYMBOL(state.Model7Submodel40, ref H, ref L, ref C, inbuf, ref inpos, ref bitsleft, ref bitbuf);
|
||||
state.Window[window + window_posn++] = sym;
|
||||
togo--;
|
||||
break;
|
||||
case 2:
|
||||
sym = (byte)GET_SYMBOL(state.Model7Submodel80, ref H, ref L, ref C, inbuf, ref inpos, ref bitsleft, ref bitbuf);
|
||||
state.Window[window + window_posn++] = sym;
|
||||
togo--;
|
||||
break;
|
||||
case 3:
|
||||
sym = (byte)GET_SYMBOL(state.Model7SubmodelC0, ref H, ref L, ref C, inbuf, ref inpos, ref bitsleft, ref bitbuf);
|
||||
state.Window[window + window_posn++] = sym;
|
||||
togo--;
|
||||
break;
|
||||
|
||||
// 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 = Q_READ_BITS_INT32(state.q_extra_bits[sym], inbuf, ref inpos, ref bitsleft, ref bitbuf);
|
||||
match_offset = (uint)(state.q_position_base[sym] + extra + 1);
|
||||
match_length = 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 = Q_READ_BITS_INT32(state.q_extra_bits[sym], inbuf, ref inpos, ref bitsleft, ref bitbuf);
|
||||
match_offset = (uint)(state.q_position_base[sym] + extra + 1);
|
||||
match_length = 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 = Q_READ_BITS_INT32(state.q_length_extra[sym], inbuf, ref inpos, ref bitsleft, ref bitbuf);
|
||||
match_length = state.q_length_base[sym] + extra + 5;
|
||||
sym = (byte)GET_SYMBOL(state.Model6Position, ref H, ref L, ref C, inbuf, ref inpos, ref bitsleft, ref bitbuf);
|
||||
extra = Q_READ_BITS_INT32(state.q_extra_bits[sym], inbuf, ref inpos, ref bitsleft, ref bitbuf);
|
||||
match_offset = (uint)(state.q_position_base[sym] + extra + 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// If this is a match */
|
||||
if (selector >= 4)
|
||||
{
|
||||
rundest = (int)(window + window_posn);
|
||||
togo -= match_length;
|
||||
|
||||
// Copy any wrapped around source data
|
||||
if (window_posn >= match_offset)
|
||||
{
|
||||
// No wrap
|
||||
runsrc = (int)(rundest - match_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
runsrc = (int)(rundest + (window_size - match_offset));
|
||||
copy_length = (int)(match_offset - window_posn);
|
||||
if (copy_length < match_length)
|
||||
{
|
||||
match_length -= copy_length;
|
||||
window_posn += (uint)copy_length;
|
||||
while (copy_length-- > 0)
|
||||
{
|
||||
state.Window[rundest++] = state.Window[rundest++];
|
||||
}
|
||||
|
||||
runsrc = window;
|
||||
}
|
||||
}
|
||||
|
||||
window_posn += (uint)match_length;
|
||||
|
||||
// Copy match data - no worries about destination wraps
|
||||
while (match_length-- > 0)
|
||||
{
|
||||
state.Window[rundest++] = state.Window[runsrc++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (togo != 0)
|
||||
return false;
|
||||
|
||||
Array.Copy(state.Window, (window_posn == 0 ? window_size : window_posn) - outlen, outbuf, 0, outlen);
|
||||
|
||||
state.WindowPosition = window_posn;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -355,7 +479,7 @@ namespace BurnOutSharp.Compression.Quantum
|
||||
/// Fetches the next symbol from the stated model and puts it in v.
|
||||
/// It may need to read the bitstream to do this.
|
||||
/// </summary>
|
||||
private static int GET_SYMBOL(Model model, ref ushort H, ref ushort L, ref ushort C, byte[] inbuf, ref int inpos, ref int bitsleft, ref uint bitbuf)
|
||||
private static ushort GET_SYMBOL(Model model, ref ushort H, ref ushort L, ref ushort C, byte[] inbuf, ref int inpos, ref int bitsleft, ref uint bitbuf)
|
||||
{
|
||||
uint range = (uint)(((H - L) & 0xFFFF) + 1);
|
||||
ushort symf = (ushort)(((((C - L + 1) * model.Symbols[0].CumulativeFrequency) - 1) / range) & 0xFFFF);
|
||||
@@ -367,7 +491,7 @@ namespace BurnOutSharp.Compression.Quantum
|
||||
break;
|
||||
}
|
||||
|
||||
int v = model.Symbols[i - 1].Symbol;
|
||||
ushort v = model.Symbols[i - 1].Symbol;
|
||||
range = (uint)(H - L + 1);
|
||||
H = (ushort)(L + ((model.Symbols[i - 1].CumulativeFrequency * range) / model.Symbols[0].CumulativeFrequency) - 1);
|
||||
L = (ushort)(L + ((model.Symbols[i].CumulativeFrequency * range) / model.Symbols[0].CumulativeFrequency));
|
||||
|
||||
@@ -1,280 +0,0 @@
|
||||
// using BurnOutSharp.Compression.Quantum;
|
||||
// using BurnOutSharp.Models.Compression.Quantum;
|
||||
// using static BurnOutSharp.Wrappers.CabinetConstants;
|
||||
// using static BurnOutSharp.Wrappers.FDIcConstants;
|
||||
// using static BurnOutSharp.Wrappers.FDIConstants;
|
||||
// using cab_LONG = System.Int32;
|
||||
// using cab_off_t = System.UInt32;
|
||||
// using cab_UBYTE = System.Byte;
|
||||
// using cab_ULONG = System.UInt32;
|
||||
// using cab_UWORD = System.UInt16;
|
||||
|
||||
// namespace BurnOutSharp.Wrappers
|
||||
// {
|
||||
// internal unsafe class Quantumfdi
|
||||
// {
|
||||
// /// <summary>
|
||||
// /// QTMfdi_decomp(internal)
|
||||
// /// </summary>
|
||||
// internal static int QTMfdi_decomp(int inlen, int outlen, fdi_decomp_state decomp_state)
|
||||
// {
|
||||
// cab_UBYTE* inpos = decomp_state.inbuf;
|
||||
// cab_UBYTE* window = decomp_state.Window;
|
||||
// cab_UBYTE* runsrc, rundest;
|
||||
// cab_ULONG window_posn = decomp_state.WindowPosition;
|
||||
// cab_ULONG window_size = decomp_state.WindowSize;
|
||||
|
||||
// /* used by bitstream macros */
|
||||
// int bitsleft, bitrun, bitsneed;
|
||||
// cab_ULONG bitbuf;
|
||||
|
||||
// /* used by GET_SYMBOL */
|
||||
// cab_ULONG range;
|
||||
// cab_UWORD symf;
|
||||
// int i;
|
||||
|
||||
// int extra = 0, togo = outlen, match_length = 0, copy_length;
|
||||
// cab_UBYTE selector, sym;
|
||||
// cab_ULONG match_offset = 0;
|
||||
|
||||
// cab_UWORD H = 0xFFFF, L = 0, C;
|
||||
|
||||
// System.Diagnostics.Debug.WriteLine("(inlen == %d, outlen == %d)\n", inlen, outlen);
|
||||
|
||||
// /* read initial value of C */
|
||||
// Q_INIT_BITSTREAM(out bitsleft, out bitbuf);
|
||||
// C = Q_READ_BITS_UINT16(16, ref inpos, ref bitsleft, ref bitbuf);
|
||||
|
||||
// /* apply 2^x-1 mask */
|
||||
// window_posn &= window_size - 1;
|
||||
// /* runs can't straddle the window wraparound */
|
||||
// if ((window_posn + togo) > window_size)
|
||||
// {
|
||||
// System.Diagnostics.Debug.WriteLine("straddled run\n");
|
||||
// return DECR_DATAFORMAT;
|
||||
// }
|
||||
|
||||
// while (togo > 0)
|
||||
// {
|
||||
// selector = GET_SYMBOL(state.Model7, ref H, ref L, ref C, ref inpos, ref bitsleft, ref bitbuf);
|
||||
// switch (selector)
|
||||
// {
|
||||
// case 0:
|
||||
// sym = GET_SYMBOL(state.Model7Submodel00, ref H, ref L, ref C, ref inpos, ref bitsleft, ref bitbuf);
|
||||
// window[window_posn++] = sym;
|
||||
// togo--;
|
||||
// break;
|
||||
// case 1:
|
||||
// sym = GET_SYMBOL(state.Model7Submodel40, ref H, ref L, ref C, ref inpos, ref bitsleft, ref bitbuf);
|
||||
// window[window_posn++] = sym;
|
||||
// togo--;
|
||||
// break;
|
||||
// case 2:
|
||||
// sym = GET_SYMBOL(state.Model7Submodel80, ref H, ref L, ref C, ref inpos, ref bitsleft, ref bitbuf);
|
||||
// window[window_posn++] = sym;
|
||||
// togo--;
|
||||
// break;
|
||||
// case 3:
|
||||
// sym = GET_SYMBOL(state.Model7SubmodelC0, ref H, ref L, ref C, ref inpos, ref bitsleft, ref bitbuf);
|
||||
// window[window_posn++] = sym;
|
||||
// togo--;
|
||||
// break;
|
||||
|
||||
// // Selector 4 = fixed length of 3
|
||||
// case 4:
|
||||
// sym = GET_SYMBOL(state.Model4, ref H, ref L, ref C, ref inpos, ref bitsleft, ref bitbuf);
|
||||
// extra = Q_READ_BITS_INT32(state.q_extra_bits[sym], ref inpos, ref bitsleft, ref bitbuf);
|
||||
// match_offset = decomp_state.q_position_base[sym] + extra + 1;
|
||||
// match_length = 3;
|
||||
// break;
|
||||
|
||||
// // Selector 5 = fixed length of 4
|
||||
// case 5:
|
||||
// sym = GET_SYMBOL(state.Model5, ref H, ref L, ref C, ref inpos, ref bitsleft, ref bitbuf);
|
||||
// extra = Q_READ_BITS_INT32(state.q_extra_bits[sym], ref inpos, ref bitsleft, ref bitbuf);
|
||||
// match_offset = decomp_state.q_position_base[sym] + extra + 1;
|
||||
// match_length = 4;
|
||||
// break;
|
||||
|
||||
// // Selector 6 = variable length
|
||||
// case 6:
|
||||
// sym = GET_SYMBOL(state.Model6Length, ref H, ref L, ref C, ref inpos, ref bitsleft, ref bitbuf);
|
||||
// extra = Q_READ_BITS_INT32(state.q_length_extra[sym], ref inpos, ref bitsleft, ref bitbuf);
|
||||
// match_length = decomp_state.q_length_base[sym] + extra + 5;
|
||||
// sym = GET_SYMBOL(state.Model6Position, ref H, ref L, ref C, ref inpos, ref bitsleft, ref bitbuf);
|
||||
// extra = Q_READ_BITS_INT32(state.q_extra_bits[sym], ref inpos, ref bitsleft, ref bitbuf);
|
||||
// match_offset = decomp_state.q_position_base[sym] + extra + 1;
|
||||
// break;
|
||||
|
||||
// default:
|
||||
// System.Diagnostics.Debug.WriteLine("Selector is bogus\n");
|
||||
// return DECR_ILLEGALDATA;
|
||||
// }
|
||||
|
||||
// /* if this is a match */
|
||||
// if (selector >= 4)
|
||||
// {
|
||||
// rundest = window + window_posn;
|
||||
// togo -= match_length;
|
||||
|
||||
// /* copy any wrapped around source data */
|
||||
// if (window_posn >= match_offset)
|
||||
// {
|
||||
// /* no wrap */
|
||||
// runsrc = rundest - match_offset;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// runsrc = rundest + (window_size - match_offset);
|
||||
// copy_length = match_offset - window_posn;
|
||||
// if (copy_length < match_length)
|
||||
// {
|
||||
// match_length -= copy_length;
|
||||
// window_posn += copy_length;
|
||||
// while (copy_length-- > 0) *rundest++ = *runsrc++;
|
||||
// runsrc = window;
|
||||
// }
|
||||
// }
|
||||
// window_posn += match_length;
|
||||
|
||||
// /* copy match data - no worries about destination wraps */
|
||||
// while (match_length-- > 0) *rundest++ = *runsrc++;
|
||||
// }
|
||||
// } /* while (togo > 0) */
|
||||
|
||||
// if (togo != 0)
|
||||
// {
|
||||
// System.Diagnostics.Debug.WriteLine("Frame overflow, this_run = %d\n", togo);
|
||||
// return DECR_ILLEGALDATA;
|
||||
// }
|
||||
|
||||
// memcpy(decomp_state.outbuf, window + ((!window_posn) ? window_size : window_posn) - outlen, outlen);
|
||||
|
||||
// decomp_state.WindowPosition = window_posn;
|
||||
// return DECR_OK;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Should be used first to set up the system
|
||||
// /// </summary>
|
||||
// private static void Q_INIT_BITSTREAM(out int bitsleft, out uint bitbuf)
|
||||
// {
|
||||
// bitsleft = 0; bitbuf = 0;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Adds more data to the bit buffer, if there is room for another 16 bits.
|
||||
// /// </summary>
|
||||
// private static void Q_FILL_BUFFER(ref byte* inpos, ref int bitsleft, ref uint bitbuf)
|
||||
// {
|
||||
// if (bitsleft <= 16)
|
||||
// {
|
||||
// bitbuf |= (uint)((inpos[0] << 8) | inpos[1]) << (16 - bitsleft);
|
||||
// bitsleft += 16; inpos += 2;
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Extracts (without removing) N bits from the bit buffer
|
||||
// /// </summary>
|
||||
// private static uint Q_PEEK_BITS(int n, uint bitbuf)
|
||||
// {
|
||||
// return bitbuf >> (32 - n);
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Removes N bits from the bit buffer
|
||||
// /// </summary>
|
||||
// private static void Q_REMOVE_BITS(int n, ref int bitsleft, ref uint bitbuf)
|
||||
// {
|
||||
// bitbuf <<= n;
|
||||
// bitsleft -= n;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Takes N bits from the buffer and puts them in v. Unlike LZX, this can loop
|
||||
// /// several times to get the requisite number of bits.
|
||||
// /// </summary>
|
||||
// private static ushort Q_READ_BITS_UINT16(int n, ref byte* inpos, ref int bitsleft, ref uint bitbuf)
|
||||
// {
|
||||
// ushort v = 0; int bitrun;
|
||||
// for (int bitsneed = n; bitsneed != 0; bitsneed -= bitrun)
|
||||
// {
|
||||
// Q_FILL_BUFFER(ref inpos, ref bitsleft, ref bitbuf);
|
||||
|
||||
// bitrun = (bitsneed > bitsleft) ? bitsleft : bitsneed;
|
||||
// v = (ushort)((v << bitrun) | Q_PEEK_BITS(bitrun, bitbuf));
|
||||
|
||||
// Q_REMOVE_BITS(bitrun, ref bitsleft, ref bitbuf);
|
||||
// }
|
||||
|
||||
// return v;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Takes N bits from the buffer and puts them in v. Unlike LZX, this can loop
|
||||
// /// several times to get the requisite number of bits.
|
||||
// /// </summary>
|
||||
// private static int Q_READ_BITS_INT32(int n, ref byte* inpos, ref int bitsleft, ref uint bitbuf)
|
||||
// {
|
||||
// int v = 0; int bitrun;
|
||||
// for (int bitsneed = n; bitsneed != 0; bitsneed -= bitrun)
|
||||
// {
|
||||
// Q_FILL_BUFFER(ref inpos, ref bitsleft, ref bitbuf);
|
||||
|
||||
// bitrun = (bitsneed > bitsleft) ? bitsleft : bitsneed;
|
||||
// v = (int)((v << bitrun) | Q_PEEK_BITS(bitrun, bitbuf));
|
||||
|
||||
// Q_REMOVE_BITS(bitrun, ref bitsleft, ref bitbuf);
|
||||
// }
|
||||
|
||||
// return v;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Fetches the next symbol from the stated model and puts it in v.
|
||||
// /// It may need to read the bitstream to do this.
|
||||
// /// </summary>
|
||||
// private static int GET_SYMBOL(Model model, ref ushort H, ref ushort L, ref ushort C, ref byte* inpos, ref int bitsleft, ref uint bitbuf)
|
||||
// {
|
||||
// uint range = (uint)(((H - L) & 0xFFFF) + 1);
|
||||
// ushort symf = (ushort)(((((C - L + 1) * model.Symbols[0].CumulativeFrequency) - 1) / range) & 0xFFFF);
|
||||
|
||||
// int i;
|
||||
// for (i = 1; i < model.Entries; i++)
|
||||
// {
|
||||
// if (model.Symbols[i].CumulativeFrequency <= symf)
|
||||
// break;
|
||||
// }
|
||||
|
||||
// int v = model.Symbols[i - 1].Symbol;
|
||||
// range = (uint)(H - L + 1);
|
||||
// H = (ushort)(L + ((model.Symbols[i - 1].CumulativeFrequency * range) / model.Symbols[0].CumulativeFrequency) - 1);
|
||||
// L = (ushort)(L + ((model.Symbols[i].CumulativeFrequency * range) / model.Symbols[0].CumulativeFrequency));
|
||||
|
||||
// while (true)
|
||||
// {
|
||||
// if ((L & 0x8000) != (H & 0x8000))
|
||||
// {
|
||||
// if ((L & 0x4000) != 0 && (H & 0x4000) == 0)
|
||||
// {
|
||||
// // Underflow case
|
||||
// C ^= 0x4000; L &= 0x3FFF; H |= 0x4000;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// L <<= 1; H = (ushort)((H << 1) | 1);
|
||||
// Q_FILL_BUFFER(ref inpos, ref bitsleft, ref bitbuf);
|
||||
// C = (ushort)((C << 1) | Q_PEEK_BITS(1, bitbuf));
|
||||
// Q_REMOVE_BITS(1, ref bitsleft, ref bitbuf);
|
||||
// }
|
||||
|
||||
// Decompressor.UpdateModel(model, i);
|
||||
// return v;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
Reference in New Issue
Block a user