mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-23 19:34:15 +08:00
(Csystem): support new incremental images.
This commit is contained in:
parent
525c2ff29b
commit
8c37a7e107
@ -2,7 +2,7 @@
|
|||||||
//! \date Thu Jun 16 13:48:04 2016
|
//! \date Thu Jun 16 13:48:04 2016
|
||||||
//! \brief Tinker Bell resource archive.
|
//! \brief Tinker Bell resource archive.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2016 by morkt
|
// Copyright (C) 2016-2017 by morkt
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to
|
// of this software and associated documentation files (the "Software"), to
|
||||||
@ -272,8 +272,12 @@ namespace GameRes.Formats.Cyberworks
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var reader = DecryptImage (input, barc.Scheme);
|
var reader = DecryptImage (input, barc.Scheme);
|
||||||
if (BlendOverlayImages && reader is AImageReader)
|
if (BlendOverlayImages)
|
||||||
reader = BlendAImage (barc, entry, reader as AImageReader);
|
{
|
||||||
|
var overlay = reader as AImageReader;
|
||||||
|
if (overlay != null)
|
||||||
|
overlay.ReadBaseline (barc, entry);
|
||||||
|
}
|
||||||
return reader;
|
return reader;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@ -294,55 +298,18 @@ namespace GameRes.Formats.Cyberworks
|
|||||||
input = BinaryStream.FromStream (new StreamRegion (input.AsStream, 5, img_size), input.Name);
|
input = BinaryStream.FromStream (new StreamRegion (input.AsStream, 5, img_size), input.Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (scheme != null && 'a' == type && input.Length > 21)
|
else if (scheme != null && ('a' == type || 'd' == type) && input.Length > 21)
|
||||||
{
|
{
|
||||||
int id = input.ReadByte();
|
int id = input.ReadByte();
|
||||||
if (id == scheme.Value2)
|
if (id == scheme.Value2)
|
||||||
{
|
{
|
||||||
return new AImageReader (input, scheme);
|
return new AImageReader (input, scheme, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
input.Position = 0;
|
input.Position = 0;
|
||||||
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);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
//! \date Fri Jun 17 18:49:04 2016
|
//! \date Fri Jun 17 18:49:04 2016
|
||||||
//! \brief Tinker Bell encrypted image file.
|
//! \brief Tinker Bell encrypted image file.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2016 by morkt
|
// Copyright (C) 2016-2017 by morkt
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to
|
// of this software and associated documentation files (the "Software"), to
|
||||||
@ -24,9 +24,10 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel.Composition;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
|
||||||
namespace GameRes.Formats.Cyberworks
|
namespace GameRes.Formats.Cyberworks
|
||||||
{
|
{
|
||||||
@ -52,11 +53,13 @@ namespace GameRes.Formats.Cyberworks
|
|||||||
AImageScheme m_scheme;
|
AImageScheme m_scheme;
|
||||||
ImageData m_image;
|
ImageData m_image;
|
||||||
int[] m_header;
|
int[] m_header;
|
||||||
|
int m_type;
|
||||||
|
|
||||||
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 byte[] Baseline { get; set; }
|
||||||
|
public int Type { get { return m_type; } }
|
||||||
|
|
||||||
public ImageData Image
|
public ImageData Image
|
||||||
{
|
{
|
||||||
@ -77,10 +80,11 @@ namespace GameRes.Formats.Cyberworks
|
|||||||
|
|
||||||
public byte[] Data { get { return m_output; } }
|
public byte[] Data { get { return m_output; } }
|
||||||
|
|
||||||
public AImageReader (IBinaryStream input, AImageScheme scheme)
|
public AImageReader (IBinaryStream input, AImageScheme scheme, int type = 'a')
|
||||||
{
|
{
|
||||||
m_input = input;
|
m_input = input;
|
||||||
m_scheme = scheme;
|
m_scheme = scheme;
|
||||||
|
m_type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal int[] ReadHeader ()
|
internal int[] ReadHeader ()
|
||||||
@ -99,6 +103,65 @@ namespace GameRes.Formats.Cyberworks
|
|||||||
return m_header;
|
return m_header;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Search archive <paramref name="arc"/> for baseline image.
|
||||||
|
/// </summary>
|
||||||
|
internal void ReadBaseline (BellArchive arc, Entry entry)
|
||||||
|
{
|
||||||
|
var header = ReadHeader();
|
||||||
|
if (!((header[0] & 1) == 1 && 'd' == this.Type
|
||||||
|
|| header[0] == 1 && 'a' == this.Type))
|
||||||
|
return;
|
||||||
|
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 = arc.OpenEntry (dir[i]))
|
||||||
|
{
|
||||||
|
int type = input.ReadByte();
|
||||||
|
if ('d' == type)
|
||||||
|
continue;
|
||||||
|
if ('a' == type)
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
Baseline = base_image.Data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ('b' == type || 'c' == type)
|
||||||
|
{
|
||||||
|
var size_buf = new byte[4];
|
||||||
|
input.Read (size_buf, 0 , 4);
|
||||||
|
var decoder = new PngBitmapDecoder (input, BitmapCreateOptions.None,
|
||||||
|
BitmapCacheOption.OnLoad);
|
||||||
|
BitmapSource frame = decoder.Frames[0];
|
||||||
|
Info.Width = (uint)frame.PixelWidth;
|
||||||
|
Info.Height = (uint)frame.PixelHeight;
|
||||||
|
if (frame.Format.BitsPerPixel != 32)
|
||||||
|
frame = new FormatConvertedBitmap (frame, PixelFormats.Bgra32, null, 0);
|
||||||
|
int stride = frame.PixelWidth * 4;
|
||||||
|
var pixels = new byte[stride * frame.PixelHeight];
|
||||||
|
frame.CopyPixels (pixels, stride, 0);
|
||||||
|
Baseline = pixels;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Unpack ()
|
public void Unpack ()
|
||||||
{
|
{
|
||||||
var header = ReadHeader();
|
var header = ReadHeader();
|
||||||
@ -118,6 +181,8 @@ namespace GameRes.Formats.Cyberworks
|
|||||||
{
|
{
|
||||||
if (0 == bits_size)
|
if (0 == bits_size)
|
||||||
CopyV6 (unpacked_size, header[6]);
|
CopyV6 (unpacked_size, header[6]);
|
||||||
|
else if (1 == (flags & 1) && 'd' == m_type && Baseline != null)
|
||||||
|
UnpackV6d (bits_size, bits_size + header[6]);
|
||||||
else
|
else
|
||||||
UnpackV6 (bits_size, data_offset, data_offset + header[6]);
|
UnpackV6 (bits_size, data_offset, data_offset + header[6]);
|
||||||
}
|
}
|
||||||
@ -306,6 +371,34 @@ namespace GameRes.Formats.Cyberworks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UnpackV6d (int bits_size, int rgb_offset)
|
||||||
|
{
|
||||||
|
Info.BPP = 32;
|
||||||
|
var rgb_map = m_input.ReadBytes (bits_size);
|
||||||
|
var alpha = m_input.ReadBytes (rgb_offset - bits_size);
|
||||||
|
int plane_size = Math.Min (Baseline.Length, bits_size*8);
|
||||||
|
m_output = Baseline;
|
||||||
|
int bit = 1;
|
||||||
|
int bit_src = 0;
|
||||||
|
int alpha_src = 0;
|
||||||
|
int dst = 0;
|
||||||
|
for (int i = 0; i < plane_size; ++i)
|
||||||
|
{
|
||||||
|
if ((bit & rgb_map[bit_src]) != 0)
|
||||||
|
{
|
||||||
|
m_input.Read (m_output, dst, 3);
|
||||||
|
m_output[dst+3] = alpha[alpha_src++];
|
||||||
|
}
|
||||||
|
dst += 4;
|
||||||
|
bit <<= 1;
|
||||||
|
if (0x100 == bit)
|
||||||
|
{
|
||||||
|
++bit_src;
|
||||||
|
bit = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int GetInt ()
|
int GetInt ()
|
||||||
{
|
{
|
||||||
byte a = m_input.ReadUInt8();
|
byte a = m_input.ReadUInt8();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user