(LzReader): slightly improved LZSS decompression performance.

This commit is contained in:
morkt 2015-09-13 19:27:00 +04:00
parent 199acb763b
commit 0002d55d7d

View File

@ -186,90 +186,52 @@ namespace GameRes.Formats.Kaguya
internal class LzReader : IDataUnpacker internal class LzReader : IDataUnpacker
{ {
Stream m_input; MsbBitStream m_input;
byte[] m_output; byte[] m_output;
uint m_size;
public byte[] Data { get { return m_output; } } public byte[] Data { get { return m_output; } }
public LzReader (Stream input, uint packed_size, uint unpacked_size) public LzReader (Stream input, uint packed_size, uint unpacked_size)
{ {
m_input = input; m_input = new MsbBitStream (input, true);
m_output = new byte[unpacked_size]; m_output = new byte[unpacked_size];
m_size = packed_size;
m_curbit = 8;
m_curbyte = 0;
} }
int m_curbit;
int m_curbyte;
public void Unpack () public void Unpack ()
{ {
int dst = 0; int dst = 0;
int frame_pos = 1; int frame_pos = 1;
byte[] frame = new byte[4096]; byte[] frame = new byte[4096];
int frame_mask = frame.Length - 1;
while (dst < m_output.Length) while (dst < m_output.Length)
{ {
int i; int bit = m_input.GetNextBit();
if (0 != GetNextBit())
{
int data = 0;
for (i = 0; i < 8; i++)
{
int bit = GetNextBit();
if (-1 == bit) if (-1 == bit)
return; break;
data = (data << 1) | bit; if (0 != bit)
} {
int data = m_input.GetBits (8);
m_output[dst++] = (byte)data; m_output[dst++] = (byte)data;
frame[frame_pos++] = (byte)data; frame[frame_pos++] = (byte)data;
frame_pos &= frame.Length - 1; frame_pos &= frame_mask;
} }
else else
{ {
int count, win_offset = 0; int win_offset = m_input.GetBits (12);
for (i = 0; i < 12; i++) if (-1 == win_offset || 0 == win_offset)
{
int bit = GetNextBit();
if (-1 == bit)
return;
win_offset = (win_offset << 1) | bit;
}
if (0 == win_offset)
break; break;
count = 0; int count = m_input.GetBits(4) + 2;
for (i = 0; i < 4; i++) for (int i = 0; i < count; i++)
{ {
int bit = GetNextBit(); byte data = frame[(win_offset + i) & frame_mask];
if (-1 == bit)
return;
count = (count << 1) | bit;
}
count += 2;
for (i = 0; i < count; i++)
{
byte data = frame[(win_offset + i) & (frame.Length - 1)];
m_output[dst++] = data; m_output[dst++] = data;
frame[frame_pos++] = data; frame[frame_pos++] = data;
frame_pos &= frame.Length - 1; frame_pos &= frame_mask;
} }
} }
} }
} }
int GetNextBit ()
{
if (8 == m_curbit)
{
m_curbyte = m_input.ReadByte();
if (m_curbyte < 0)
return -1;
m_curbit = 0;
}
return (m_curbyte >> (7 - m_curbit++)) & 1;
}
} }
} }