mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-24 03:44:13 +08:00
(LzReader): slightly improved LZSS decompression performance.
This commit is contained in:
parent
199acb763b
commit
0002d55d7d
@ -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())
|
if (-1 == bit)
|
||||||
|
break;
|
||||||
|
if (0 != bit)
|
||||||
{
|
{
|
||||||
int data = 0;
|
int data = m_input.GetBits (8);
|
||||||
for (i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
int bit = GetNextBit();
|
|
||||||
if (-1 == bit)
|
|
||||||
return;
|
|
||||||
data = (data << 1) | bit;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user