mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-23 19:34:15 +08:00
implemented D.O.'s VRS, GGA and GGS images.
This commit is contained in:
parent
c270574f52
commit
aa93dabd2d
@ -123,6 +123,11 @@
|
||||
<Compile Include="elf\ArcAi5DAT.cs" />
|
||||
<Compile Include="elf\ImageRMT.cs" />
|
||||
<Compile Include="HuffmanCompression.cs" />
|
||||
<Compile Include="Ikura\ArcTAN.cs" />
|
||||
<Compile Include="Ikura\ImageGGA.cs" />
|
||||
<Compile Include="Ikura\ImageGGS.cs" />
|
||||
<Compile Include="Ikura\ImageTAN.cs" />
|
||||
<Compile Include="Ikura\ImageVRS.cs" />
|
||||
<Compile Include="Lambda\ArcLAX.cs" />
|
||||
<Compile Include="Lambda\ImageCLS.cs" />
|
||||
<Compile Include="Maika\ArcBK.cs" />
|
||||
|
@ -45,7 +45,7 @@ namespace GameRes.Formats.Ikura
|
||||
|
||||
public DrsOpener ()
|
||||
{
|
||||
Extensions = Enumerable.Empty<string>(); // DRS archives have no extensions
|
||||
Extensions = new string[] { "", "dat", "snr" };
|
||||
}
|
||||
|
||||
public override ArcFile TryOpen (ArcView file)
|
||||
@ -56,7 +56,7 @@ namespace GameRes.Formats.Ikura
|
||||
if (dir_size < 0x20 || 0 != (dir_size & 0xf) || dir_size + 2 >= file.MaxOffset)
|
||||
return null;
|
||||
byte first = file.View.ReadByte (2);
|
||||
if (0 == first)
|
||||
if (first <= 0x20)
|
||||
return null;
|
||||
file.View.Reserve (0, (uint)dir_size + 2);
|
||||
int dir_offset = 2;
|
||||
@ -64,25 +64,19 @@ namespace GameRes.Formats.Ikura
|
||||
uint next_offset = file.View.ReadUInt32 (dir_offset+12);
|
||||
if (next_offset > file.MaxOffset || next_offset < dir_size+2)
|
||||
return null;
|
||||
var encoding = Encodings.cp932.WithFatalFallback();
|
||||
byte[] name_raw = new byte[12];
|
||||
|
||||
int count = dir_size / 0x10 - 1;
|
||||
var dir = new List<Entry> (count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
file.View.Read (dir_offset, name_raw, 0, 12);
|
||||
int name_length = name_raw.Length;
|
||||
while (name_length > 0 && 0 == name_raw[name_length-1])
|
||||
--name_length;
|
||||
if (0 == name_length)
|
||||
var name = file.View.ReadString (dir_offset, 12);
|
||||
if (string.IsNullOrEmpty (name))
|
||||
return null;
|
||||
uint offset = next_offset;
|
||||
dir_offset += 0x10;
|
||||
next_offset = file.View.ReadUInt32 (dir_offset+12);
|
||||
if (next_offset > file.MaxOffset || next_offset < offset)
|
||||
return null;
|
||||
string name = encoding.GetString (name_raw, 0, name_length).ToLowerInvariant();
|
||||
var entry = FormatCatalog.Instance.Create<Entry> (name);
|
||||
entry.Offset = offset;
|
||||
entry.Size = next_offset - offset;
|
||||
@ -138,21 +132,16 @@ namespace GameRes.Formats.Ikura
|
||||
uint index_size = file.View.ReadUInt32 (12);
|
||||
if (index_size > file.MaxOffset)
|
||||
return null;
|
||||
var encoding = Encodings.cp932.WithFatalFallback();
|
||||
byte[] name_raw = new byte[12];
|
||||
|
||||
long dir_offset = 0x20;
|
||||
var dir = new List<Entry> (count);
|
||||
bool has_scripts = false;
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
file.View.Read (dir_offset, name_raw, 0, 12);
|
||||
int name_length = name_raw.Length;
|
||||
while (name_length > 0 && 0 == name_raw[name_length-1])
|
||||
--name_length;
|
||||
if (0 == name_length)
|
||||
var name = file.View.ReadString (dir_offset, 12);
|
||||
if (string.IsNullOrEmpty (name))
|
||||
return null;
|
||||
string name = encoding.GetString (name_raw, 0, name_length).ToLowerInvariant();
|
||||
name = name.ToLowerInvariant();
|
||||
Entry entry;
|
||||
if (name.EndsWith (".isf") || name.EndsWith (".snr"))
|
||||
{
|
||||
|
128
ArcFormats/Ikura/ArcTAN.cs
Normal file
128
ArcFormats/Ikura/ArcTAN.cs
Normal file
@ -0,0 +1,128 @@
|
||||
//! \file ArcTAN.cs
|
||||
//! \date 2018 Jan 16
|
||||
//! \brief D.O. animation resource format.
|
||||
//
|
||||
// Copyright (C) 2018 by morkt
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
|
||||
|
||||
namespace GameRes.Formats.Ikura
|
||||
{
|
||||
internal class TanEntry : Entry
|
||||
{
|
||||
public int Index;
|
||||
}
|
||||
|
||||
internal class TanArchive : ArcFile
|
||||
{
|
||||
public readonly TanMetaData Info;
|
||||
|
||||
public TanArchive (ArcView arc, ArchiveFormat impl, ICollection<Entry> dir, TanMetaData info)
|
||||
: base (arc, impl, dir)
|
||||
{
|
||||
Info = info;
|
||||
}
|
||||
}
|
||||
|
||||
[Export(typeof(ArchiveFormat))]
|
||||
public class TanOpener : ArchiveFormat
|
||||
{
|
||||
public override string Tag { get { return "TAN/DO"; } }
|
||||
public override string Description { get { return "D.O. animation resource"; } }
|
||||
public override uint Signature { get { return 0; } }
|
||||
public override bool IsHierarchic { get { return false; } }
|
||||
public override bool CanWrite { get { return false; } }
|
||||
|
||||
public override ArcFile TryOpen (ArcView file)
|
||||
{
|
||||
if (!file.Name.HasExtension (".tan"))
|
||||
return null;
|
||||
int count = file.View.ReadInt16 (0);
|
||||
if (!IsSaneCount (count))
|
||||
return null;
|
||||
uint index_pos = 2 + (uint)count * 4;
|
||||
var info = new TanMetaData {
|
||||
Width = file.View.ReadUInt16 (index_pos),
|
||||
Height = file.View.ReadUInt16 (index_pos+2),
|
||||
DataOffset = index_pos + 4,
|
||||
};
|
||||
index_pos += 0x404;
|
||||
count = file.View.ReadInt16 (index_pos);
|
||||
if (!IsSaneCount (count))
|
||||
return null;
|
||||
index_pos += 2;
|
||||
|
||||
var base_name = Path.GetFileNameWithoutExtension (file.Name);
|
||||
var base_offset = index_pos + 4 * count;
|
||||
var dir = new List<Entry> (count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
var entry = new TanEntry {
|
||||
Name = string.Format ("{0}#{1:D2}", base_name, i),
|
||||
Type = "image",
|
||||
Offset = base_offset + file.View.ReadUInt32 (index_pos),
|
||||
Index = i,
|
||||
};
|
||||
dir.Add (entry);
|
||||
index_pos += 4;
|
||||
}
|
||||
for (int i = 1; i < count; ++i)
|
||||
{
|
||||
dir[i-1].Size = (uint)(dir[i].Offset - dir[i-1].Offset);
|
||||
if (!dir[i-1].CheckPlacement (file.MaxOffset))
|
||||
return null;
|
||||
}
|
||||
dir[dir.Count-1].Size = (uint)(file.MaxOffset - dir[dir.Count-1].Offset);
|
||||
return new TanArchive (file, this, dir, info);
|
||||
}
|
||||
|
||||
public override IImageDecoder OpenImage (ArcFile arc, Entry entry)
|
||||
{
|
||||
var tarc = (TanArchive)arc;
|
||||
var tent = (TanEntry)entry;
|
||||
var input = arc.File.CreateStream();
|
||||
return new TanFrameDecoder (input, tarc.Info, tent.Index);
|
||||
}
|
||||
}
|
||||
|
||||
internal class TanFrameDecoder : BinaryImageDecoder
|
||||
{
|
||||
int m_frame;
|
||||
TanReader m_reader;
|
||||
|
||||
public TanFrameDecoder (IBinaryStream input, TanMetaData info, int frame)
|
||||
: base (input, info)
|
||||
{
|
||||
m_frame = frame;
|
||||
m_reader = new TanReader (m_input, info);
|
||||
}
|
||||
|
||||
protected override ImageData GetImageData ()
|
||||
{
|
||||
var pixels = m_reader.UnpackFrame (m_frame);
|
||||
return ImageData.Create (Info, m_reader.Format, m_reader.Palette, pixels);
|
||||
}
|
||||
}
|
||||
}
|
@ -460,13 +460,13 @@ namespace GameRes.Formats.Ikura
|
||||
}
|
||||
|
||||
[Export(typeof(ImageFormat))]
|
||||
public class GgaFormat : ImageFormat
|
||||
public class Gga0Format : ImageFormat
|
||||
{
|
||||
public override string Tag { get { return "GG2"; } }
|
||||
public override string Description { get { return "IKURA GDL image format"; } }
|
||||
public override uint Signature { get { return 0x30414747u; } } // 'GGA0'
|
||||
|
||||
public GgaFormat ()
|
||||
public Gga0Format ()
|
||||
{
|
||||
Extensions = new string[] { "gg1", "gg2", "gg3", "gg0" };
|
||||
}
|
||||
|
81
ArcFormats/Ikura/ImageGGA.cs
Normal file
81
ArcFormats/Ikura/ImageGGA.cs
Normal file
@ -0,0 +1,81 @@
|
||||
//! \file ImageGGA.cs
|
||||
//! \date 2018 Jan 16
|
||||
//! \brief D.O. compressed image format.
|
||||
//
|
||||
// Copyright (C) 2018 by morkt
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Windows.Media;
|
||||
using GameRes.Compression;
|
||||
|
||||
namespace GameRes.Formats.Ikura
|
||||
{
|
||||
[Export(typeof(ImageFormat))]
|
||||
public class GgaFormat : ImageFormat
|
||||
{
|
||||
public override string Tag { get { return "GGA"; } }
|
||||
public override string Description { get { return "D.O. image format"; } }
|
||||
public override uint Signature { get { return 0; } }
|
||||
|
||||
class GgaMetaData : ImageMetaData
|
||||
{
|
||||
public int UnpackedSize;
|
||||
}
|
||||
|
||||
public override ImageMetaData ReadMetaData (IBinaryStream file)
|
||||
{
|
||||
if (!file.Name.HasExtension (".gga"))
|
||||
return null;
|
||||
int x = file.ReadInt16();
|
||||
int y = file.ReadInt16();
|
||||
uint w = file.ReadUInt16();
|
||||
uint h = file.ReadUInt16();
|
||||
int unpacked_size = file.ReadInt32();
|
||||
if (0 == w || 0 == h || w > 0x7FFF || h > 0x7FFF || x < 0 || y < 0
|
||||
|| 3 * w * h != unpacked_size)
|
||||
return null;
|
||||
return new GgaMetaData {
|
||||
Width = w, Height = h, OffsetX = x, OffsetY = y, BPP = 24,
|
||||
UnpackedSize = unpacked_size,
|
||||
};
|
||||
}
|
||||
|
||||
public override ImageData Read (IBinaryStream file, ImageMetaData info)
|
||||
{
|
||||
var meta = (GgaMetaData)info;
|
||||
file.Position = 12;
|
||||
var pixels = new byte[meta.UnpackedSize];
|
||||
using (var input = new LzssStream (file.AsStream, LzssMode.Decompress, true))
|
||||
{
|
||||
if (pixels.Length != input.Read (pixels, 0, pixels.Length))
|
||||
throw new InvalidFormatException();
|
||||
}
|
||||
return ImageData.Create (info, PixelFormats.Bgr24, null, pixels);
|
||||
}
|
||||
|
||||
public override void Write (Stream file, ImageData image)
|
||||
{
|
||||
throw new System.NotImplementedException ("GgaFormat.Write not implemented");
|
||||
}
|
||||
}
|
||||
}
|
140
ArcFormats/Ikura/ImageGGS.cs
Normal file
140
ArcFormats/Ikura/ImageGGS.cs
Normal file
@ -0,0 +1,140 @@
|
||||
//! \file ImageGGS.cs
|
||||
//! \date 2018 Jan 16
|
||||
//! \brief D.O. compressed image format.
|
||||
//
|
||||
// Copyright (C) 2018 by morkt
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace GameRes.Formats.Ikura
|
||||
{
|
||||
[Export(typeof(ImageFormat))]
|
||||
public class GgsFormat : ImageFormat
|
||||
{
|
||||
public override string Tag { get { return "GGS"; } }
|
||||
public override string Description { get { return "D.O. image format"; } }
|
||||
public override uint Signature { get { return 0; } }
|
||||
|
||||
public override ImageMetaData ReadMetaData (IBinaryStream file)
|
||||
{
|
||||
if (!file.Name.HasExtension (".ggs"))
|
||||
return null;
|
||||
int x = file.ReadInt16();
|
||||
int y = file.ReadInt16();
|
||||
uint w = file.ReadUInt16();
|
||||
uint h = file.ReadUInt16();
|
||||
if (0 == w || 0 == h || w > 0x4000 || h > 0x4000 || x < 0 || y < 0)
|
||||
return null;
|
||||
return new ImageMetaData { Width = w, Height = h, OffsetX = x, OffsetY = y, BPP = 24 };
|
||||
}
|
||||
|
||||
public override ImageData Read (IBinaryStream file, ImageMetaData info)
|
||||
{
|
||||
var reader = new GgsReader (file, info);
|
||||
var pixels = reader.Unpack();
|
||||
return ImageData.Create (info, reader.Format, null, pixels);
|
||||
}
|
||||
|
||||
public override void Write (Stream file, ImageData image)
|
||||
{
|
||||
throw new System.NotImplementedException ("GgsFormat.Write not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
internal class GgsReader
|
||||
{
|
||||
IBinaryStream m_input;
|
||||
byte[] m_output;
|
||||
|
||||
public PixelFormat Format { get { return PixelFormats.Bgr24; } }
|
||||
|
||||
public GgsReader (IBinaryStream input, ImageMetaData info)
|
||||
{
|
||||
m_input = input;
|
||||
m_output = new byte[3 * info.Width * info.Height];
|
||||
}
|
||||
|
||||
public byte[] Unpack ()
|
||||
{
|
||||
m_input.Position = 8;
|
||||
for (int channel = 0; channel < 3; ++channel)
|
||||
{
|
||||
int dst = channel;
|
||||
while (dst < m_output.Length)
|
||||
{
|
||||
int count;
|
||||
byte ctl = m_input.ReadUInt8();
|
||||
if (0 == ctl--)
|
||||
{
|
||||
count = m_input.ReadUInt8();
|
||||
byte v = m_input.ReadUInt8();
|
||||
while (count --> 0)
|
||||
{
|
||||
m_output[dst] = v;
|
||||
dst += 3;
|
||||
}
|
||||
}
|
||||
else if (0 == ctl--)
|
||||
{
|
||||
count = m_input.ReadUInt8();
|
||||
int offset = m_input.ReadUInt8();
|
||||
while (count --> 0)
|
||||
{
|
||||
m_output[dst] = m_output[dst-offset];
|
||||
dst += 3;
|
||||
}
|
||||
}
|
||||
else if (0 == ctl--)
|
||||
{
|
||||
count = m_input.ReadUInt8();
|
||||
int offset = m_input.ReadUInt16();
|
||||
while (count --> 0)
|
||||
{
|
||||
m_output[dst] = m_output[dst-offset];
|
||||
dst += 3;
|
||||
}
|
||||
}
|
||||
else if (0 == ctl--)
|
||||
{
|
||||
dst += m_input.ReadUInt8();
|
||||
}
|
||||
else if (0 == ctl)
|
||||
{
|
||||
dst += m_input.ReadUInt16();
|
||||
}
|
||||
else
|
||||
{
|
||||
count = ctl;
|
||||
while (count --> 0)
|
||||
{
|
||||
m_output[dst] = m_input.ReadUInt8();
|
||||
dst += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return m_output;
|
||||
}
|
||||
}
|
||||
}
|
170
ArcFormats/Ikura/ImageTAN.cs
Normal file
170
ArcFormats/Ikura/ImageTAN.cs
Normal file
@ -0,0 +1,170 @@
|
||||
//! \file ImageTAN.cs
|
||||
//! \date 2018 Jan 16
|
||||
//! \brief D.O. animation resource format.
|
||||
//
|
||||
// Copyright (C) 2018 by morkt
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using GameRes.Utility;
|
||||
|
||||
namespace GameRes.Formats.Ikura
|
||||
{
|
||||
internal class TanMetaData : ImageMetaData
|
||||
{
|
||||
public uint DataOffset;
|
||||
}
|
||||
|
||||
[Export(typeof(ImageFormat))]
|
||||
public class TanFormat : ImageFormat
|
||||
{
|
||||
public override string Tag { get { return "TAN"; } }
|
||||
public override string Description { get { return "D.O. animation resource"; } }
|
||||
public override uint Signature { get { return 0; } }
|
||||
|
||||
public override ImageMetaData ReadMetaData (IBinaryStream file)
|
||||
{
|
||||
if (!file.Name.HasExtension (".tan"))
|
||||
return null;
|
||||
int count = file.ReadUInt16();
|
||||
if (0 == count)
|
||||
return null;
|
||||
file.Position = 2 + count * 4;
|
||||
uint w = file.ReadUInt16();
|
||||
uint h = file.ReadUInt16();
|
||||
if (0 == w || 0 == h)
|
||||
return null;
|
||||
return new TanMetaData {
|
||||
Width = w, Height = h, BPP = 8,
|
||||
DataOffset = (uint)file.Position,
|
||||
};
|
||||
}
|
||||
|
||||
public override ImageData Read (IBinaryStream file, ImageMetaData info)
|
||||
{
|
||||
var reader = new TanReader (file, (TanMetaData)info);
|
||||
var pixels = reader.UnpackFrame (0);
|
||||
return ImageData.Create (info, reader.Format, reader.Palette, pixels);
|
||||
}
|
||||
|
||||
public override void Write (Stream file, ImageData image)
|
||||
{
|
||||
throw new System.NotImplementedException ("TanFormat.Write not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
internal class TanReader
|
||||
{
|
||||
IBinaryStream m_input;
|
||||
byte[] m_output;
|
||||
TanMetaData m_info;
|
||||
|
||||
public PixelFormat Format { get; private set; }
|
||||
public BitmapPalette Palette { get; private set; }
|
||||
|
||||
public TanReader (IBinaryStream input, TanMetaData info)
|
||||
{
|
||||
m_input = input;
|
||||
m_output = new byte[info.Width * info.Height];
|
||||
m_info = info;
|
||||
Format = 8 == m_info.BPP ? PixelFormats.Indexed8 : PixelFormats.Bgr24;
|
||||
}
|
||||
|
||||
public byte[] UnpackFrame (int frame)
|
||||
{
|
||||
m_input.Position = m_info.DataOffset;
|
||||
if (8 == m_info.BPP)
|
||||
Palette = ImageFormat.ReadPalette (m_input.AsStream);
|
||||
int count = m_input.ReadUInt16();
|
||||
if (frame >= count)
|
||||
throw new InvalidFormatException ("Not enough frames in TAN file.");
|
||||
long base_pos = m_input.Position + 4 * count;
|
||||
var frame_table = new uint[count];
|
||||
for (int i = 0; i < count; ++i)
|
||||
frame_table[i] = m_input.ReadUInt32();
|
||||
Action Unpack;
|
||||
if (8 == m_info.BPP)
|
||||
Unpack = Unpack8bpp;
|
||||
else
|
||||
Unpack = Unpack24bpp;
|
||||
for (int i = 0; i <= frame; ++i)
|
||||
{
|
||||
m_input.Position = base_pos + frame_table[i];
|
||||
Unpack();
|
||||
}
|
||||
return m_output;
|
||||
}
|
||||
|
||||
void Unpack8bpp ()
|
||||
{
|
||||
int dst = 0;
|
||||
while (dst < m_output.Length)
|
||||
{
|
||||
int count;
|
||||
byte ctl = m_input.ReadUInt8();
|
||||
if (0 == ctl--)
|
||||
{
|
||||
count = m_input.ReadUInt8();
|
||||
byte v = m_input.ReadUInt8();
|
||||
while (count --> 0)
|
||||
m_output[dst++] = v;
|
||||
}
|
||||
else if (0 == ctl--)
|
||||
{
|
||||
count = m_input.ReadUInt8();
|
||||
int offset = m_input.ReadUInt8();
|
||||
Binary.CopyOverlapped (m_output, dst-offset, dst, count);
|
||||
dst += count;
|
||||
}
|
||||
else if (0 == ctl--)
|
||||
{
|
||||
count = m_input.ReadUInt8();
|
||||
int offset = m_input.ReadUInt16();
|
||||
Binary.CopyOverlapped (m_output, dst-offset, dst, count);
|
||||
dst += count;
|
||||
}
|
||||
else if (0 == ctl--)
|
||||
{
|
||||
dst += m_input.ReadUInt8();
|
||||
}
|
||||
else if (0 == ctl)
|
||||
{
|
||||
dst += m_input.ReadUInt16();
|
||||
}
|
||||
else
|
||||
{
|
||||
count = ctl;
|
||||
m_input.Read (m_output, dst, count);
|
||||
dst += count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Unpack24bpp ()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
132
ArcFormats/Ikura/ImageVRS.cs
Normal file
132
ArcFormats/Ikura/ImageVRS.cs
Normal file
@ -0,0 +1,132 @@
|
||||
//! \file ImageVRS.cs
|
||||
//! \date 2018 Jan 16
|
||||
//! \brief D.O. image format.
|
||||
//
|
||||
// Copyright (C) 2018 by morkt
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using GameRes.Utility;
|
||||
|
||||
namespace GameRes.Formats.Ikura
|
||||
{
|
||||
[Export(typeof(ImageFormat))]
|
||||
public class DoFormat : ImageFormat
|
||||
{
|
||||
public override string Tag { get { return "VRS/DO"; } }
|
||||
public override string Description { get { return "D.O. image format"; } }
|
||||
public override uint Signature { get { return 0x4F44; } } // 'DO'
|
||||
|
||||
public override ImageMetaData ReadMetaData (IBinaryStream file)
|
||||
{
|
||||
var header = file.ReadHeader (8);
|
||||
return new ImageMetaData {
|
||||
Width = header.ToUInt16 (4),
|
||||
Height = header.ToUInt16 (6),
|
||||
BPP = 8,
|
||||
};
|
||||
}
|
||||
|
||||
public override ImageData Read (IBinaryStream file, ImageMetaData info)
|
||||
{
|
||||
var reader = new DoReader (file, info);
|
||||
reader.Unpack();
|
||||
return ImageData.Create (info, reader.Format, reader.Palette, reader.Data);
|
||||
}
|
||||
|
||||
public override void Write (Stream file, ImageData image)
|
||||
{
|
||||
throw new System.NotImplementedException ("DoFormat.Write not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
internal class DoReader
|
||||
{
|
||||
IBinaryStream m_input;
|
||||
byte[] m_output;
|
||||
|
||||
public PixelFormat Format { get; private set; }
|
||||
public BitmapPalette Palette { get; private set; }
|
||||
public byte[] Data { get { return m_output; } }
|
||||
|
||||
public DoReader (IBinaryStream input, ImageMetaData info)
|
||||
{
|
||||
m_input = input;
|
||||
m_output = new byte[info.Width * info.Height];
|
||||
Format = PixelFormats.Indexed8;
|
||||
}
|
||||
|
||||
public void Unpack ()
|
||||
{
|
||||
m_input.Position = 12;
|
||||
Palette = ReadPalette();
|
||||
int dst = 0;
|
||||
while (dst < m_output.Length)
|
||||
{
|
||||
int count;
|
||||
byte ctl = m_input.ReadUInt8();
|
||||
if (0 == (ctl & 0xC0))
|
||||
{
|
||||
count = ctl & 0x3F;
|
||||
if (0 == count)
|
||||
count = m_input.ReadUInt8() + 0x40;
|
||||
m_input.Read (m_output, dst, count);
|
||||
}
|
||||
else if (0 == (ctl & 0x80))
|
||||
{
|
||||
count = ctl & 0x3F;
|
||||
if (0 == count)
|
||||
count = m_input.ReadUInt8() + 0x40;
|
||||
++count;
|
||||
Binary.CopyOverlapped (m_output, dst-1, dst, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = (m_input.ReadUInt8() | (ctl & 0xF) << 8) + 1;
|
||||
count = (ctl >> 4) & 7;
|
||||
if (0 == count)
|
||||
count = m_input.ReadUInt8() + 8;
|
||||
count += 2;
|
||||
Binary.CopyOverlapped (m_output, dst-offset, dst, count);
|
||||
}
|
||||
dst += count;
|
||||
}
|
||||
}
|
||||
|
||||
BitmapPalette ReadPalette ()
|
||||
{
|
||||
var palette_data = m_input.ReadBytes (0x300);
|
||||
if (palette_data.Length != 0x300)
|
||||
throw new EndOfStreamException();
|
||||
int src = 0;
|
||||
var color_map = new Color[0x100];
|
||||
for (int i = 0; i < 0x100; ++i)
|
||||
{
|
||||
color_map[i] = Color.FromRgb (palette_data[src+1], palette_data[src+2], palette_data[src]);
|
||||
src += 3;
|
||||
}
|
||||
return new BitmapPalette (color_map);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user