(Csystem): implemented incremental images.

This commit is contained in:
morkt 2017-03-26 07:27:52 +04:00
parent 305680a4d3
commit 3cefd9d151
2 changed files with 79 additions and 15 deletions

View File

@ -174,6 +174,8 @@ namespace GameRes.Formats.Cyberworks
Extensions = new string[] { "dat", "04", "05", "06", "app" }; Extensions = new string[] { "dat", "04", "05", "06", "app" };
} }
public bool BlendOverlayImages = true;
static readonly ArchiveNameParser[] s_name_parsers = { static readonly ArchiveNameParser[] s_name_parsers = {
new ArcNameParser(), new DatNameParser(), new InKyouParser() new ArcNameParser(), new DatNameParser(), new InKyouParser()
}; };
@ -256,6 +258,7 @@ namespace GameRes.Formats.Cyberworks
var pent = entry as PackedEntry; var pent = entry as PackedEntry;
if (null != pent && pent.IsPacked) if (null != pent && pent.IsPacked)
{ {
input = new BufferedStream (input);
input = new LzssStream (input); input = new LzssStream (input);
} }
return input; return input;
@ -269,7 +272,10 @@ namespace GameRes.Formats.Cyberworks
var input = arc.OpenBinaryEntry (entry); var input = arc.OpenBinaryEntry (entry);
try try
{ {
return DecryptImage (input, barc.Scheme); var reader = DecryptImage (input, barc.Scheme);
if (BlendOverlayImages && reader is AImageReader)
reader = BlendAImage (barc, entry, reader as AImageReader);
return reader;
} }
catch catch
{ {
@ -301,6 +307,43 @@ namespace GameRes.Formats.Cyberworks
return new ImageFormatDecoder (input); return new ImageFormatDecoder (input);
} }
IImageDecoder BlendAImage (BellArchive arc, Entry entry, AImageReader overlay)
{
var header = overlay.ReadHeader();
if (header[0] != 1)
return overlay;
var scheme = arc.Scheme;
var dir = (List<Entry>)arc.Dir;
int i = dir.IndexOf (entry);
while (--i >= 0 && "image" == dir[i].Type)
{
using (var input = OpenEntry (arc, dir[i]))
{
int type = input.ReadByte();
if (type != 'a')
break;
int id = input.ReadByte();
if (id != scheme.Value2)
break;
using (var bin = new BinaryStream (input, dir[i].Name))
using (var base_image = new AImageReader (bin, scheme))
{
var base_header = base_image.ReadHeader();
if (1 == base_header[0])
continue;
// check if image width/height are the same
if (base_header[3] == header[3] && base_header[4] == header[4])
{
base_image.Unpack();
overlay.Baseline = base_image.Data;
}
break;
}
}
}
return overlay;
}
internal AImageScheme QueryScheme (string arc_name) internal AImageScheme QueryScheme (string arc_name)
{ {
var title = FormatCatalog.Instance.LookupGame (arc_name); var title = FormatCatalog.Instance.LookupGame (arc_name);
@ -579,8 +622,7 @@ namespace GameRes.Formats.Cyberworks
var entry = ReadEntryInfo(); var entry = ReadEntryInfo();
if (ReadEntryType (entry, entry_size)) if (ReadEntryType (entry, entry_size))
{ {
if (!entry.CheckPlacement (MaxOffset)) if (entry.CheckPlacement (MaxOffset))
return false;
m_dir.Add (entry); m_dir.Add (entry);
} }
m_index.Position = next_pos; m_index.Position = next_pos;
@ -668,6 +710,8 @@ namespace GameRes.Formats.Cyberworks
protected override bool ReadEntryType (Entry entry, int entry_size) protected override bool ReadEntryType (Entry entry, int entry_size)
{ {
if (entry_size > 0x11)
throw new InvalidFormatException();
char type = (char)m_index.ReadByte(); char type = (char)m_index.ReadByte();
if (type > 0x20 && type < 0x7F) if (type > 0x20 && type < 0x7F)
{ {

View File

@ -51,10 +51,12 @@ namespace GameRes.Formats.Cyberworks
byte[] m_output; byte[] m_output;
AImageScheme m_scheme; AImageScheme m_scheme;
ImageData m_image; ImageData m_image;
int[] m_header;
public Stream Source { get { m_input.Position = 0; return m_input.AsStream; } } public Stream Source { get { m_input.Position = 0; return m_input.AsStream; } }
public ImageFormat SourceFormat { get { return null; } } public ImageFormat SourceFormat { get { return null; } }
public ImageMetaData Info { get { return m_info; } } public ImageMetaData Info { get { return m_info; } }
public byte[] Baseline { get; set; }
public ImageData Image public ImageData Image
{ {
@ -81,17 +83,25 @@ namespace GameRes.Formats.Cyberworks
m_scheme = scheme; m_scheme = scheme;
} }
public void Unpack () internal int[] ReadHeader ()
{ {
if (m_header != null)
return m_header;
int header_length = Math.Max (8, m_scheme.HeaderOrder.Length); int header_length = Math.Max (8, m_scheme.HeaderOrder.Length);
var header = new int[header_length]; m_header = new int[header_length];
for (int i = 0; i < m_scheme.HeaderOrder.Length; ++i) for (int i = 0; i < m_scheme.HeaderOrder.Length; ++i)
{ {
int b = GetInt(); int b = GetInt();
header[m_scheme.HeaderOrder[i]] = b; m_header[m_scheme.HeaderOrder[i]] = b;
} }
Info.Width = (uint)header[4]; Info.Width = (uint)m_header[4];
Info.Height = (uint)header[3]; Info.Height = (uint)m_header[3];
return m_header;
}
public void Unpack ()
{
var header = ReadHeader();
if (0 == Info.Width || Info.Width >= 0x8000 || 0 == Info.Height || Info.Height >= 0x8000) if (0 == Info.Width || Info.Width >= 0x8000 || 0 == Info.Height || Info.Height >= 0x8000)
throw new InvalidFormatException(); throw new InvalidFormatException();
int unpacked_size = header[5]; int unpacked_size = header[5];
@ -160,22 +170,32 @@ namespace GameRes.Formats.Cyberworks
if (alpha_map.Length != alpha_size) if (alpha_map.Length != alpha_size)
throw new InvalidFormatException(); throw new InvalidFormatException();
Info.BPP = 32;
int plane_size = (int)Info.Width * (int)Info.Height; int plane_size = (int)Info.Width * (int)Info.Height;
if (Baseline != null)
{
Info.BPP = 24;
m_output = Baseline;
}
else
{
Info.BPP = 32;
m_output = new byte[plane_size * 4]; m_output = new byte[plane_size * 4];
}
int pixel_size = Info.BPP / 8;
int bit = 1; int bit = 1;
int bit_src = 0; int bit_src = 0;
int dst = 0; int dst = 0;
for (int i = 0; i < plane_size; ++i) for (int i = 0; i < plane_size; ++i)
{ {
byte alpha = 0;
if ((bit & alpha_map[bit_src]) != 0) if ((bit & alpha_map[bit_src]) != 0)
{ {
m_input.Read (m_output, dst, 3); m_input.Read (m_output, dst, 3);
m_output[dst+3] = 0xFF; alpha = 0xFF;
} }
else if (4 == pixel_size)
m_output[dst+3] = 0; m_output[dst+3] = alpha;
dst += 4; dst += pixel_size;
if (0x80 == bit) if (0x80 == bit)
{ {
++bit_src; ++bit_src;