mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-24 20:04:13 +08:00
(StreamRange): new wrapper around IO.Stream.
(LzssReader): allow compressed format customization.
This commit is contained in:
parent
fc27ece34d
commit
29bd97fca9
@ -187,26 +187,134 @@ namespace GameRes.Formats
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a region within existing stream.
|
||||||
|
/// Underlying stream should allow seeking (CanSeek == true).
|
||||||
|
/// </summary>
|
||||||
|
public class StreamRegion : Stream
|
||||||
|
{
|
||||||
|
private Stream m_stream;
|
||||||
|
private long m_begin;
|
||||||
|
private long m_end;
|
||||||
|
|
||||||
|
public StreamRegion (Stream main, long offset, long length)
|
||||||
|
{
|
||||||
|
m_stream = main;
|
||||||
|
m_begin = offset;
|
||||||
|
m_end = Math.Min (offset + length, m_stream.Length);
|
||||||
|
m_stream.Position = m_begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamRegion (Stream main, long offset) : this (main, offset, main.Length-offset)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanRead { get { return m_stream.CanRead; } }
|
||||||
|
public override bool CanSeek { get { return true; } }
|
||||||
|
public override bool CanWrite { get { return false; } }
|
||||||
|
public override long Length { get { return m_end - m_begin; } }
|
||||||
|
public override long Position
|
||||||
|
{
|
||||||
|
get { return m_stream.Position - m_begin; }
|
||||||
|
set { m_stream.Position = Math.Max (m_begin + value, m_begin); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Flush()
|
||||||
|
{
|
||||||
|
m_stream.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Seek (long offset, SeekOrigin origin)
|
||||||
|
{
|
||||||
|
if (SeekOrigin.Begin == origin)
|
||||||
|
offset += m_begin;
|
||||||
|
else if (SeekOrigin.Current == origin)
|
||||||
|
offset += m_stream.Position;
|
||||||
|
else
|
||||||
|
offset += m_end;
|
||||||
|
offset = Math.Max (offset, m_begin);
|
||||||
|
m_stream.Position = offset;
|
||||||
|
return offset - m_begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Read (byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
int read = 0;
|
||||||
|
long available = m_end - m_stream.Position;
|
||||||
|
if (available > 0)
|
||||||
|
{
|
||||||
|
read = m_stream.Read (buffer, offset, (int)Math.Min (count, available));
|
||||||
|
}
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int ReadByte ()
|
||||||
|
{
|
||||||
|
if (m_stream.Position < m_end)
|
||||||
|
return m_stream.ReadByte();
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetLength (long length)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException ("StreamRegion.SetLength method is not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write (byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException ("StreamRegion.Write method is not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteByte (byte value)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException ("StreamRegion.WriteByte method is not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool m_disposed = false;
|
||||||
|
protected override void Dispose (bool disposing)
|
||||||
|
{
|
||||||
|
if (!m_disposed)
|
||||||
|
{
|
||||||
|
m_stream.Dispose();
|
||||||
|
m_disposed = true;
|
||||||
|
base.Dispose (disposing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class LzssReader : IDisposable
|
public class LzssReader : IDisposable
|
||||||
{
|
{
|
||||||
BinaryReader m_input;
|
BinaryReader m_input;
|
||||||
byte[] m_output;
|
byte[] m_output;
|
||||||
int m_size;
|
int m_size;
|
||||||
|
|
||||||
public byte[] Data { get { return m_output; } }
|
public BinaryReader Input { get { return m_input; } }
|
||||||
|
public byte[] Data { get { return m_output; } }
|
||||||
|
public int FrameSize { get; set; }
|
||||||
|
public byte FrameFill { get; set; }
|
||||||
|
public int FrameInitPos { get; set; }
|
||||||
|
|
||||||
public LzssReader (Stream input, int input_length, int output_length)
|
public LzssReader (Stream input, int input_length, int output_length)
|
||||||
{
|
{
|
||||||
m_input = new BinaryReader (input, Encoding.ASCII, true);
|
m_input = new BinaryReader (input, Encoding.ASCII, true);
|
||||||
m_output = new byte[output_length];
|
m_output = new byte[output_length];
|
||||||
m_size = input_length;
|
m_size = input_length;
|
||||||
|
|
||||||
|
FrameSize = 0x1000;
|
||||||
|
FrameFill = 0;
|
||||||
|
FrameInitPos = 0xfee;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Unpack ()
|
public void Unpack ()
|
||||||
{
|
{
|
||||||
int dst = 0;
|
int dst = 0;
|
||||||
var frame = new byte[0x1000];
|
var frame = new byte[FrameSize];
|
||||||
int frame_pos = 0xfee;
|
if (FrameFill != 0)
|
||||||
|
for (int i = 0; i < frame.Length; ++i)
|
||||||
|
frame[i] = FrameFill;
|
||||||
|
int frame_pos = FrameInitPos;
|
||||||
|
int frame_mask = FrameSize-1;
|
||||||
int remaining = (int)m_size;
|
int remaining = (int)m_size;
|
||||||
while (remaining > 0)
|
while (remaining > 0)
|
||||||
{
|
{
|
||||||
@ -221,7 +329,7 @@ namespace GameRes.Formats
|
|||||||
byte b = m_input.ReadByte();
|
byte b = m_input.ReadByte();
|
||||||
--remaining;
|
--remaining;
|
||||||
frame[frame_pos++] = b;
|
frame[frame_pos++] = b;
|
||||||
frame_pos &= 0xfff;
|
frame_pos &= frame_mask;
|
||||||
m_output[dst++] = b;
|
m_output[dst++] = b;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -237,9 +345,9 @@ namespace GameRes.Formats
|
|||||||
if (dst >= m_output.Length)
|
if (dst >= m_output.Length)
|
||||||
break;
|
break;
|
||||||
byte v = frame[offset++];
|
byte v = frame[offset++];
|
||||||
offset &= 0xfff;
|
offset &= frame_mask;
|
||||||
frame[frame_pos++] = v;
|
frame[frame_pos++] = v;
|
||||||
frame_pos &= 0xfff;
|
frame_pos &= frame_mask;
|
||||||
m_output[dst++] = v;
|
m_output[dst++] = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user