mirror of
https://github.com/crskycode/GARbro.git
synced 2025-01-12 12:59:28 +08:00
implemented PT1 images version 3.
This commit is contained in:
parent
58718944ab
commit
5cfa6243c8
@ -51,7 +51,7 @@ namespace GameRes.Formats.Ffa
|
|||||||
|
|
||||||
public Pt1Format ()
|
public Pt1Format ()
|
||||||
{
|
{
|
||||||
Signatures = new uint[] { 2, 1, 0 };
|
Signatures = new uint[] { 3, 2, 1, 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Write (Stream file, ImageData image)
|
public override void Write (Stream file, ImageData image)
|
||||||
@ -64,7 +64,7 @@ namespace GameRes.Formats.Ffa
|
|||||||
using (var input = new ArcView.Reader (stream))
|
using (var input = new ArcView.Reader (stream))
|
||||||
{
|
{
|
||||||
int type = input.ReadInt32();
|
int type = input.ReadInt32();
|
||||||
if (type < 0 || type > 2)
|
if (type < 0 || type > 3)
|
||||||
return null;
|
return null;
|
||||||
if (-1 != input.ReadInt32())
|
if (-1 != input.ReadInt32())
|
||||||
return null;
|
return null;
|
||||||
@ -81,7 +81,7 @@ namespace GameRes.Formats.Ffa
|
|||||||
Height = height,
|
Height = height,
|
||||||
OffsetX = x,
|
OffsetX = x,
|
||||||
OffsetY = y,
|
OffsetY = y,
|
||||||
BPP = 24,
|
BPP = 3 == type ? 32 : 24,
|
||||||
Type = type,
|
Type = type,
|
||||||
PackedSize = comp_size,
|
PackedSize = comp_size,
|
||||||
UnpackedSize = uncomp_size
|
UnpackedSize = uncomp_size
|
||||||
@ -91,51 +91,84 @@ namespace GameRes.Formats.Ffa
|
|||||||
|
|
||||||
public override ImageData Read (Stream stream, ImageMetaData info)
|
public override ImageData Read (Stream stream, ImageMetaData info)
|
||||||
{
|
{
|
||||||
var meta = info as Pt1MetaData;
|
var meta = (Pt1MetaData)info;
|
||||||
if (null == meta)
|
|
||||||
throw new ArgumentException ("Pt1Format.Read should be supplied with Pt1MetaData", "info");
|
|
||||||
|
|
||||||
stream.Position = 0x20;
|
|
||||||
var reader = new Reader (stream, meta);
|
var reader = new Reader (stream, meta);
|
||||||
reader.Unpack();
|
reader.Unpack();
|
||||||
return ImageData.Create (meta, PixelFormats.Bgr24, null, reader.Data);
|
return ImageData.Create (meta, reader.Format, null, reader.Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class Reader
|
internal class Reader
|
||||||
{
|
{
|
||||||
byte[] m_input;
|
byte[] m_input;
|
||||||
byte[] m_output;
|
byte[] m_output;
|
||||||
|
byte[] m_alpha_packed;
|
||||||
int m_type;
|
int m_type;
|
||||||
int m_width;
|
int m_width;
|
||||||
int m_height;
|
int m_height;
|
||||||
int m_stride;
|
int m_stride;
|
||||||
int m_left = 0;
|
|
||||||
|
|
||||||
|
public PixelFormat Format { get; private set; }
|
||||||
public byte[] Data { get { return m_output; } }
|
public byte[] Data { get { return m_output; } }
|
||||||
|
|
||||||
public Reader (Stream input, Pt1MetaData info)
|
public Reader (Stream input, Pt1MetaData info)
|
||||||
{
|
{
|
||||||
m_type = info.Type;
|
m_type = info.Type;
|
||||||
m_input = new byte[info.PackedSize+8];
|
m_input = new byte[info.PackedSize+8];
|
||||||
|
input.Position = 0x20;
|
||||||
if ((int)info.PackedSize != input.Read (m_input, 0, (int)info.PackedSize))
|
if ((int)info.PackedSize != input.Read (m_input, 0, (int)info.PackedSize))
|
||||||
throw new InvalidFormatException ("Unexpected end of file");
|
throw new InvalidFormatException ("Unexpected end of file");
|
||||||
m_width = (int)info.Width;
|
m_width = (int)info.Width;
|
||||||
m_height = (int)info.Height;
|
m_height = (int)info.Height;
|
||||||
m_output = new byte[info.UnpackedSize];
|
m_output = new byte[info.UnpackedSize];
|
||||||
m_stride = m_width*3;
|
m_stride = m_width*3;
|
||||||
|
if (3 == m_type)
|
||||||
|
{
|
||||||
|
Format = PixelFormats.Bgra32;
|
||||||
|
using (var reader = new ArcView.Reader (input))
|
||||||
|
{
|
||||||
|
int packed_size = reader.ReadInt32();
|
||||||
|
m_alpha_packed = new byte[packed_size];
|
||||||
|
if (packed_size != input.Read (m_alpha_packed, 0, packed_size))
|
||||||
|
throw new EndOfStreamException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Format = PixelFormats.Bgr24;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] Unpack ()
|
public byte[] Unpack ()
|
||||||
{
|
{
|
||||||
switch (m_type)
|
switch (m_type)
|
||||||
{
|
{
|
||||||
|
case 3: UnpackV3(); break;
|
||||||
case 2: UnpackV2(); break;
|
case 2: UnpackV2(); break;
|
||||||
case 1: UnpackV1(); break;
|
case 1: UnpackV1(); break;
|
||||||
case 0: UnpackV0(); break;
|
case 0: UnpackV0 (m_input, m_output); break;
|
||||||
}
|
}
|
||||||
return m_output;
|
return m_output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UnpackV3 ()
|
||||||
|
{
|
||||||
|
UnpackV2();
|
||||||
|
int total = m_width * m_height;
|
||||||
|
var alpha = new byte[total];
|
||||||
|
UnpackV0 (m_alpha_packed, alpha);
|
||||||
|
var pixels = new byte[total * 4];
|
||||||
|
int src = 0;
|
||||||
|
int dst = 0;
|
||||||
|
for (int i = 0; i < total; ++i)
|
||||||
|
{
|
||||||
|
pixels[dst++] = m_output[src++];
|
||||||
|
pixels[dst++] = m_output[src++];
|
||||||
|
pixels[dst++] = m_output[src++];
|
||||||
|
pixels[dst++] = alpha[i];
|
||||||
|
}
|
||||||
|
m_output = pixels;
|
||||||
|
}
|
||||||
|
|
||||||
uint edx;
|
uint edx;
|
||||||
byte ch;
|
byte ch;
|
||||||
int src;
|
int src;
|
||||||
@ -213,7 +246,6 @@ namespace GameRes.Formats.Ffa
|
|||||||
}
|
}
|
||||||
for (int i = 1; i < m_height; ++i)
|
for (int i = 1; i < m_height; ++i)
|
||||||
{
|
{
|
||||||
dst += m_left; // XXX add edi, [ebp+arg_8]
|
|
||||||
ReadNext();
|
ReadNext();
|
||||||
_CF = edx & 1;
|
_CF = edx & 1;
|
||||||
edx >>= 1;
|
edx >>= 1;
|
||||||
@ -349,37 +381,20 @@ namespace GameRes.Formats.Ffa
|
|||||||
Buffer.BlockCopy (m_output, dst - m_stride, m_output, dst, 3);
|
Buffer.BlockCopy (m_output, dst - m_stride, m_output, dst, 3);
|
||||||
dst += 3;
|
dst += 3;
|
||||||
}
|
}
|
||||||
else if (4 == ebx)
|
|
||||||
{
|
|
||||||
ah = sub_4225EA();
|
|
||||||
al = (byte)(ah + m_output[dst - m_stride - 3]);
|
|
||||||
m_output[dst++] = al;
|
|
||||||
|
|
||||||
ReadNext();
|
|
||||||
ah = sub_4225EA();
|
|
||||||
al = (byte)(ah + m_output[dst - m_stride - 3]);
|
|
||||||
m_output[dst++] = al;
|
|
||||||
|
|
||||||
ReadNext();
|
|
||||||
ah = sub_4225EA();
|
|
||||||
al = (byte)(ah + m_output[dst - m_stride - 3]);
|
|
||||||
m_output[dst++] = al;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
int off = dst - m_stride;
|
||||||
|
if (4 == ebx) off -= 3;
|
||||||
ah = sub_4225EA();
|
ah = sub_4225EA();
|
||||||
al = (byte)(ah + m_output[dst - m_stride]);
|
m_output[dst++] = (byte)(ah + m_output[off++]);
|
||||||
m_output[dst++] = al;
|
|
||||||
|
|
||||||
ReadNext();
|
ReadNext();
|
||||||
ah = sub_4225EA();
|
ah = sub_4225EA();
|
||||||
al = (byte)(ah + m_output[dst - m_stride]);
|
m_output[dst++] = (byte)(ah + m_output[off++]);
|
||||||
m_output[dst++] = al;
|
|
||||||
|
|
||||||
ReadNext();
|
ReadNext();
|
||||||
ah = sub_4225EA();
|
ah = sub_4225EA();
|
||||||
al = (byte)(ah + m_output[dst - m_stride]);
|
m_output[dst++] = (byte)(ah + m_output[off++]);
|
||||||
m_output[dst++] = al;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -571,29 +586,29 @@ namespace GameRes.Formats.Ffa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnpackV0 ()
|
void UnpackV0 (byte[] input, byte[] output)
|
||||||
{
|
{
|
||||||
int src = 0;
|
int src = 0;
|
||||||
int dst = 0;
|
int dst = 0;
|
||||||
byte[] frame = new byte[0x1000]; // word_461A28
|
byte[] frame = new byte[0x1000]; // word_461A28
|
||||||
PopulateLzssFrame (frame);
|
PopulateLzssFrame (frame);
|
||||||
int ebp = 0xfee;
|
int ebp = 0xfee;
|
||||||
while (src < m_input.Length)
|
while (src < input.Length)
|
||||||
{
|
{
|
||||||
byte ah = m_input[src++];
|
byte ah = input[src++];
|
||||||
for (int mask = 1; mask != 0x100; mask <<= 1)
|
for (int mask = 1; mask != 0x100; mask <<= 1)
|
||||||
{
|
{
|
||||||
if (0 != (ah & mask))
|
if (0 != (ah & mask))
|
||||||
{
|
{
|
||||||
byte al = m_input[src++];
|
byte al = input[src++];
|
||||||
frame[ebp++] = al;
|
frame[ebp++] = al;
|
||||||
ebp &= 0xfff;
|
ebp &= 0xfff;
|
||||||
m_output[dst++] = al;
|
output[dst++] = al;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int offset = m_input[src++];
|
int offset = input[src++];
|
||||||
int count = m_input[src++];
|
int count = input[src++];
|
||||||
offset |= (count & 0xf0) << 4;
|
offset |= (count & 0xf0) << 4;
|
||||||
count = (count & 0x0f) + 3;
|
count = (count & 0x0f) + 3;
|
||||||
for (int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
@ -602,10 +617,10 @@ namespace GameRes.Formats.Ffa
|
|||||||
frame[ebp++] = al;
|
frame[ebp++] = al;
|
||||||
offset &= 0xfff;
|
offset &= 0xfff;
|
||||||
ebp &= 0xfff;
|
ebp &= 0xfff;
|
||||||
m_output[dst++] = al;
|
output[dst++] = al;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dst >= m_output.Length)
|
if (dst >= output.Length)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user