(GR2): alternative '*Pola*' images.

This commit is contained in:
morkt
2017-12-31 09:01:57 +04:00
parent cb54e20e56
commit 5ecb488929

View File

@@ -52,7 +52,7 @@ namespace GameRes.Formats.AdvSys
public override ImageData Read (IBinaryStream stream, ImageMetaData info) public override ImageData Read (IBinaryStream stream, ImageMetaData info)
{ {
stream.Position = 0x10; stream.Position = 0x10;
int stride = ((int)info.Width * info.BPP/8 + 3) & ~3; int stride = GetStride (info);
var pixels = new byte[stride * info.Height]; var pixels = new byte[stride * info.Height];
if (pixels.Length != stream.Read (pixels, 0, pixels.Length)) if (pixels.Length != stream.Read (pixels, 0, pixels.Length))
throw new InvalidFormatException ("Unexpected end of file"); throw new InvalidFormatException ("Unexpected end of file");
@@ -67,6 +67,11 @@ namespace GameRes.Formats.AdvSys
return ImageData.Create (info, format, null, pixels, stride); return ImageData.Create (info, format, null, pixels, stride);
} }
internal int GetStride (ImageMetaData info)
{
return ((int)info.Width * info.BPP/8 + 3) & ~3;
}
public override void Write (Stream file, ImageData image) public override void Write (Stream file, ImageData image)
{ {
throw new System.NotImplementedException ("Gr2Format.Write not implemented"); throw new System.NotImplementedException ("Gr2Format.Write not implemented");
@@ -75,7 +80,8 @@ namespace GameRes.Formats.AdvSys
internal class PolaMetaData : ImageMetaData internal class PolaMetaData : ImageMetaData
{ {
public int UnpackedSize; public uint DataOffset;
public int UnpackedSize;
} }
[Export(typeof(ImageFormat))] [Export(typeof(ImageFormat))]
@@ -93,38 +99,40 @@ namespace GameRes.Formats.AdvSys
public override ImageMetaData ReadMetaData (IBinaryStream stream) public override ImageMetaData ReadMetaData (IBinaryStream stream)
{ {
var header = stream.ReadHeader (20); var header = stream.ReadHeader (20);
if (!header.AsciiEqual ("*Pola* ")) if (!header.AsciiEqual ("*Pola"))
return null; return null;
bool new_version = header.AsciiEqual (5, "* ");
uint data_offset = new_version ? 20u : 13u;
int unpacked_size = header.ToInt32 (8); int unpacked_size = header.ToInt32 (8);
using (var reader = new PolaReader (stream, 64)) stream.Position = data_offset;
var reader = new PolaReader (stream, 64);
reader.Unpack();
using (var temp = BinaryStream.FromArray (reader.Data, stream.Name))
{ {
reader.Unpack(); var info = base.ReadMetaData (temp);
using (var temp = BinaryStream.FromArray (reader.Data, stream.Name)) if (null == info)
return null;
if (!new_version)
unpacked_size = 0x10 + GetStride (info) * (int)info.Height;
return new PolaMetaData
{ {
var info = base.ReadMetaData (temp); Width = info.Width,
if (null == info) Height = info.Height,
return null; BPP = info.BPP,
return new PolaMetaData DataOffset = data_offset,
{ UnpackedSize = unpacked_size,
Width = info.Width, };
Height = info.Height,
BPP = info.BPP,
UnpackedSize = unpacked_size,
};
}
} }
} }
public override ImageData Read (IBinaryStream stream, ImageMetaData info) public override ImageData Read (IBinaryStream stream, ImageMetaData info)
{ {
var meta = (PolaMetaData)info; var meta = (PolaMetaData)info;
stream.Position = 0x14; stream.Position = meta.DataOffset;
using (var reader = new PolaReader (stream, meta.UnpackedSize)) var reader = new PolaReader (stream, meta.UnpackedSize);
{ reader.Unpack();
reader.Unpack(); using (var temp = BinaryStream.FromArray (reader.Data, stream.Name))
using (var temp = BinaryStream.FromArray (reader.Data, stream.Name)) return base.Read (temp, info);
return base.Read (temp, info);
}
} }
public override void Write (Stream file, ImageData image) public override void Write (Stream file, ImageData image)
@@ -133,7 +141,7 @@ namespace GameRes.Formats.AdvSys
} }
} }
internal sealed class PolaReader : IDisposable internal sealed class PolaReader
{ {
IBinaryStream m_input; IBinaryStream m_input;
byte[] m_output; byte[] m_output;
@@ -259,24 +267,17 @@ namespace GameRes.Formats.AdvSys
} }
} }
int m_flag = 2; int m_bits = 2;
int NextBit () int NextBit ()
{ {
int bit = m_flag & 1; int bit = m_bits & 1;
m_flag >>= 1; m_bits >>= 1;
if (1 == m_flag) if (1 == m_bits)
{ {
m_flag = m_input.ReadUInt16() | 0x10000; m_bits = m_input.ReadUInt16() | 0x10000;
} }
return bit; return bit;
} }
#region IDisposable Members
public void Dispose ()
{
}
#endregion
} }
} }