mirror of
https://github.com/crskycode/GARbro.git
synced 2024-11-23 21:55:34 +08:00
implemented PBZ archives, PSB images and MV audio.
This commit is contained in:
parent
554ec7edce
commit
21138f9dcd
@ -73,6 +73,9 @@
|
||||
<Compile Include="Ankh\ArcGRP.cs" />
|
||||
<Compile Include="ArcCG.cs" />
|
||||
<Compile Include="Banana\ImageGEC.cs" />
|
||||
<Compile Include="Cmvs\ArcPBZ.cs" />
|
||||
<Compile Include="Cmvs\AudioMV.cs" />
|
||||
<Compile Include="Cmvs\ImagePSB.cs" />
|
||||
<Compile Include="Bruns\AudioUM3.cs" />
|
||||
<Compile Include="Bruns\ImageEENC.cs" />
|
||||
<Compile Include="LiveMaker\ArcVF.cs" />
|
||||
|
223
ArcFormats/Cmvs/ArcPBZ.cs
Normal file
223
ArcFormats/Cmvs/ArcPBZ.cs
Normal file
@ -0,0 +1,223 @@
|
||||
//! \file ArcPBZ.cs
|
||||
//! \date Thu Jun 23 19:12:32 2016
|
||||
//! \brief PVNS engine (CMVS precursor) resource archive.
|
||||
//
|
||||
// Copyright (C) 2016 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.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using GameRes.Utility;
|
||||
|
||||
namespace GameRes.Formats.Pvns
|
||||
{
|
||||
internal class PbzArchive : ArcFile
|
||||
{
|
||||
public readonly byte[] ArcKey;
|
||||
public readonly byte[] ScriptKey;
|
||||
|
||||
public PbzArchive (ArcView arc, ArchiveFormat impl, ICollection<Entry> dir, PbzKeys scheme)
|
||||
: base (arc, impl, dir)
|
||||
{
|
||||
ArcKey = scheme.ArcKey;
|
||||
ScriptKey = scheme.ScriptKey;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class PbzKeys
|
||||
{
|
||||
public byte[] ArcKey;
|
||||
public byte[] ScriptKey;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class PbzScheme : ResourceScheme
|
||||
{
|
||||
public Dictionary<string, PbzKeys> KnownSchemes;
|
||||
}
|
||||
|
||||
[Export(typeof(ArchiveFormat))]
|
||||
public class PbzOpener : ArchiveFormat
|
||||
{
|
||||
public override string Tag { get { return "PBZ"; } }
|
||||
public override string Description { get { return "PVNS engine resource archive"; } }
|
||||
public override uint Signature { get { return 0x315A4250; } } // 'PBZ1'
|
||||
public override bool IsHierarchic { get { return false; } }
|
||||
public override bool CanCreate { get { return false; } }
|
||||
|
||||
public static Dictionary<string, PbzKeys> KnownSchemes = new Dictionary<string, PbzKeys>();
|
||||
|
||||
public override ResourceScheme Scheme
|
||||
{
|
||||
get { return new PbzScheme { KnownSchemes = KnownSchemes }; }
|
||||
set { KnownSchemes = ((PbzScheme)value).KnownSchemes; }
|
||||
}
|
||||
|
||||
public override ArcFile TryOpen (ArcView file)
|
||||
{
|
||||
if (0 == KnownSchemes.Count)
|
||||
return null;
|
||||
int count = file.View.ReadInt32 (4);
|
||||
if (!IsSaneCount (count))
|
||||
return null;
|
||||
uint index_size = file.View.ReadUInt32 (8);
|
||||
var index = file.View.ReadBytes (0x10, index_size);
|
||||
if (index.Length != index_size)
|
||||
return null;
|
||||
|
||||
var scheme = KnownSchemes.Values.First(); // XXX
|
||||
Decrypt (index, scheme.ArcKey);
|
||||
|
||||
long base_offset = 0x10 + index_size;
|
||||
int index_pos = 0;
|
||||
var dir = new List<Entry> (count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
int entry_size = LittleEndian.ToInt32 (index, index_pos);
|
||||
if (entry_size <= 0x18)
|
||||
return null;
|
||||
var name = Binary.GetCString (index, index_pos+0x18, entry_size - 0x18);
|
||||
var entry = FormatCatalog.Instance.Create<Entry> (name);
|
||||
entry.Size = LittleEndian.ToUInt32 (index, index_pos+4);
|
||||
entry.Offset = base_offset + LittleEndian.ToUInt32 (index, index_pos+8);
|
||||
if (!entry.CheckPlacement (file.MaxOffset))
|
||||
return null;
|
||||
dir.Add (entry);
|
||||
index_pos += entry_size;
|
||||
}
|
||||
return new PbzArchive (file, this, dir, scheme);
|
||||
}
|
||||
|
||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
||||
{
|
||||
var parc = arc as PbzArchive;
|
||||
if (null == parc)
|
||||
return base.OpenEntry (arc, entry);
|
||||
var data = arc.File.View.ReadBytes (entry.Offset, entry.Size);
|
||||
Decrypt (data, parc.ArcKey);
|
||||
if (entry.Name.EndsWith (".scr", StringComparison.InvariantCultureIgnoreCase)
|
||||
&& Binary.AsciiEqual (data, "PSRA") && data.Length > 20)
|
||||
{
|
||||
data = DecryptScript (data, parc.ScriptKey);
|
||||
}
|
||||
return new MemoryStream (data);
|
||||
}
|
||||
|
||||
static void Decrypt (byte[] data, byte[] key)
|
||||
{
|
||||
if (0 == key.Length)
|
||||
return;
|
||||
for (int i = 0; i < data.Length; ++i)
|
||||
{
|
||||
data[i] = (byte)((data[i] ^ key[i % key.Length]) + 0x80);
|
||||
}
|
||||
}
|
||||
|
||||
byte[] DecryptScript (byte[] data, byte[] key)
|
||||
{
|
||||
int input_size = data.Length - 0x14;
|
||||
for (int i = 4; i < 0x14; ++i)
|
||||
{
|
||||
data[i] = (byte)((data[i] ^ 0xF5) - 0x10);
|
||||
}
|
||||
if (0 != (input_size & -4))
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* data8 = &data[0x14])
|
||||
{
|
||||
uint m = 0x817543;
|
||||
uint* data32 = (uint*)data8;
|
||||
for (int length = (((input_size & -4) - 1) >> 2) + 1; length > 0; --length)
|
||||
{
|
||||
*data32 ^= m;
|
||||
m += 0x1352467u;
|
||||
++data32;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
uint checksum = LittleEndian.ToUInt32 (data, 4);
|
||||
for (int i = 0x14; i < data.Length; ++i)
|
||||
{
|
||||
checksum -= data[i];
|
||||
}
|
||||
if (checksum != 0)
|
||||
throw new InvalidEncryptionScheme();
|
||||
|
||||
for (int i = 0x14; i < data.Length; ++i)
|
||||
{
|
||||
data[i] = Binary.RotByteR (data[i], 3);
|
||||
}
|
||||
int src = 0x14;
|
||||
for (int count = ((input_size - 2) >> 1) + 1; count > 0; --count)
|
||||
{
|
||||
byte t = data[src];
|
||||
data[src] = data[src+1];
|
||||
data[src+1] = t;
|
||||
src += 2;
|
||||
}
|
||||
int k = 0;
|
||||
for (int i = 0x14; i < data.Length; ++i)
|
||||
{
|
||||
data[i] = (byte)((data[i] ^ key[k++]) + 0x35);
|
||||
k %= key.Length;
|
||||
}
|
||||
int unpacked_size = LittleEndian.ToInt32 (data, 0x10);
|
||||
var output = new byte[unpacked_size];
|
||||
src = 0x14 + LittleEndian.ToInt32 (data, 8);
|
||||
int dst = 0;
|
||||
int bit_mask = 0x80;
|
||||
int bits = 0x14;
|
||||
while (dst < output.Length)
|
||||
{
|
||||
if (0 == bit_mask)
|
||||
{
|
||||
bit_mask = 0x80;
|
||||
++bits;
|
||||
}
|
||||
if (0 != (bit_mask & data[bits]))
|
||||
{
|
||||
int u = LittleEndian.ToUInt16 (data, src);
|
||||
src += 2;
|
||||
int offset = (u >> 5) + 1;
|
||||
int count = (u & 0x1F) + 3;
|
||||
Binary.CopyOverlapped (output, dst - offset, dst, count);
|
||||
dst += count;
|
||||
}
|
||||
else
|
||||
{
|
||||
output[dst++] = data[src++];
|
||||
}
|
||||
bit_mask >>= 1;
|
||||
}
|
||||
for (int i = 0; i < output.Length; ++i)
|
||||
{
|
||||
output[i] ^= 0x7E;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
408
ArcFormats/Cmvs/AudioMV.cs
Normal file
408
ArcFormats/Cmvs/AudioMV.cs
Normal file
@ -0,0 +1,408 @@
|
||||
//! \file AudioMV.cs
|
||||
//! \date Fri Jun 24 05:29:29 2016
|
||||
//! \brief PVNS engine audio format.
|
||||
//
|
||||
// Copyright (C) 2016 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 GameRes.Utility;
|
||||
|
||||
namespace GameRes.Formats.Pvns
|
||||
{
|
||||
[Export(typeof(AudioFormat))]
|
||||
public class MvAudio : AudioFormat
|
||||
{
|
||||
public override string Tag { get { return "MV"; } }
|
||||
public override string Description { get { return "PVNS engine compressed audio format"; } }
|
||||
public override uint Signature { get { return 0x53564B4D; } } // 'MKVS'
|
||||
|
||||
public override SoundInput TryOpen (Stream file)
|
||||
{
|
||||
using (var reader = new MvReader (file))
|
||||
{
|
||||
reader.Unpack();
|
||||
var input = new MemoryStream (reader.Data);
|
||||
var sound = new RawPcmInput (input, reader.Format);
|
||||
file.Dispose();
|
||||
return sound;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class MvReader : IDisposable
|
||||
{
|
||||
BinaryReader m_input;
|
||||
byte[] m_output;
|
||||
WaveFormat m_format;
|
||||
int m_channel_size;
|
||||
int m_samples;
|
||||
|
||||
public byte[] Data { get { return m_output; } }
|
||||
public WaveFormat Format { get { return m_format; } }
|
||||
|
||||
public MvReader (Stream input)
|
||||
{
|
||||
var header = new byte[0x12];
|
||||
input.Read (header, 0, header.Length);
|
||||
m_channel_size = LittleEndian.ToInt32 (header, 4);
|
||||
m_format.FormatTag = 1;
|
||||
m_format.BitsPerSample = 16;
|
||||
m_format.Channels = header[0xC];
|
||||
m_format.SamplesPerSecond = LittleEndian.ToUInt16 (header, 0xA);
|
||||
m_format.BlockAlign = (ushort)(m_format.Channels*m_format.BitsPerSample/8);
|
||||
m_format.AverageBytesPerSecond = m_format.SamplesPerSecond*m_format.BlockAlign;
|
||||
m_input = new ArcView.Reader (input);
|
||||
m_output = new byte[2 * m_format.Channels * m_channel_size];
|
||||
m_samples = LittleEndian.ToInt32 (header, 0xE);
|
||||
}
|
||||
|
||||
public void Unpack ()
|
||||
{
|
||||
m_input.BaseStream.Position = 0x12;
|
||||
var pre_sample1 = new int[0x400];
|
||||
var pre_sample2 = new int[0x400];
|
||||
var pre_sample3 = new int[0x140 * m_format.Channels];
|
||||
int pre2_idx = 0;
|
||||
int dst = 0;
|
||||
for (int i = 0; i < m_samples; ++i)
|
||||
{
|
||||
for (int c = 0; c < m_format.Channels; ++c)
|
||||
{
|
||||
int count = GetBits (10);
|
||||
int v32 = (int)SampleTable[GetBits (10)];
|
||||
for (int j = 0; j < pre_sample1.Length; ++j)
|
||||
pre_sample1[j] = 0;
|
||||
for (int j = 0; j < count; ++j)
|
||||
{
|
||||
int bit_count = 0;
|
||||
while (0 != GetBits (1))
|
||||
{
|
||||
++bit_count;
|
||||
}
|
||||
if (bit_count != 0)
|
||||
{
|
||||
int coef = GetBits (bit_count);
|
||||
if (coef < (1 << (bit_count - 1)))
|
||||
coef += 1 - (1 << bit_count);
|
||||
pre_sample1[j] = v32 * coef;
|
||||
}
|
||||
else
|
||||
{
|
||||
j += GetBits (3);
|
||||
}
|
||||
}
|
||||
int pre3_idx = 0;
|
||||
for (int n = 0; n < 10; ++n)
|
||||
{
|
||||
int coef1_idx = 0;
|
||||
for (int j = 0; j < 64; ++j)
|
||||
{
|
||||
int pre1_idx = pre3_idx;
|
||||
int sample = 0;
|
||||
for (int k = 0; k < 8; ++k)
|
||||
{
|
||||
for (int m = 0; m < 4; ++m)
|
||||
{
|
||||
sample += Coef1Table[coef1_idx] * pre_sample1[pre1_idx++] >> 10;
|
||||
++coef1_idx;
|
||||
}
|
||||
}
|
||||
pre_sample2[pre2_idx + j] = sample;
|
||||
}
|
||||
int coef2_idx = 0;
|
||||
for (int j = 0; j < 0x20; ++j)
|
||||
{
|
||||
int x = 0;
|
||||
int m = pre2_idx + j;
|
||||
for (int k = 0; k < 0x10; ++k)
|
||||
{
|
||||
int coef = Coef2Table[coef2_idx++] * pre_sample2[m & 0x3FF] >> 10;
|
||||
x += ((~k & 2) - 1) * coef;
|
||||
m += ~(k << 6) & 0x40 | 0x20;
|
||||
}
|
||||
pre_sample3[pre3_idx++] = x;
|
||||
}
|
||||
pre2_idx = ((ushort)pre2_idx - 0x40) & 0x3FF;
|
||||
}
|
||||
for (int j = 0; j < 0x140; ++j)
|
||||
{
|
||||
int sample = pre_sample3[j] >> 1;
|
||||
if (sample > 0x7FFF)
|
||||
sample = 0x7FFF;
|
||||
else if (sample < -0x7FFF)
|
||||
sample = -0x7FFF;
|
||||
LittleEndian.Pack ((short)sample, m_output, dst);
|
||||
dst += 2; // ??? shouldn't channel interleaving be taken into account?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int m_bits;
|
||||
int m_bits_count = 0;
|
||||
|
||||
int GetBits (int count)
|
||||
{
|
||||
int v = 0;
|
||||
while (count --> 0)
|
||||
{
|
||||
if (0 == m_bits_count)
|
||||
{
|
||||
m_bits = m_input.ReadInt32();
|
||||
m_bits_count = 32;
|
||||
}
|
||||
v = (v << 1) | (m_bits & 1);
|
||||
m_bits >>= 1;
|
||||
--m_bits_count;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
bool _disposed = false;
|
||||
public void Dispose ()
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
m_input.Dispose();
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
static MvReader ()
|
||||
{
|
||||
var table = new uint[0x400];
|
||||
Array.Copy (SampleTable, 0, table, 0x192, SampleTable.Length);
|
||||
SampleTable = table;
|
||||
}
|
||||
|
||||
static readonly uint[] SampleTable = {
|
||||
1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9,
|
||||
0x0A, 0x0B, 0x0D, 0x0F, 0x11, 0x13, 0x15, 0x18, 0x1C, 0x1F, 0x24, 0x29, 0x2E, 0x34, 0x3B, 0x43,
|
||||
0x4C, 0x57, 0x62, 0x6F, 0x7E, 0x8F, 0x0A2, 0x0B8, 0x0D1, 0x0ED, 0x10C, 0x130, 0x159, 0x187, 0x1BB,
|
||||
0x1F6, 0x23A, 0x286, 0x2DC, 0x33E, 0x3AC, 0x42A, 0x4B8, 0x55A, 0x611, 0x6E0, 0x7CB, 0x8D5, 0x0A03,
|
||||
0x0B59, 0x0CDD, 0x0E95, 0x1087, 0x12BC, 0x153C, 0x1812, 0x1B48, 0x1EED, 0x230D, 0x27BB, 0x2D09,
|
||||
0x330B, 0x39DC, 0x4195, 0x4A56, 0x5442, 0x5F81, 0x6C40, 0x7AB3, 0x8B13, 0x9DA4, 0x0B2AE, 0x0CA87,
|
||||
0x0E590, 0x10434, 0x126EF, 0x14E4C, 0x17AEB, 0x1AD7E, 0x1E6D2, 0x227CC, 0x27173, 0x2C4EE, 0x3238D,
|
||||
0x38ECE, 0x4085F, 0x4922B, 0x52E5A, 0x5DF62, 0x6A80C, 0x78B7D, 0x88D4B, 0x9B181, 0x0AFCB8,
|
||||
0x0C7424, 0x0E1DAC, 0x100000, 0x1222B4, 0x148E61, 0x174CC4, 0x1A68E6, 0x1DEF4C, 0x021EE24,
|
||||
0x0267582, 0x02B979E, 0x0316920, 0x0380171, 0x03F7B1A, 0x047F42F, 0x0518EC8,
|
||||
0x005C7189, 0x0068C83E, 0x0076C48E, 0x00869EBE, 0x00989697, 0x00ACF464, 0x00C40A17, 0x00DE3494,
|
||||
0x00FBDD22, 0x011D7B16, 0x014395B5, 0x016EC64D, 0x019FBAA7, 0x01D737BC, 0x02161CD0, 0x025D66F3,
|
||||
0x02AE34FC, 0x0309CC0D, 0x03719CA9, 0x03E74889, 0x046CA921, 0x0503D71B, 0x05AF32C0, 0x06716D8A,
|
||||
0x074D94FB, 0x08471EE1, 0x0961F74A, 0x0AA29043, 0x0C0DF3C3, 0x0DA9D7EB, 0x0F7CB605, 0x118DE48F,
|
||||
0x13E5B4C1, 0x168D9405, 0x199031E4, 0x1CF9AB08, 0x20D7B9F2, 0x2539EE3E, 0x2A31EB3C, 0x2FD3AEE5,
|
||||
0x3635E252, 0x3D7234E4, 0x45A5C3A0, 0x4EF18E50, 0x597AFC4E, 0x656C72FE, 0x72F60068, 0x824E1C92,
|
||||
0x93B284A6, 0xA7693360, 0xBDC17A9E, 0xD7154285, 0xF3CA7345, 0x14548F1D, 0x39368323, 0x6304B60B,
|
||||
0x92675D44, 0xC81D21C8, 0x04FE1F40, 0x49FF4989, 0x98364650, 0xF0DDCA35, 0x555A8B0B, 0xC740DB1A,
|
||||
0x485B03F6, 0xDAB07A77, 0x808E08CC, 0x3C8F0F8E, 0x11A80301, 0x03324EC0, 0x14F9CFAE, 0x4B4C1A53,
|
||||
0xAB09CB36, 0x39BA26C6, 0xFDA157D3, 0xFDD9A61D, 0x42700A59, 0xD48492BE, 0xBE6F1A63, 0x0BE8E730,
|
||||
0xCA3BD5C8, 0x0877D150, 0xD7AF6E22, 0x4B3C9B45, 0x790E7F24, 0x7A01B8AE, 0x6A446813, 0x69C79196,
|
||||
0x9CBFA29E, 0x2C361E40, 0x46AEBB45, 0x20E28C1F, 0xF69421D6, 0x0B7FFF6C, 0xAC6D2545, 0x3061FD29,
|
||||
0xFA0281CC, 0x791D22E1, 0x2C6CA27E, 0xA395FE02, 0x816A6624, 0x7E765BA6, 0x6BE83C9E, 0x36D9EE16,
|
||||
0xEC0ADC7A, 0xBC19516B, 0x004C1DC9, 0x3FFFDB91, 0x36CD9D5F, 0xDB83CB83, 0x680D3C3A, 0x62665333,
|
||||
0xA6C432FE, 0x7316DA81, 0x74147C83, 0xD4028D70, 0x4B7804F0, 0x345C419E, 0x9F6EFD39, 0x6CAFF339,
|
||||
0x67086BEA, 0x63A5F955, 0x65848E7B, 0xC5B6EFEF, 0x610F9314, 0xCBE1A360, 0x8CAA6A87, 0x5E8F23A2,
|
||||
0x7CBAC282, 0xF7CAEDB8, 0x16A3E37E, 0xC430E23C, 0x0BCAAD8E, 0xA638B9A5, 0x998455D9, 0xEE20E8F1,
|
||||
0x7C4226CE, 0xD49A7152, 0x4829DC77, 0x13434BF5, 0xB07ACE02, 0x58D0ECCF, 0xB724B5AC, 0xD5C48581,
|
||||
0x4DDF847F, 0xC1A2CBDE, 0xAAF9A261, 0x8A3CC828, 0x819ECA65, 0x6BD8DCBC, 0x7E8BA111, 0x8AF96278,
|
||||
0xF23C6AD9, 0x64EE47B6, 0x896763F7, 0xA75E2F54, 0x7BC8B5BB, 0x5C8B914C, 0xD8C8442D, 0x0898814F,
|
||||
0xC5CBCE4B, 0x0EEC7CF0, 0xDE872E53, 0xCA8FEFF0, 0xCAF14963, 0x9301470C, 0xF7F9BE55, 0xEEDD91D7,
|
||||
0xBEAE2B5F, 0x18C51C24, 0xE0E2027C, 0x89641700, 0x06A53454, 0x7EFCA69E, 0x041D80AE, 0xCEEC5354,
|
||||
0xA93DA54C, 0x69FBCBF4, 0xA8DD9914, 0x18239314, 0x45E66D10, 0xE4AD08E8, 0x25BDE2A0, 0x289C3F50,
|
||||
0x0C445120, 0xCA29BE38, 0xB32BDF40, 0x2E668E30, 0x3C220C80, 0x3FB63840, 0xB605D1A0, 0xC7D85340,
|
||||
0x1CF90F40, 0xFC81FE00, 0xA6BDAA80, 0xF523F640, 0xB5AB4A80, 0xF1AFFA40, 0x6906E880, 0x0BE74AC0,
|
||||
0x384A5880, 0x0133C880, 0xE2293C00, 0x0B819180, 0x0475A980, 0xD05D4700, 0x333C9700, 0x409BF280,
|
||||
0x3515DE00, 0xE29F7D00, 0xE2C72400, 0x88E93700, 0x703D4500, 0xC6771000, 0x6D335200, 0x16D6F000,
|
||||
0x07D2F200, 0x9A0BEA00, 0x8C1F4A00, 0x22092C00, 0xD5107C00, 0x8A20AC00, 0xDDBFC000, 0x07CE7800,
|
||||
};
|
||||
|
||||
static readonly short[] Coef1Table = {
|
||||
724, -724, -724, 724, 724, -724, -724, 724, 724, -724, -724, 724, 724, -724, -724, 724,
|
||||
724, -724, -724, 724, 724, -724, -724, 724, 724, -724, -724, 724, 724, -724, -724, 724,
|
||||
687, -822, -526, 925, 344, -993, -150, 1022, -50, -1012, 248, 964, -437, -878, 609, 758,
|
||||
-758, -609, 878, 437, -964, -248, 1012, 50, -1022, 150, 993, -344, -925, 526, 822, -687,
|
||||
649, -903, -297, 1019, -100, -979, 482, 791, -791, -482, 979, 100, -1019, 297, 903, -649,
|
||||
-649, 903, 297, -1019, 100, 979, -482, -791, 791, 482, -979, -100, 1019, -297, -903, 649,
|
||||
609, -964, -50, 993, -526, -687, 925, 150, -1012, 437, 758, -878, -248, 1022, -344, -822,
|
||||
822, 344, -1022, 248, 878, -758, -437, 1012, -150, -925, 687, 526, -993, 50, 964, -609,
|
||||
568, -1004, 199, 851, -851, -199, 1004, -568, -568, 1004, -199, -851, 851, 199, -1004, 568,
|
||||
568, -1004, 199, 851, -851, -199, 1004, -568, -568, 1004, -199, -851, 851, 199, -1004, 568,
|
||||
526, -1022, 437, 609, -1012, 344, 687, -993, 248, 758, -964, 150, 822, -925, 50, 878,
|
||||
-878, -50, 925, -822, -150, 964, -758, -248, 993, -687, -344, 1012, -609, -437, 1022, -526,
|
||||
482, -1019, 649, 297, -979, 791, 100, -903, 903, -100, -791, 979, -297, -649, 1019, -482,
|
||||
-482, 1019, -649, -297, 979, -791, -100, 903, -903, 100, 791, -979, 297, 649, -1019, 482,
|
||||
437, -993, 822, -50, -758, 1012, -526, -344, 964, -878, 150, 687, -1022, 609, 248, -925,
|
||||
925, -248, -609, 1022, -687, -150, 878, -964, 344, 526, -1012, 758, 50, -822, 993, -437,
|
||||
391, -946, 946, -391, -391, 946, -946, 391, 391, -946, 946, -391, -391, 946, -946, 391,
|
||||
391, -946, 946, -391, -391, 946, -946, 391, 391, -946, 946, -391, -391, 946, -946, 391,
|
||||
344, -878, 1012, -687, 50, 609, -993, 925, -437, -248, 822, -1022, 758, -150, -526, 964,
|
||||
-964, 526, 150, -758, 1022, -822, 248, 437, -925, 993, -609, -50, 687, -1012, 878, -344,
|
||||
297, -791, 1019, -903, 482, 100, -649, 979, -979, 649, -100, -482, 903, -1019, 791, -297,
|
||||
-297, 791, -1019, 903, -482, -100, 649, -979, 979, -649, 100, 482, -903, 1019, -791, 297,
|
||||
248, -687, 964, -1012, 822, -437, -50, 526, -878, 1022, -925, 609, -150, -344, 758, -993,
|
||||
993, -758, 344, 150, -609, 925, -1022, 878, -526, 50, 437, -822, 1012, -964, 687, -248,
|
||||
199, -568, 851, -1004, 1004, -851, 568, -199, -199, 568, -851, 1004, -1004, 851, -568, 199,
|
||||
199, -568, 851, -1004, 1004, -851, 568, -199, -199, 568, -851, 1004, -1004, 851, -568, 199,
|
||||
150, -437, 687, -878, 993, -1022, 964, -822, 609, -344, 50, 248, -526, 758, -925, 1012,
|
||||
-1012, 925, -758, 526, -248, -50, 344, -609, 822, -964, 1022, -993, 878, -687, 437, -150,
|
||||
100, -297, 482, -649, 791, -903, 979, -1019, 1019, -979, 903, -791, 649, -482, 297, -100,
|
||||
-100, 297, -482, 649, -791, 903, -979, 1019, -1019, 979, -903, 791, -649, 482, -297, 100,
|
||||
50, -150, 248, -344, 437, -526, 609, -687, 758, -822, 878, -925, 964, -993, 1012, -1022,
|
||||
1022, -1012, 993, -964, 925, -878, 822, -758, 687, -609, 526, -437, 344, -248, 150, -50,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
-50, 150, -248, 344, -437, 526, -609, 687, -758, 822, -878, 925, -964, 993, -1012, 1022,
|
||||
-1022, 1012, -993, 964, -925, 878, -822, 758, -687, 609, -526, 437, -344, 248, -150, 50,
|
||||
-100, 297, -482, 649, -791, 903, -979, 1019, -1019, 979, -903, 791, -649, 482, -297, 100,
|
||||
100, -297, 482, -649, 791, -903, 979, -1019, 1019, -979, 903, -791, 649, -482, 297, -100,
|
||||
-150, 437, -687, 878, -993, 1022, -964, 822, -609, 344, -50, -248, 526, -758, 925, -1012,
|
||||
1012, -925, 758, -526, 248, 50, -344, 609, -822, 964, -1022, 993, -878, 687, -437, 150,
|
||||
-199, 568, -851, 1004, -1004, 851, -568, 199, 199, -568, 851, -1004, 1004, -851, 568, -199,
|
||||
-199, 568, -851, 1004, -1004, 851, -568, 199, 199, -568, 851, -1004, 1004, -851, 568, -199,
|
||||
-248, 687, -964, 1012, -822, 437, 50, -526, 878, -1022, 925, -609, 150, 344, -758, 993,
|
||||
-993, 758, -344, -150, 609, -925, 1022, -878, 526, -50, -437, 822, -1012, 964, -687, 248,
|
||||
-297, 791, -1019, 903, -482, -100, 649, -979, 979, -649, 100, 482, -903, 1019, -791, 297,
|
||||
297, -791, 1019, -903, 482, 100, -649, 979, -979, 649, -100, -482, 903, -1019, 791, -297,
|
||||
-344, 878, -1012, 687, -50, -609, 993, -925, 437, 248, -822, 1022, -758, 150, 526, -964,
|
||||
964, -526, -150, 758, -1022, 822, -248, -437, 925, -993, 609, 50, -687, 1012, -878, 344,
|
||||
-391, 946, -946, 391, 391, -946, 946, -391, -391, 946, -946, 391, 391, -946, 946, -391,
|
||||
-391, 946, -946, 391, 391, -946, 946, -391, -391, 946, -946, 391, 391, -946, 946, -391,
|
||||
-437, 993, -822, 50, 758, -1012, 526, 344, -964, 878, -150, -687, 1022, -609, -248, 925,
|
||||
-925, 248, 609, -1022, 687, 150, -878, 964, -344, -526, 1012, -758, -50, 822, -993, 437,
|
||||
-482, 1019, -649, -297, 979, -791, -100, 903, -903, 100, 791, -979, 297, 649, -1019, 482,
|
||||
482, -1019, 649, 297, -979, 791, 100, -903, 903, -100, -791, 979, -297, -649, 1019, -482,
|
||||
-526, 1022, -437, -609, 1012, -344, -687, 993, -248, -758, 964, -150, -822, 925, -50, -878,
|
||||
878, 50, -925, 822, 150, -964, 758, 248, -993, 687, 344, -1012, 609, 437, -1022, 526,
|
||||
-568, 1004, -199, -851, 851, 199, -1004, 568, 568, -1004, 199, 851, -851, -199, 1004, -568,
|
||||
-568, 1004, -199, -851, 851, 199, -1004, 568, 568, -1004, 199, 851, -851, -199, 1004, -568,
|
||||
-609, 964, 50, -993, 526, 687, -925, -150, 1012, -437, -758, 878, 248, -1022, 344, 822,
|
||||
-822, -344, 1022, -248, -878, 758, 437, -1012, 150, 925, -687, -526, 993, -50, -964, 609,
|
||||
-649, 903, 297, -1019, 100, 979, -482, -791, 791, 482, -979, -100, 1019, -297, -903, 649,
|
||||
649, -903, -297, 1019, -100, -979, 482, 791, -791, -482, 979, 100, -1019, 297, 903, -649,
|
||||
-687, 822, 526, -925, -344, 993, 150, -1022, 50, 1012, -248, -964, 437, 878, -609, -758,
|
||||
758, 609, -878, -437, 964, 248, -1012, -50, 1022, -150, -993, 344, 925, -526, -822, 687,
|
||||
-724, 724, 724, -724, -724, 724, 724, -724, -724, 724, 724, -724, -724, 724, 724, -724,
|
||||
-724, 724, 724, -724, -724, 724, 724, -724, -724, 724, 724, -724, -724, 724, 724, -724,
|
||||
-758, 609, 878, -437, -964, 248, 1012, -50, -1022, -150, 993, 344, -925, -526, 822, 687,
|
||||
-687, -822, 526, 925, -344, -993, 150, 1022, 50, -1012, -248, 964, 437, -878, -609, 758,
|
||||
-791, 482, 979, -100, -1019, -297, 903, 649, -649, -903, 297, 1019, 100, -979, -482, 791,
|
||||
791, -482, -979, 100, 1019, 297, -903, -649, 649, 903, -297, -1019, -100, 979, 482, -791,
|
||||
-822, 344, 1022, 248, -878, -758, 437, 1012, 150, -925, -687, 526, 993, 50, -964, -609,
|
||||
609, 964, -50, -993, -526, 687, 925, -150, -1012, -437, 758, 878, -248, -1022, -344, 822,
|
||||
-851, 199, 1004, 568, -568, -1004, -199, 851, 851, -199, -1004, -568, 568, 1004, 199, -851,
|
||||
-851, 199, 1004, 568, -568, -1004, -199, 851, 851, -199, -1004, -568, 568, 1004, 199, -851,
|
||||
-878, 50, 925, 822, -150, -964, -758, 248, 993, 687, -344, -1012, -609, 437, 1022, 526,
|
||||
-526, -1022, -437, 609, 1012, 344, -687, -993, -248, 758, 964, 150, -822, -925, -50, 878,
|
||||
-903, -100, 791, 979, 297, -649, -1019, -482, 482, 1019, 649, -297, -979, -791, 100, 903,
|
||||
903, 100, -791, -979, -297, 649, 1019, 482, -482, -1019, -649, 297, 979, 791, -100, -903,
|
||||
-925, -248, 609, 1022, 687, -150, -878, -964, -344, 526, 1012, 758, -50, -822, -993, -437,
|
||||
437, 993, 822, 50, -758, -1012, -526, 344, 964, 878, 150, -687, -1022, -609, 248, 925,
|
||||
-946, -391, 391, 946, 946, 391, -391, -946, -946, -391, 391, 946, 946, 391, -391, -946,
|
||||
-946, -391, 391, 946, 946, 391, -391, -946, -946, -391, 391, 946, 946, 391, -391, -946,
|
||||
-964, -526, 150, 758, 1022, 822, 248, -437, -925, -993, -609, 50, 687, 1012, 878, 344,
|
||||
-344, -878, -1012, -687, -50, 609, 993, 925, 437, -248, -822, -1022, -758, -150, 526, 964,
|
||||
-979, -649, -100, 482, 903, 1019, 791, 297, -297, -791, -1019, -903, -482, 100, 649, 979,
|
||||
979, 649, 100, -482, -903, -1019, -791, -297, 297, 791, 1019, 903, 482, -100, -649, -979,
|
||||
-993, -758, -344, 150, 609, 925, 1022, 878, 526, 50, -437, -822, -1012, -964, -687, -248,
|
||||
248, 687, 964, 1012, 822, 437, -50, -526, -878, -1022, -925, -609, -150, 344, 758, 993,
|
||||
-1004, -851, -568, -199, 199, 568, 851, 1004, 1004, 851, 568, 199, -199, -568, -851, -1004,
|
||||
-1004, -851, -568, -199, 199, 568, 851, 1004, 1004, 851, 568, 199, -199, -568, -851, -1004,
|
||||
-1012, -925, -758, -526, -248, 50, 344, 609, 822, 964, 1022, 993, 878, 687, 437, 150,
|
||||
-150, -437, -687, -878, -993, -1022, -964, -822, -609, -344, -50, 248, 526, 758, 925, 1012,
|
||||
-1019, -979, -903, -791, -649, -482, -297, -100, 100, 297, 482, 649, 791, 903, 979, 1019,
|
||||
1019, 979, 903, 791, 649, 482, 297, 100, -100, -297, -482, -649, -791, -903, -979, -1019,
|
||||
-1022, -1012, -993, -964, -925, -878, -822, -758, -687, -609, -526, -437, -344, -248, -150, -50,
|
||||
50, 150, 248, 344, 437, 526, 609, 687, 758, 822, 878, 925, 964, 993, 1012, 1022,
|
||||
-1024, -1024, -1024, -1024, -1024, -1024, -1024, -1024, -1024, -1024, -1024, -1024, -1024, -1024, -1024, -1024,
|
||||
-1024, -1024, -1024, -1024, -1024, -1024, -1024, -1024, -1024, -1024, -1024, -1024, -1024, -1024, -1024, -1024,
|
||||
-1022, -1012, -993, -964, -925, -878, -822, -758, -687, -609, -526, -437, -344, -248, -150, -50,
|
||||
50, 150, 248, 344, 437, 526, 609, 687, 758, 822, 878, 925, 964, 993, 1012, 1022,
|
||||
-1019, -979, -903, -791, -649, -482, -297, -100, 100, 297, 482, 649, 791, 903, 979, 1019,
|
||||
1019, 979, 903, 791, 649, 482, 297, 100, -100, -297, -482, -649, -791, -903, -979, -1019,
|
||||
-1012, -925, -758, -526, -248, 50, 344, 609, 822, 964, 1022, 993, 878, 687, 437, 150,
|
||||
-150, -437, -687, -878, -993, -1022, -964, -822, -609, -344, -50, 248, 526, 758, 925, 1012,
|
||||
-1004, -851, -568, -199, 199, 568, 851, 1004, 1004, 851, 568, 199, -199, -568, -851, -1004,
|
||||
-1004, -851, -568, -199, 199, 568, 851, 1004, 1004, 851, 568, 199, -199, -568, -851, -1004,
|
||||
-993, -758, -344, 150, 609, 925, 1022, 878, 526, 50, -437, -822, -1012, -964, -687, -248,
|
||||
248, 687, 964, 1012, 822, 437, -50, -526, -878, -1022, -925, -609, -150, 344, 758, 993,
|
||||
-979, -649, -100, 482, 903, 1019, 791, 297, -297, -791, -1019, -903, -482, 100, 649, 979,
|
||||
979, 649, 100, -482, -903, -1019, -791, -297, 297, 791, 1019, 903, 482, -100, -649, -979,
|
||||
-964, -526, 150, 758, 1022, 822, 248, -437, -925, -993, -609, 50, 687, 1012, 878, 344,
|
||||
-344, -878, -1012, -687, -50, 609, 993, 925, 437, -248, -822, -1022, -758, -150, 526, 964,
|
||||
-946, -391, 391, 946, 946, 391, -391, -946, -946, -391, 391, 946, 946, 391, -391, -946,
|
||||
-946, -391, 391, 946, 946, 391, -391, -946, -946, -391, 391, 946, 946, 391, -391, -946,
|
||||
-925, -248, 609, 1022, 687, -150, -878, -964, -344, 526, 1012, 758, -50, -822, -993, -437,
|
||||
437, 993, 822, 50, -758, -1012, -526, 344, 964, 878, 150, -687, -1022, -609, 248, 925,
|
||||
-903, -100, 791, 979, 297, -649, -1019, -482, 482, 1019, 649, -297, -979, -791, 100, 903,
|
||||
903, 100, -791, -979, -297, 649, 1019, 482, -482, -1019, -649, 297, 979, 791, -100, -903,
|
||||
-878, 50, 925, 822, -150, -964, -758, 248, 993, 687, -344, -1012, -609, 437, 1022, 526,
|
||||
-526, -1022, -437, 609, 1012, 344, -687, -993, -248, 758, 964, 150, -822, -925, -50, 878,
|
||||
-851, 199, 1004, 568, -568, -1004, -199, 851, 851, -199, -1004, -568, 568, 1004, 199, -851,
|
||||
-851, 199, 1004, 568, -568, -1004, -199, 851, 851, -199, -1004, -568, 568, 1004, 199, -851,
|
||||
-822, 344, 1022, 248, -878, -758, 437, 1012, 150, -925, -687, 526, 993, 50, -964, -609,
|
||||
609, 964, -50, -993, -526, 687, 925, -150, -1012, -437, 758, 878, -248, -1022, -344, 822,
|
||||
-791, 482, 979, -100, -1019, -297, 903, 649, -649, -903, 297, 1019, 100, -979, -482, 791,
|
||||
791, -482, -979, 100, 1019, 297, -903, -649, 649, 903, -297, -1019, -100, 979, 482, -791,
|
||||
-758, 609, 878, -437, -964, 248, 1012, -50, -1022, -150, 993, 344, -925, -526, 822, 687,
|
||||
-687, -822, 526, 925, -344, -993, 150, 1022, 50, -1012, -248, 964, 437, -878, -609, 758,
|
||||
};
|
||||
|
||||
static readonly short[] Coef2Table = {
|
||||
0, 0, -3, 7, 31, -80, -102, 585, 1172, 585, -102, -80, 31, 7, -3, 0,
|
||||
0, 0, -3, 8, 31, -86, -93, 614, 1171, 556, -111, -74, 32, 6, -3, 0,
|
||||
0, 0, -3, 9, 30, -91, -82, 643, 1169, 527, -119, -69, 32, 5, -3, 0,
|
||||
0, 0, -3, 10, 29, -97, -71, 671, 1166, 499, -126, -63, 32, 4, -3, 0,
|
||||
0, 0, -3, 11, 28, -102, -58, 700, 1161, 470, -132, -57, 32, 3, -2, 0,
|
||||
0, 0, -3, 12, 27, -108, -45, 728, 1154, 442, -138, -52, 32, 3, -2, 0,
|
||||
0, 0, -3, 13, 25, -113, -31, 756, 1147, 413, -142, -46, 32, 2, -2, 0,
|
||||
0, 0, -3, 14, 23, -118, -16, 783, 1138, 385, -146, -41, 31, 1, -2, 0,
|
||||
0, 0, -3, 15, 22, -123, -1, 810, 1127, 358, -149, -36, 31, 1, -2, 0,
|
||||
0, 0, -3, 16, 20, -128, 15, 836, 1115, 331, -152, -31, 30, 0, -2, 0,
|
||||
0, -1, -3, 17, 17, -132, 33, 862, 1102, 304, -154, -26, 29, 0, -2, 0,
|
||||
0, -1, -3, 18, 15, -136, 51, 887, 1088, 278, -155, -21, 29, 0, -2, 0,
|
||||
0, -1, -3, 20, 12, -140, 70, 911, 1073, 252, -155, -17, 28, 0, -2, 0,
|
||||
0, -1, -2, 21, 9, -144, 90, 934, 1056, 227, -155, -12, 27, -1, -1, 0,
|
||||
0, -1, -2, 22, 6, -147, 111, 957, 1038, 202, -154, -8, 26, -1, -1, 0,
|
||||
0, -1, -2, 23, 2, -149, 133, 979, 1020, 178, -153, -4, 25, -1, -1, 0,
|
||||
0, -1, -2, 24, 0, -151, 155, 1000, 1000, 155, -151, 0, 24, -2, -1, 0,
|
||||
0, -1, -1, 25, -4, -153, 178, 1020, 979, 133, -149, 2, 23, -2, -1, 0,
|
||||
0, -1, -1, 26, -8, -154, 202, 1038, 957, 111, -147, 6, 22, -2, -1, 0,
|
||||
0, -1, -1, 27, -12, -155, 227, 1056, 934, 90, -144, 9, 21, -2, -1, 0,
|
||||
0, -2, 0, 28, -17, -155, 252, 1073, 911, 70, -140, 12, 20, -3, -1, 0,
|
||||
0, -2, 0, 29, -21, -155, 278, 1088, 887, 51, -136, 15, 18, -3, -1, 0,
|
||||
0, -2, 0, 29, -26, -154, 304, 1102, 862, 33, -132, 17, 17, -3, -1, 0,
|
||||
0, -2, 0, 30, -31, -152, 331, 1115, 836, 15, -128, 20, 16, -3, 0, 0,
|
||||
0, -2, 1, 31, -36, -149, 358, 1127, 810, -1, -123, 22, 15, -3, 0, 0,
|
||||
0, -2, 1, 31, -41, -146, 385, 1138, 783, -16, -118, 23, 14, -3, 0, 0,
|
||||
0, -2, 2, 32, -46, -142, 413, 1147, 756, -31, -113, 25, 13, -3, 0, 0,
|
||||
0, -2, 3, 32, -52, -138, 442, 1154, 728, -45, -108, 27, 12, -3, 0, 0,
|
||||
0, -2, 3, 32, -57, -132, 470, 1161, 700, -58, -102, 28, 11, -3, 0, 0,
|
||||
0, -3, 4, 32, -63, -126, 499, 1166, 671, -71, -97, 29, 10, -3, 0, 0,
|
||||
0, -3, 5, 32, -69, -119, 527, 1169, 643, -82, -91, 30, 9, -3, 0, 0,
|
||||
0, -3, 6, 32, -74, -111, 556, 1171, 614, -93, -86, 31, 8, -3, 0, 0,
|
||||
};
|
||||
}
|
||||
}
|
@ -133,6 +133,13 @@ namespace GameRes.Formats.Purple
|
||||
int height = (int)m_info.Height;
|
||||
m_output = new byte[m_stride * height];
|
||||
|
||||
int x_blocks = width >> 4;
|
||||
if (0 != (width & 0xF))
|
||||
++x_blocks;
|
||||
int y_blocks = height >> 4;
|
||||
if (0 != (height & 0xF))
|
||||
++y_blocks;
|
||||
|
||||
int plane_size = width * height;
|
||||
byte[] plane = new byte[plane_size];
|
||||
|
||||
@ -157,13 +164,6 @@ namespace GameRes.Formats.Purple
|
||||
m_lzss_frame[i] = 0;
|
||||
LzssUnpack (bit_src, data_src, plane, channel_size);
|
||||
|
||||
int x_blocks = width >> 4;
|
||||
if (0 != (width & 0xF))
|
||||
++x_blocks;
|
||||
int y_blocks = height >> 4;
|
||||
if (0 != (height & 0xF))
|
||||
++y_blocks;
|
||||
|
||||
if (0 == y_blocks || 0 == x_blocks)
|
||||
continue;
|
||||
int plane_src = 0;
|
||||
|
297
ArcFormats/Cmvs/ImagePSB.cs
Normal file
297
ArcFormats/Cmvs/ImagePSB.cs
Normal file
@ -0,0 +1,297 @@
|
||||
//! \file ImagePSB.cs
|
||||
//! \date Thu Jun 23 20:16:31 2016
|
||||
//! \brief PVNS engine image format.
|
||||
//
|
||||
// Copyright (C) 2016 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 GameRes.Utility;
|
||||
|
||||
namespace GameRes.Formats.Pvns
|
||||
{
|
||||
internal class PsbMetaData : ImageMetaData
|
||||
{
|
||||
public int Method;
|
||||
public int TableOffset;
|
||||
public int DataOffset;
|
||||
}
|
||||
|
||||
[Export(typeof(ImageFormat))]
|
||||
public class PsbFormat : ImageFormat
|
||||
{
|
||||
public override string Tag { get { return "PSB"; } }
|
||||
public override string Description { get { return "PVNS engine image format"; } }
|
||||
public override uint Signature { get { return 0x50425350; } } // 'PSBP'
|
||||
|
||||
public override ImageMetaData ReadMetaData (Stream stream)
|
||||
{
|
||||
var header = new byte[0x14];
|
||||
if (header.Length != stream.Read (header, 0, header.Length))
|
||||
return null;
|
||||
stream.Seek (-0x13, SeekOrigin.End);
|
||||
var tail = new byte[0x13];
|
||||
stream.Read (tail, 0, tail.Length);
|
||||
for (int i = 4; i < 0x14; ++i)
|
||||
{
|
||||
header[i] ^= tail[tail.Length - 3 + (i & 1)];
|
||||
header[i] -= tail[i-4];
|
||||
}
|
||||
return new PsbMetaData
|
||||
{
|
||||
Width = LittleEndian.ToUInt16 (header, 0x0E),
|
||||
Height = LittleEndian.ToUInt16 (header, 0x10),
|
||||
BPP = LittleEndian.ToUInt16 (header, 0x12),
|
||||
Method = LittleEndian.ToUInt16 (header, 0x0C),
|
||||
TableOffset = LittleEndian.ToInt32 (header, 4),
|
||||
DataOffset = LittleEndian.ToInt32 (header, 8),
|
||||
};
|
||||
}
|
||||
|
||||
public override ImageData Read (Stream stream, ImageMetaData info)
|
||||
{
|
||||
var reader = new PsbReader (stream, (PsbMetaData)info);
|
||||
reader.Unpack();
|
||||
return ImageData.Create (info, reader.Format, null, reader.Data);
|
||||
}
|
||||
|
||||
public override void Write (Stream file, ImageData image)
|
||||
{
|
||||
throw new System.NotImplementedException ("PsbFormat.Write not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class PsbReader
|
||||
{
|
||||
byte[] m_input;
|
||||
byte[] m_output;
|
||||
PsbMetaData m_info;
|
||||
int m_width;
|
||||
int m_height;
|
||||
int m_channels;
|
||||
byte[] m_lzss_frame;
|
||||
|
||||
public byte[] Data { get { return m_output; } }
|
||||
public PixelFormat Format { get; private set; }
|
||||
|
||||
public PsbReader (Stream input, PsbMetaData info)
|
||||
{
|
||||
m_info = info;
|
||||
m_width = (int)m_info.Width;
|
||||
m_height = (int)m_info.Height;
|
||||
m_channels = m_info.BPP / 8;
|
||||
if (4 == m_channels)
|
||||
Format = PixelFormats.Bgra32;
|
||||
else if (3 == m_channels)
|
||||
Format = PixelFormats.Bgr24;
|
||||
else
|
||||
throw new InvalidFormatException();
|
||||
m_input = new byte[input.Length];
|
||||
input.Read (m_input, 0, m_input.Length);
|
||||
m_output = new byte[info.Width * info.Height * m_channels];
|
||||
m_lzss_frame = new byte[0x1000];
|
||||
}
|
||||
|
||||
public void Unpack ()
|
||||
{
|
||||
switch (m_info.Method)
|
||||
{
|
||||
case 2: UnpackV2(); break;
|
||||
case 3: UnpackV3(); break;
|
||||
default:
|
||||
throw new NotImplementedException (string.Format ("PSB images type {0} not implemented", m_info.Method));
|
||||
}
|
||||
}
|
||||
|
||||
void UnpackV2 ()
|
||||
{
|
||||
int plane_size = m_width * m_height;
|
||||
var plane = new byte[plane_size];
|
||||
|
||||
int src = m_info.TableOffset;
|
||||
var bits_table = new int[m_channels];
|
||||
int offset = m_info.TableOffset + 4 * m_channels;
|
||||
for (int i = 0; i < m_channels; ++i)
|
||||
{
|
||||
bits_table[i] = offset;
|
||||
offset += LittleEndian.ToInt32 (m_input, src);
|
||||
src += 4;
|
||||
}
|
||||
src = offset;
|
||||
offset += 4 * m_channels;
|
||||
var data_table = new int[m_channels];
|
||||
for (int i = 0; i < m_channels; ++i)
|
||||
{
|
||||
data_table[i] = offset;
|
||||
offset += LittleEndian.ToInt32 (m_input, src);
|
||||
src += 4;
|
||||
}
|
||||
for (int channel = 0; channel < m_channels; ++channel)
|
||||
{
|
||||
LzssUnpack (bits_table[channel], data_table[channel], plane, plane.Length);
|
||||
int dst = channel;
|
||||
byte pixel = 0;
|
||||
for (int i = 0; i < plane_size; ++i)
|
||||
{
|
||||
pixel += plane[i];
|
||||
m_output[dst] = pixel;
|
||||
dst += m_channels;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UnpackV3 ()
|
||||
{
|
||||
int stride = m_width * m_channels;
|
||||
var plane = new byte[m_width * m_height];
|
||||
int y_blocks = m_height >> 3;
|
||||
int x_blocks = m_width >> 3;
|
||||
if (0 != (m_width & 7))
|
||||
++x_blocks;
|
||||
if (0 != (m_height & 7))
|
||||
++y_blocks;
|
||||
|
||||
int src = m_info.TableOffset;
|
||||
var bits_table = new int[m_channels];
|
||||
int offset = m_info.TableOffset + 4 * m_channels;
|
||||
for (int i = 0; i < m_channels; ++i)
|
||||
{
|
||||
bits_table[i] = offset;
|
||||
offset += LittleEndian.ToInt32 (m_input, src);
|
||||
src += 4;
|
||||
}
|
||||
src = m_info.DataOffset;
|
||||
var data_offsets = new int[m_channels];
|
||||
offset = m_info.DataOffset + 4 * m_channels;
|
||||
for (int i = 0; i < m_channels; ++i)
|
||||
{
|
||||
data_offsets[i] = offset;
|
||||
offset += LittleEndian.ToInt32 (m_input, src);
|
||||
src += 4;
|
||||
}
|
||||
|
||||
for (int channel = 0; channel < m_channels; ++channel)
|
||||
{
|
||||
int dst = channel;
|
||||
|
||||
src = bits_table[channel];
|
||||
int bit_length = LittleEndian.ToInt32 (m_input, src);
|
||||
int bit_src = src + 12 + bit_length + LittleEndian.ToInt32 (m_input, src+4);
|
||||
int plane_size = LittleEndian.ToInt32 (m_input, src+8);
|
||||
|
||||
LzssUnpack (bit_src, data_offsets[channel], plane, plane_size);
|
||||
|
||||
int plane_src = 0;
|
||||
bit_src = src + 12;
|
||||
src = bit_src + bit_length;
|
||||
int bit_mask = 128;
|
||||
int y_pos = 0;
|
||||
for (int y = 0; y < y_blocks; ++y)
|
||||
{
|
||||
int block_height = Math.Min (8, m_height - y_pos);
|
||||
y_pos += 8;
|
||||
int x_pos = 0;
|
||||
int dst_origin = dst;
|
||||
for (int x = 0; x < x_blocks; ++x)
|
||||
{
|
||||
int block_width = Math.Min (8, m_width - x_pos);
|
||||
x_pos += 8;
|
||||
if (0 == bit_mask)
|
||||
{
|
||||
++bit_src;
|
||||
bit_mask = 128;
|
||||
}
|
||||
if (0 != (bit_mask & m_input[bit_src]))
|
||||
{
|
||||
byte b = m_input[src++];
|
||||
for (int j = 0; j < block_height; ++j)
|
||||
{
|
||||
int d = dst + stride * j;
|
||||
for (int i = 0; i < block_width; ++i)
|
||||
{
|
||||
m_output[d] = b;
|
||||
d += m_channels;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 0; j < block_height; ++j)
|
||||
{
|
||||
int d = dst + stride * j;
|
||||
for (int i = 0; i < block_width; ++i)
|
||||
{
|
||||
m_output[d] = plane[plane_src++];
|
||||
d += m_channels;
|
||||
}
|
||||
}
|
||||
}
|
||||
bit_mask >>= 1;
|
||||
dst += 8 * m_channels;
|
||||
}
|
||||
dst = dst_origin + 8 * stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LzssUnpack (int bit_src, int data_src, byte[] output, int output_size)
|
||||
{
|
||||
for (int i = 0; i < m_lzss_frame.Length; ++i)
|
||||
m_lzss_frame[i] = 0;
|
||||
int dst = 0;
|
||||
int bit_mask = 0x80;
|
||||
int frame_offset = 0xFEE;
|
||||
while (dst < output_size)
|
||||
{
|
||||
if (0 == bit_mask)
|
||||
{
|
||||
bit_mask = 0x80;
|
||||
++bit_src;
|
||||
}
|
||||
if (0 != (bit_mask & m_input[bit_src]))
|
||||
{
|
||||
int v = LittleEndian.ToUInt16 (m_input, data_src);
|
||||
data_src += 2;
|
||||
int count = (v & 0xF) + 3;
|
||||
int offset = v >> 4;
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
byte b = m_lzss_frame[(i + offset) & 0xFFF];
|
||||
output[dst++] = b;
|
||||
m_lzss_frame[frame_offset++] = b;
|
||||
frame_offset &= 0xFFF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
byte b = m_input[data_src++];
|
||||
output[dst++] = b;
|
||||
m_lzss_frame[frame_offset++] = b;
|
||||
frame_offset &= 0xFFF;
|
||||
}
|
||||
bit_mask >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -294,6 +294,7 @@ Imouto ~Mitsutsubo Complete Edition~<br/>
|
||||
</td></tr>
|
||||
<tr><td>*</td><td><tt>gra</tt><br/><tt>mas</tt><br/><tt>dif</tt></td><td>No</td></tr>
|
||||
<tr class="odd"><td>*.ald</td><td>-</td><td>No</td><td rowspan="4">Alice Soft</td><td rowspan="4">
|
||||
Daiteikoku<br/>
|
||||
Pastel Chime 3 Bind Seeker<br/>
|
||||
Shaman's Sanctuary -Miko no Seiiki-<br/>
|
||||
Tsuma Shibori<br/>
|
||||
@ -568,7 +569,7 @@ Konata yori Kanata made<br/>
|
||||
<tr><td>*.mcg</td><td><tt>MCG 2.00</tt></td><td>No</td></tr>
|
||||
<tr><td>*.acd</td><td><tt>ACD 1.00</tt></td><td>No</td></tr>
|
||||
<tr class="odd"><td>*.pk<br/>*.gpk<br/>*.tpk<br/>*.wpk<br/></td><td>-</td><td>No</td><td rowspan="2">U-Me Soft</td><td rowspan="2">
|
||||
Fetish 2: Omote no Kioku/Ura no Kioku<br/>
|
||||
Fetish Omote no Kioku/Ura no Kioku series<br>
|
||||
</td></tr>
|
||||
<tr class="odd"><td>*.grx</td><td><tt>GRX\x1a</tt><br/><tt>SGX\x1a</tt></td><td>No</td></tr>
|
||||
<tr><td>*.fpk</td><td><tt>MFWY</tt></td><td>No</td><td rowspan="2">Caligula</td><td rowspan="2">
|
||||
@ -789,6 +790,7 @@ Daisounan<br/>
|
||||
Dancing Crazies<br/>
|
||||
Level Justice<br/>
|
||||
Ouzoku<br/>
|
||||
Planet Dragon<br/>
|
||||
</td></tr>
|
||||
<tr><td>*.iph</td><td><tt>RIFF....IPH fmt</tt></td><td>No</td></tr>
|
||||
<tr><td>*.aog</td><td><tt>AoiOgg</tt></td><td>No</td></tr>
|
||||
@ -903,6 +905,11 @@ Majiyome<br/>
|
||||
Uchi no Tsuma Dakimasenka?<br/>
|
||||
</td></tr>
|
||||
<tr><td>*.um3</td><td><tt>\xB0\x98\x98\xAC</tt></td><td>No</td></tr>
|
||||
<tr class="odd"><td>*.pbz</td><td><tt>PBZ1</tt></td><td>No</td><td rowspan="3">PVNS</td><td rowspan="3">
|
||||
Karen<br/>
|
||||
</td></tr>
|
||||
<tr class="odd"><td>*.psb</td><td><tt>PSBP</tt></td><td>No</td></tr>
|
||||
<tr class="odd"><td>*.mk</td><td><tt>MKVS</tt></td><td>No</td></tr>
|
||||
</table>
|
||||
<p><a name="note-1" class="footnote">1</a> Non-encrypted only</p>
|
||||
</body>
|
||||
|
Loading…
Reference in New Issue
Block a user