mirror of
https://github.com/crskycode/GARbro.git
synced 2025-01-11 04:29:15 +08:00
added some IImageDecoder implementations.
This commit is contained in:
parent
d02a9b180a
commit
2c06c1cbcd
@ -52,7 +52,7 @@ namespace GameRes.Formats.CatSystem
|
||||
uint section_size = file.View.ReadUInt32 (offset+0x40);
|
||||
var entry = new Entry
|
||||
{
|
||||
Name = string.Format ("{0}#{1:D4}.tga", base_name, i),
|
||||
Name = string.Format ("{0}#{1:D4}", base_name, i),
|
||||
Type = "image",
|
||||
Offset = offset,
|
||||
};
|
||||
@ -71,9 +71,8 @@ namespace GameRes.Formats.CatSystem
|
||||
return new ArcFile (file, this, dir);
|
||||
}
|
||||
|
||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
||||
public override IImageDecoder OpenImage (ArcFile arc, Entry entry)
|
||||
{
|
||||
// emulate TGA image
|
||||
var offset = entry.Offset;
|
||||
var info = new Hg2MetaData
|
||||
{
|
||||
@ -90,11 +89,8 @@ namespace GameRes.Formats.CatSystem
|
||||
OffsetX = arc.File.View.ReadInt32 (offset+0x34),
|
||||
OffsetY = arc.File.View.ReadInt32 (offset+0x38),
|
||||
};
|
||||
using (var input = arc.File.CreateStream (entry.Offset, entry.Size))
|
||||
using (var reader = new Hg2Reader (input, info))
|
||||
{
|
||||
return TgaStream.Create (info, reader.Unpack(), true);
|
||||
}
|
||||
var input = arc.File.CreateStream (entry.Offset, entry.Size);
|
||||
return new Hg2Reader (input, info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ namespace GameRes.Formats.CatSystem
|
||||
{
|
||||
var entry = new Entry
|
||||
{
|
||||
Name = string.Format ("{0}#{1:D4}.tga", base_name, i),
|
||||
Name = string.Format ("{0}#{1:D4}", base_name, i),
|
||||
Type = "image",
|
||||
Offset = offset + 8,
|
||||
Size = section_size - 8,
|
||||
@ -70,9 +70,8 @@ namespace GameRes.Formats.CatSystem
|
||||
return new ArcFile (file, this, dir);
|
||||
}
|
||||
|
||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
||||
public override IImageDecoder OpenImage (ArcFile arc, Entry entry)
|
||||
{
|
||||
// emulate TGA image
|
||||
var offset = entry.Offset+8;
|
||||
var info = new HgMetaData
|
||||
{
|
||||
@ -85,12 +84,8 @@ namespace GameRes.Formats.CatSystem
|
||||
CanvasWidth = arc.File.View.ReadUInt32 (offset+0x1C),
|
||||
CanvasHeight = arc.File.View.ReadUInt32 (offset+0x20),
|
||||
};
|
||||
using (var input = arc.File.CreateStream (entry.Offset, entry.Size))
|
||||
using (var reader = new Hg3Reader (input, info))
|
||||
{
|
||||
var pixels = reader.Unpack();
|
||||
return TgaStream.Create (info, pixels, reader.Flipped);
|
||||
}
|
||||
var input = arc.File.CreateStream (entry.Offset, entry.Size);
|
||||
return new Hg3Reader (input, info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -74,11 +74,7 @@ namespace GameRes.Formats.CatSystem
|
||||
public override ImageData Read (IBinaryStream stream, ImageMetaData info)
|
||||
{
|
||||
using (var reader = new Hg2Reader (stream, (Hg2MetaData)info))
|
||||
{
|
||||
var pixels = reader.Unpack();
|
||||
var format = 24 == info.BPP ? PixelFormats.Bgr24 : PixelFormats.Bgra32;
|
||||
return ImageData.CreateFlipped (info, format, null, pixels, reader.Stride);
|
||||
}
|
||||
return reader.Image;
|
||||
}
|
||||
|
||||
public override void Write (Stream file, ImageData image)
|
||||
@ -91,6 +87,20 @@ namespace GameRes.Formats.CatSystem
|
||||
{
|
||||
Hg2MetaData m_hg2;
|
||||
|
||||
public override ImageData Image
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == m_image)
|
||||
{
|
||||
var pixels = Unpack();
|
||||
var format = 24 == m_hg2.BPP ? PixelFormats.Bgr24 : PixelFormats.Bgra32;
|
||||
m_image = ImageData.CreateFlipped (m_hg2, format, null, pixels, Stride);
|
||||
}
|
||||
return m_image;
|
||||
}
|
||||
}
|
||||
|
||||
public Hg2Reader (IBinaryStream input, Hg2MetaData info) : base (input, info)
|
||||
{
|
||||
m_hg2 = info;
|
||||
|
@ -77,11 +77,7 @@ namespace GameRes.Formats.CatSystem
|
||||
using (var input = new BinaryStream (reg, stream.Name))
|
||||
using (var reader = new Hg3Reader (input, meta))
|
||||
{
|
||||
var pixels = reader.Unpack();
|
||||
if (reader.Flipped)
|
||||
return ImageData.CreateFlipped (info, PixelFormats.Bgra32, null, pixels, reader.Stride);
|
||||
else
|
||||
return ImageData.Create (info, PixelFormats.Bgra32, null, pixels, reader.Stride);
|
||||
return reader.Image;
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,15 +87,18 @@ namespace GameRes.Formats.CatSystem
|
||||
}
|
||||
}
|
||||
|
||||
internal class HgReader : IDisposable
|
||||
internal class HgReader : IImageDecoder
|
||||
{
|
||||
private IBinaryStream m_input;
|
||||
protected IBinaryStream m_input;
|
||||
protected HgMetaData m_info;
|
||||
protected int m_pixel_size;
|
||||
protected ImageData m_image;
|
||||
|
||||
protected IBinaryStream Input { get { return m_input; } }
|
||||
protected Stream InputStream { get { return m_input.AsStream; } }
|
||||
public Stream Input { get { return m_input.AsStream; } }
|
||||
public int Stride { get; protected set; }
|
||||
public ImageFormat Format { get { return null; } }
|
||||
public ImageMetaData Info { get { return m_info; } }
|
||||
public virtual ImageData Image { get { throw new NotImplementedException(); } }
|
||||
|
||||
protected HgReader (IBinaryStream input, HgMetaData info)
|
||||
{
|
||||
@ -113,12 +112,12 @@ namespace GameRes.Formats.CatSystem
|
||||
{
|
||||
var ctl_offset = data_offset + data_packed;
|
||||
var data = new byte[data_unpacked];
|
||||
using (var z = new StreamRegion (InputStream, data_offset, data_packed, true))
|
||||
using (var z = new StreamRegion (Input, data_offset, data_packed, true))
|
||||
using (var data_in = new ZLibStream (z, CompressionMode.Decompress))
|
||||
if (data.Length != data_in.Read (data, 0, data.Length))
|
||||
throw new EndOfStreamException();
|
||||
|
||||
using (var z = new StreamRegion (InputStream, ctl_offset, ctl_packed, true))
|
||||
using (var z = new StreamRegion (Input, ctl_offset, ctl_packed, true))
|
||||
using (var ctl_in = new ZLibStream (z, CompressionMode.Decompress))
|
||||
using (var bits = new LsbBitStream (ctl_in))
|
||||
{
|
||||
@ -237,14 +236,30 @@ namespace GameRes.Formats.CatSystem
|
||||
{
|
||||
public bool Flipped { get; private set; }
|
||||
|
||||
public override ImageData Image
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == m_image)
|
||||
{
|
||||
var pixels = Unpack();
|
||||
if (Flipped)
|
||||
m_image = ImageData.CreateFlipped (Info, PixelFormats.Bgra32, null, pixels, Stride);
|
||||
else
|
||||
m_image = ImageData.Create (Info, PixelFormats.Bgra32, null, pixels, Stride);
|
||||
}
|
||||
return m_image;
|
||||
}
|
||||
}
|
||||
|
||||
public Hg3Reader (IBinaryStream input, HgMetaData info) : base (input, info)
|
||||
{
|
||||
}
|
||||
|
||||
public byte[] Unpack ()
|
||||
{
|
||||
InputStream.Position = m_info.HeaderSize;
|
||||
var img_type = Input.ReadBytes (8);
|
||||
Input.Position = m_info.HeaderSize;
|
||||
var img_type = m_input.ReadBytes (8);
|
||||
if (Binary.AsciiEqual (img_type, "img0000\0"))
|
||||
return UnpackImg0000();
|
||||
else if (Binary.AsciiEqual (img_type, "img_jpg\0"))
|
||||
@ -256,21 +271,21 @@ namespace GameRes.Formats.CatSystem
|
||||
byte[] UnpackImg0000 ()
|
||||
{
|
||||
Flipped = true;
|
||||
InputStream.Position = m_info.HeaderSize+0x18;
|
||||
int packed_data_size = Input.ReadInt32();
|
||||
int data_size = Input.ReadInt32();
|
||||
int packed_ctl_size = Input.ReadInt32();
|
||||
int ctl_size = Input.ReadInt32();
|
||||
Input.Position = m_info.HeaderSize+0x18;
|
||||
int packed_data_size = m_input.ReadInt32();
|
||||
int data_size = m_input.ReadInt32();
|
||||
int packed_ctl_size = m_input.ReadInt32();
|
||||
int ctl_size = m_input.ReadInt32();
|
||||
return UnpackStream (m_info.HeaderSize+0x28, packed_data_size, data_size, packed_ctl_size, ctl_size);
|
||||
}
|
||||
|
||||
byte[] UnpackJpeg ()
|
||||
{
|
||||
Flipped = false;
|
||||
Input.ReadInt32();
|
||||
var jpeg_size = Input.ReadInt32();
|
||||
long next_section = InputStream.Position + jpeg_size;
|
||||
var decoder = new JpegBitmapDecoder (InputStream,
|
||||
m_input.ReadInt32();
|
||||
var jpeg_size = m_input.ReadInt32();
|
||||
long next_section = Input.Position + jpeg_size;
|
||||
var decoder = new JpegBitmapDecoder (Input,
|
||||
BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
|
||||
var frame = decoder.Frames[0];
|
||||
if (frame.Format.BitsPerPixel < 24)
|
||||
@ -292,13 +307,13 @@ namespace GameRes.Formats.CatSystem
|
||||
src += src_pixel_size;
|
||||
}
|
||||
|
||||
Input.Position = next_section;
|
||||
var section_header = Input.ReadBytes (8);
|
||||
m_input.Position = next_section;
|
||||
var section_header = m_input.ReadBytes (8);
|
||||
if (!Binary.AsciiEqual (section_header, "img_al\0\0"))
|
||||
return output;
|
||||
Input.Seek (8, SeekOrigin.Current);
|
||||
int alpha_size = Input.ReadInt32();
|
||||
using (var alpha_in = new StreamRegion (InputStream, InputStream.Position+4, alpha_size, true))
|
||||
m_input.Seek (8, SeekOrigin.Current);
|
||||
int alpha_size = m_input.ReadInt32();
|
||||
using (var alpha_in = new StreamRegion (Input, Input.Position+4, alpha_size, true))
|
||||
using (var alpha = new ZLibStream (alpha_in, CompressionMode.Decompress))
|
||||
{
|
||||
for (int i = 3; i < output.Length; i += 4)
|
||||
|
@ -27,6 +27,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace GameRes.Formats.Kaguya
|
||||
{
|
||||
@ -79,7 +80,7 @@ namespace GameRes.Formats.Kaguya
|
||||
uint height = file.View.ReadUInt32 (current_offset+12);
|
||||
var entry = new Entry
|
||||
{
|
||||
Name = string.Format ("{0}#{1:D2}.tga", base_name, i),
|
||||
Name = string.Format ("{0}#{1:D2}", base_name, i),
|
||||
Type = "image",
|
||||
Offset = current_offset,
|
||||
Size = 0x10 + 4*width*height,
|
||||
@ -90,22 +91,34 @@ namespace GameRes.Formats.Kaguya
|
||||
return new AnmArchive (file, this, dir, base_info);
|
||||
}
|
||||
|
||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
||||
public override IImageDecoder OpenImage (ArcFile arc, Entry entry)
|
||||
{
|
||||
var base_info = ((AnmArchive)arc).ImageInfo;
|
||||
// emulate TGA image
|
||||
var offset = entry.Offset;
|
||||
var info = new ImageMetaData
|
||||
var input = arc.File.CreateStream (entry.Offset, entry.Size);
|
||||
return new An00Decoder (input, base_info);
|
||||
}
|
||||
}
|
||||
|
||||
internal class An00Decoder : BinaryImageDecoder
|
||||
{
|
||||
public An00Decoder (IBinaryStream input, ImageMetaData base_info) : base (input)
|
||||
{
|
||||
Info = new ImageMetaData
|
||||
{
|
||||
OffsetX = base_info.OffsetX + arc.File.View.ReadInt32 (offset),
|
||||
OffsetY = base_info.OffsetY + arc.File.View.ReadInt32 (offset+4),
|
||||
Width = arc.File.View.ReadUInt32 (offset+8),
|
||||
Height = arc.File.View.ReadUInt32 (offset+12),
|
||||
BPP = 32,
|
||||
OffsetX = base_info.OffsetX + m_input.ReadInt32(),
|
||||
OffsetY = base_info.OffsetY + m_input.ReadInt32(),
|
||||
Width = m_input.ReadUInt32(),
|
||||
Height = m_input.ReadUInt32(),
|
||||
BPP = 32,
|
||||
};
|
||||
offset += 0x10;
|
||||
var pixels = arc.File.View.ReadBytes (offset, 4*info.Width*info.Height);
|
||||
return TgaStream.Create (info, pixels, true);
|
||||
}
|
||||
|
||||
protected override ImageData GetImageData ()
|
||||
{
|
||||
m_input.Position = 0x10;
|
||||
int stride = 4*(int)Info.Width;
|
||||
var pixels = m_input.ReadBytes (stride*(int)Info.Height);
|
||||
return ImageData.CreateFlipped (Info, PixelFormats.Bgra32, null, pixels, stride);
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,7 +176,7 @@ namespace GameRes.Formats.Kaguya
|
||||
uint depth = file.View.ReadUInt32 (current_offset+0x10);
|
||||
var entry = new Entry
|
||||
{
|
||||
Name = string.Format ("{0}#{1:D2}.tga", base_name, i),
|
||||
Name = string.Format ("{0}#{1:D2}", base_name, i),
|
||||
Type = "image",
|
||||
Offset = current_offset,
|
||||
Size = 0x14 + depth*width*height,
|
||||
@ -174,22 +187,45 @@ namespace GameRes.Formats.Kaguya
|
||||
return new AnmArchive (file, this, dir, base_info);
|
||||
}
|
||||
|
||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
||||
public override IImageDecoder OpenImage (ArcFile arc, Entry entry)
|
||||
{
|
||||
var base_info = ((AnmArchive)arc).ImageInfo;
|
||||
// emulate TGA image
|
||||
var offset = entry.Offset;
|
||||
var info = new ImageMetaData
|
||||
var input = arc.File.CreateStream (entry.Offset, entry.Size);
|
||||
return new An20Decoder (input, base_info);
|
||||
}
|
||||
}
|
||||
|
||||
internal class An20Decoder : BinaryImageDecoder
|
||||
{
|
||||
public An20Decoder (IBinaryStream input, ImageMetaData base_info) : base (input)
|
||||
{
|
||||
Info = new ImageMetaData
|
||||
{
|
||||
OffsetX = base_info.OffsetX + arc.File.View.ReadInt32 (offset),
|
||||
OffsetY = base_info.OffsetY + arc.File.View.ReadInt32 (offset+4),
|
||||
Width = arc.File.View.ReadUInt32 (offset+8),
|
||||
Height = arc.File.View.ReadUInt32 (offset+0xC),
|
||||
BPP = arc.File.View.ReadInt32 (offset+0x10) * 8,
|
||||
OffsetX = base_info.OffsetX + m_input.ReadInt32(),
|
||||
OffsetY = base_info.OffsetY + m_input.ReadInt32(),
|
||||
Width = m_input.ReadUInt32(),
|
||||
Height = m_input.ReadUInt32(),
|
||||
BPP = m_input.ReadInt32() * 8,
|
||||
};
|
||||
offset += 0x14;
|
||||
var pixels = arc.File.View.ReadBytes (offset, (uint)info.BPP/8*info.Width*info.Height);
|
||||
return TgaStream.Create (info, pixels, true);
|
||||
}
|
||||
|
||||
protected override ImageData GetImageData ()
|
||||
{
|
||||
m_input.Position = 0x14;
|
||||
int stride = info.BPP/8*(int)Info.Width;
|
||||
var pixels = m_input.ReadBytes (stride*(int)info.Height);
|
||||
return ImageData.CreateFlipped (Info, GetFormat(), null, pixels, stride);
|
||||
}
|
||||
|
||||
PixelFormat GetFormat ()
|
||||
{
|
||||
switch (Info.BPP)
|
||||
{
|
||||
case 8: return PixelFormats.Gray8;
|
||||
case 24: return PixelFormats.Bgr24;
|
||||
case 32: return PixelFormats.Bgra32;
|
||||
default: throw new InvalidFormatException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ namespace GameRes.Formats.Musica
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
var entry = new Entry {
|
||||
Name = string.Format ("{0}#{1:D4}.tga", base_name, i),
|
||||
Name = string.Format ("{0}#{1:D4}", base_name, i),
|
||||
Type = "image",
|
||||
Offset = file.View.ReadUInt32 (index_offset),
|
||||
Size = file.View.ReadUInt32 (index_offset+4),
|
||||
@ -82,15 +82,51 @@ namespace GameRes.Formats.Musica
|
||||
return new SqzArchive (file, this, dir, info);
|
||||
}
|
||||
|
||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
||||
public override IImageDecoder OpenImage (ArcFile arc, Entry entry)
|
||||
{
|
||||
var sqarc = (SqzArchive)arc;
|
||||
using (var input = arc.File.CreateStream (entry.Offset, entry.Size))
|
||||
using (var zs = new ZLibStream (input, CompressionMode.Decompress))
|
||||
var input = arc.File.CreateStream (entry.Offset, entry.Size);
|
||||
var zs = new ZLibStream (input, CompressionMode.Decompress);
|
||||
return new SqzReader (zs, sqarc.Info);
|
||||
}
|
||||
|
||||
internal sealed class SqzReader : IImageDecoder
|
||||
{
|
||||
Stream m_input;
|
||||
ImageMetaData m_info;
|
||||
ImageData m_image;
|
||||
|
||||
public Stream Input { get { return m_input; } }
|
||||
public ImageFormat Format { get { return null; } }
|
||||
public ImageMetaData Info { get { return m_info; } }
|
||||
public ImageData Image
|
||||
{
|
||||
var pixels = new byte[sqarc.Info.Width * sqarc.Info.Height * 4];
|
||||
zs.Read (pixels, 0, pixels.Length);
|
||||
return TgaStream.Create (sqarc.Info, pixels);
|
||||
get
|
||||
{
|
||||
if (null == m_image)
|
||||
{
|
||||
var pixels = new byte[m_info.Width * m_info.Height * 4];
|
||||
m_input.Read (pixels, 0, pixels.Length);
|
||||
m_image = ImageData.Create (m_info, PixelFormats.Bgra32, null, pixels);
|
||||
}
|
||||
return m_image;
|
||||
}
|
||||
}
|
||||
|
||||
public SqzReader (Stream input, ImageMetaData info)
|
||||
{
|
||||
m_input = input;
|
||||
m_info = info;
|
||||
}
|
||||
|
||||
bool m_disposed = false;
|
||||
public void Dispose ()
|
||||
{
|
||||
if (!m_disposed)
|
||||
{
|
||||
m_input.Dispose();
|
||||
m_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ namespace GameRes.Formats.ShiinaRio
|
||||
{
|
||||
var entry = new Entry
|
||||
{
|
||||
Name = string.Format ("{0}@{1:D4}.tga", base_name, i),
|
||||
Name = string.Format ("{0}@{1:D4}", base_name, i),
|
||||
Type = "image",
|
||||
Offset = offset,
|
||||
};
|
||||
@ -79,9 +79,8 @@ namespace GameRes.Formats.ShiinaRio
|
||||
return new ArcFile (file, this, dir);
|
||||
}
|
||||
|
||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
||||
public override IImageDecoder OpenImage (ArcFile arc, Entry entry)
|
||||
{
|
||||
// emulate TGA image
|
||||
var offset = entry.Offset;
|
||||
var info = new S25MetaData
|
||||
{
|
||||
@ -93,11 +92,8 @@ namespace GameRes.Formats.ShiinaRio
|
||||
FirstOffset = (uint)(offset + 0x14),
|
||||
Incremental = 0 != (arc.File.View.ReadUInt32 (offset+0x10) & 0x80000000u),
|
||||
};
|
||||
using (var input = arc.File.CreateStream (0, (uint)arc.File.MaxOffset))
|
||||
using (var reader = new S25Format.Reader (input, info))
|
||||
{
|
||||
return TgaStream.Create (info, reader.Unpack());
|
||||
}
|
||||
var input = arc.File.CreateStream (0, (uint)arc.File.MaxOffset);
|
||||
return new S25Format.Reader (input, info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,10 +76,7 @@ namespace GameRes.Formats.ShiinaRio
|
||||
public override ImageData Read (IBinaryStream stream, ImageMetaData info)
|
||||
{
|
||||
using (var reader = new Reader (stream, (S25MetaData)info))
|
||||
{
|
||||
var pixels = reader.Unpack();
|
||||
return ImageData.Create (info, PixelFormats.Bgra32, null, pixels);
|
||||
}
|
||||
return reader.Image;
|
||||
}
|
||||
|
||||
public override void Write (Stream file, ImageData image)
|
||||
@ -87,7 +84,7 @@ namespace GameRes.Formats.ShiinaRio
|
||||
throw new NotImplementedException ("S25Format.Write not implemented");
|
||||
}
|
||||
|
||||
internal sealed class Reader : IDisposable
|
||||
internal sealed class Reader : IImageDecoder
|
||||
{
|
||||
IBinaryStream m_input;
|
||||
int m_width;
|
||||
@ -95,6 +92,25 @@ namespace GameRes.Formats.ShiinaRio
|
||||
uint m_origin;
|
||||
byte[] m_output;
|
||||
bool m_incremental;
|
||||
ImageMetaData m_info;
|
||||
ImageData m_image;
|
||||
|
||||
public Stream Input { get { m_input.Position = 0; return m_input.AsStream; } }
|
||||
public ImageMetaData Info { get { return m_info; } }
|
||||
public ImageFormat Format { get { return null; } }
|
||||
|
||||
public ImageData Image
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == m_image)
|
||||
{
|
||||
var pixels = Unpack();
|
||||
m_image = ImageData.Create (m_info, PixelFormats.Bgra32, null, pixels);
|
||||
}
|
||||
return m_image;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] Data { get { return m_output; } }
|
||||
|
||||
@ -106,6 +122,7 @@ namespace GameRes.Formats.ShiinaRio
|
||||
m_input = file;
|
||||
m_origin = info.FirstOffset;
|
||||
m_incremental = info.Incremental;
|
||||
m_info = info;
|
||||
}
|
||||
|
||||
public byte[] Unpack ()
|
||||
|
Loading…
x
Reference in New Issue
Block a user