(Seraphim): CX images.

This commit is contained in:
morkt 2018-05-07 01:09:03 +04:00
parent ac7303b4b3
commit b09a444aa8

View File

@ -76,7 +76,7 @@ namespace GameRes.Formats.Seraphim
var meta = (SeraphMetaData)info; var meta = (SeraphMetaData)info;
var reader = new SeraphReader (stream.AsStream, meta); var reader = new SeraphReader (stream.AsStream, meta);
reader.UnpackCf(); reader.UnpackCf();
return ImageData.Create (info, PixelFormats.Bgr24, null, reader.Data); return ImageData.Create (info, reader.Format, null, reader.Data);
} }
public override void Write (Stream file, ImageData image) public override void Write (Stream file, ImageData image)
@ -94,7 +94,8 @@ namespace GameRes.Formats.Seraphim
public override ImageMetaData ReadMetaData (IBinaryStream stream) public override ImageMetaData ReadMetaData (IBinaryStream stream)
{ {
var info = base.ReadMetaData (stream); var info = base.ReadMetaData (stream);
info.BPP = 32; if (info != null)
info.BPP = 32;
return info; return info;
} }
@ -158,6 +159,33 @@ namespace GameRes.Formats.Seraphim
} }
} }
[Export(typeof(ImageFormat))]
public class SeraphCxImage : SeraphCfImage
{
public override string Tag { get { return "CX"; } }
public override uint Signature { get { return 0x5843; } } // 'CX'
public override ImageMetaData ReadMetaData (IBinaryStream stream)
{
var info = base.ReadMetaData (stream);
if (info != null)
info.BPP = 32;
return info;
}
public override ImageData Read (IBinaryStream stream, ImageMetaData info)
{
var reader = new SeraphReader (stream.AsStream, (SeraphMetaData)info, 4);
reader.UnpackCx();
return ImageData.Create (info, reader.Format, null, reader.Data);
}
public override void Write (Stream file, ImageData image)
{
throw new NotImplementedException ("SeraphCxImage.Write not implemented");
}
}
internal class SeraphReader internal class SeraphReader
{ {
Stream m_input; Stream m_input;
@ -167,6 +195,7 @@ namespace GameRes.Formats.Seraphim
int m_stride; int m_stride;
int m_colors; int m_colors;
int m_packed_size; int m_packed_size;
int m_pixel_size;
public byte[] Data { get { return m_output; } } public byte[] Data { get { return m_output; } }
public PixelFormat Format { get; private set; } public PixelFormat Format { get; private set; }
@ -184,6 +213,7 @@ namespace GameRes.Formats.Seraphim
m_output = new byte[m_stride * m_height]; m_output = new byte[m_stride * m_height];
m_packed_size = info.PackedSize; m_packed_size = info.PackedSize;
m_colors = info.Colors; m_colors = info.Colors;
m_pixel_size = pixel_size;
if (1 == pixel_size && m_colors > 0) if (1 == pixel_size && m_colors > 0)
Palette = ReadPalette (m_colors); Palette = ReadPalette (m_colors);
} }
@ -236,6 +266,13 @@ namespace GameRes.Formats.Seraphim
Format = PixelFormats.Bgr24; Format = PixelFormats.Bgr24;
} }
public void UnpackCx ()
{
UnpackRgb();
FlipPixels();
Format = PixelFormats.Bgra32;
}
private void UnpackRgb () // sub_404250 private void UnpackRgb () // sub_404250
{ {
int dst = 0; int dst = 0;
@ -253,9 +290,7 @@ namespace GameRes.Formats.Seraphim
if (0 != (ctl & 0x40)) if (0 != (ctl & 0x40))
{ {
count = (ctl & 0x3F) + 2; count = (ctl & 0x3F) + 2;
int v2 = m_input.ReadByte(); FillBytes (dst, (byte)m_input.ReadByte(), count);
for (int i = 0; i < count; ++i)
m_output[dst+i] = (byte)v2;
} }
else else
{ {
@ -266,15 +301,12 @@ namespace GameRes.Formats.Seraphim
} }
else if (0 == (ctl & 0x40)) else if (0 == (ctl & 0x40))
{ {
int v2 = m_input.ReadByte(); count = m_input.ReadByte() | ((ctl & 0xF) << 8);
count = v2 | ((ctl & 0xF) << 8);
switch ((ctl >> 4) & 3) switch ((ctl >> 4) & 3)
{ {
case 0: case 0:
count += 2; count += 2;
v2 = m_input.ReadByte(); FillBytes (dst, (byte)m_input.ReadByte(), count);
for (int i = 0; i < count; ++i)
m_output[dst+i] = (byte)v2;
break; break;
case 1: case 1:
++count; ++count;
@ -292,37 +324,28 @@ namespace GameRes.Formats.Seraphim
} }
else if (0 == (ctl & 0x30)) else if (0 == (ctl & 0x30))
{ {
int v2 = m_input.ReadByte(); count = m_input.ReadByte() + ((ctl & 7) << 8) + 1;
count = v2 + ((ctl & 7) << 8) + 1; int x = m_pixel_size;
if (0 != (ctl & 8)) if (0 != (ctl & 8))
{ x *= 2;
m_input.Read (m_output, dst, 6); m_input.Read (m_output, dst, x);
Binary.CopyOverlapped (m_output, dst, dst+6, count*6); Binary.CopyOverlapped (m_output, dst, dst+x, count*x);
++count; ++count;
count *= 6; count *= x;
}
else
{
m_input.Read (m_output, dst, 3);
Binary.CopyOverlapped (m_output, dst, dst+3, count*3);
++count;
count *= 3;
}
} }
else if (0 == (ctl & 0x20)) else if (0 == (ctl & 0x20))
{ {
int offset = m_input.ReadByte() + ((ctl & 0xF) << 8); int offset = m_input.ReadByte() + ((ctl & 0xF) << 8) + 1;
count = m_input.ReadByte() + 1; count = m_input.ReadByte() + 1;
int src = dst - 3 - 3 * offset; // auto v34 = &unpacked[dst - 3] - 3 * offset; int src = dst - m_pixel_size * offset;
count *= 3; count *= m_pixel_size;
Binary.CopyOverlapped (m_output, src, dst, count); Binary.CopyOverlapped (m_output, src, dst, count);
} }
else else
{ {
int v37 = m_input.ReadByte(); int offset = m_input.ReadByte() + ((ctl & 0xF) << 8) + 1;
int v38 = v37 + ((ctl & 0xF) << 8);
count = m_input.ReadByte() + 1; count = m_input.ReadByte() + 1;
int src = dst - 1 - v38; // auto v40 = &unpacked[dst - 1] - v38; int src = dst - offset;
Binary.CopyOverlapped (m_output, src, dst, count); Binary.CopyOverlapped (m_output, src, dst, count);
} }
if (0 == count) if (0 == count)
@ -350,9 +373,9 @@ namespace GameRes.Formats.Seraphim
if (0 != (next & 0x40)) if (0 != (next & 0x40))
{ {
count = (next & 0x3F) + 2; count = (next & 0x3F) + 2;
int v4 = m_input.ReadByte(); byte v = (byte)m_input.ReadByte();
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
output[dst+i] = (byte)v4; output[dst+i] = v;
} }
else else
{ {
@ -363,16 +386,17 @@ namespace GameRes.Formats.Seraphim
} }
else if (0 == (next & 0x40)) else if (0 == (next & 0x40))
{ {
int v2 = m_input.ReadByte(); count = m_input.ReadByte() | ((next & 0xF) << 8);
count = v2 | ((next & 0xF) << 8);
switch ((next >> 4) & 3) switch ((next >> 4) & 3)
{ {
case 0: case 0:
count += 2; {
v2 = m_input.ReadByte(); count += 2;
for (int i = 0; i < count; ++i) byte v = (byte)m_input.ReadByte();
output[dst+i] = (byte)v2; for (int i = 0; i < count; ++i)
break; output[dst+i] = v;
break;
}
case 1: case 1:
++count; ++count;
Binary.CopyOverlapped (output, dst-m_width, dst, count); Binary.CopyOverlapped (output, dst-m_width, dst, count);
@ -442,5 +466,11 @@ namespace GameRes.Formats.Seraphim
} }
m_output = pixels; m_output = pixels;
} }
void FillBytes (int dst, byte value, int count)
{
for (int i = 0; i < count; ++i)
m_output[dst+i] = value;
}
} }
} }