mirror of
https://github.com/crskycode/GARbro.git
synced 2025-01-11 20:39:29 +08:00
(YpfOpener): support YSTB scripts decryption.
This commit is contained in:
parent
382b01cc9a
commit
d2e7882e6d
@ -57,6 +57,7 @@ namespace GameRes.Formats.YuRis
|
||||
public byte Key;
|
||||
public bool GuessKey;
|
||||
public uint ExtraHeaderSize;
|
||||
public uint ScriptKey;
|
||||
|
||||
public YpfScheme () { }
|
||||
|
||||
@ -76,6 +77,17 @@ namespace GameRes.Formats.YuRis
|
||||
}
|
||||
}
|
||||
|
||||
public class YpfArchive : ArcFile
|
||||
{
|
||||
public uint ScriptKey;
|
||||
|
||||
public YpfArchive (ArcView arc, ArchiveFormat impl, ICollection<Entry> dir, uint script_key)
|
||||
: base (arc, impl, dir)
|
||||
{
|
||||
ScriptKey = script_key;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class YuRisScheme : ResourceScheme
|
||||
{
|
||||
@ -115,17 +127,31 @@ namespace GameRes.Formats.YuRis
|
||||
if (null == dir || 0 == dir.Count)
|
||||
return null;
|
||||
|
||||
return new ArcFile (file, this, dir);
|
||||
if (scheme.ScriptKey != 0)
|
||||
return new YpfArchive (file, this, dir, scheme.ScriptKey);
|
||||
else
|
||||
return new ArcFile (file, this, dir);
|
||||
}
|
||||
|
||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
||||
{
|
||||
var input = arc.File.CreateStream (entry.Offset, entry.Size);
|
||||
var packed_entry = entry as PackedEntry;
|
||||
if (null == packed_entry || !packed_entry.IsPacked)
|
||||
var ypf = arc as YpfArchive;
|
||||
Stream input = arc.File.CreateStream (entry.Offset, entry.Size);
|
||||
if (null != packed_entry && packed_entry.IsPacked)
|
||||
input = new ZLibStream (input, CompressionMode.Decompress);
|
||||
uint unpacked_size = null == packed_entry ? entry.Size : packed_entry.UnpackedSize;
|
||||
if (null == ypf || 0 == ypf.ScriptKey || unpacked_size <= 0x20
|
||||
|| !entry.Name.EndsWith (".ybn", StringComparison.InvariantCultureIgnoreCase))
|
||||
return input;
|
||||
else
|
||||
return new ZLibStream (input, CompressionMode.Decompress);
|
||||
using (input)
|
||||
{
|
||||
var data = new byte[unpacked_size];
|
||||
input.Read (data, 0, data.Length);
|
||||
if (Binary.AsciiEqual (data, 0, "YSTB"))
|
||||
DecryptYstb (data, ypf.ScriptKey);
|
||||
return new MemoryStream (data);
|
||||
}
|
||||
}
|
||||
|
||||
public override ResourceOptions GetDefaultOptions ()
|
||||
@ -318,6 +344,57 @@ namespace GameRes.Formats.YuRis
|
||||
return SwapTable00;
|
||||
}
|
||||
|
||||
unsafe void DecryptYstb (byte[] data, uint key)
|
||||
{
|
||||
if (data.Length <= 0x20)
|
||||
return;
|
||||
fixed (byte* raw = data)
|
||||
{
|
||||
uint* header = (uint*)raw;
|
||||
uint version = header[1];
|
||||
int first_item, last_item;
|
||||
if (version >= 0x22A)
|
||||
{
|
||||
first_item = 3;
|
||||
last_item = 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
first_item = 2;
|
||||
last_item = 4;
|
||||
}
|
||||
uint total = 0x20;
|
||||
// check sizes
|
||||
for (int i = first_item; i < last_item; ++i)
|
||||
{
|
||||
if (header[i] >= data.Length)
|
||||
return;
|
||||
total += header[i];
|
||||
if (total > data.Length)
|
||||
return;
|
||||
}
|
||||
if (total != data.Length)
|
||||
return;
|
||||
byte* data8 = raw+0x20;
|
||||
for (int i = first_item; i < last_item; ++i)
|
||||
{
|
||||
uint size = header[i];
|
||||
if (0 == size)
|
||||
continue;
|
||||
uint* data32 = (uint*)data8;
|
||||
for (uint j = size / 4; j != 0; --j)
|
||||
*data32++ ^= key;
|
||||
data8 = (byte*)data32;
|
||||
uint k = key;
|
||||
for (uint j = size & 3; j != 0; --j)
|
||||
{
|
||||
*data8++ ^= (byte)k;
|
||||
k >>= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class Parser
|
||||
{
|
||||
ArcView m_file;
|
||||
|
Loading…
x
Reference in New Issue
Block a user