mirror of
https://github.com/crskycode/GARbro.git
synced 2025-01-11 12:39:16 +08:00
(BURIKO): decode BSE-encrypted entries.
This commit is contained in:
parent
5378499a8a
commit
d6908c9e1e
@ -135,11 +135,57 @@ namespace GameRes.Formats.BGI
|
||||
var res = AutoEntry.DetectFileType (signature);
|
||||
if (res != null)
|
||||
entry.Type = res.Type;
|
||||
else if (file.View.AsciiEqual (entry.Offset, "BSE 1."))
|
||||
entry.Type = "image";
|
||||
else if (file.View.AsciiEqual (entry.Offset+4, "bw "))
|
||||
entry.Type = "audio";
|
||||
}
|
||||
return new ArcFile (file, this, dir);
|
||||
}
|
||||
|
||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
||||
{
|
||||
if (entry.Size < 0x50 || !arc.File.View.AsciiEqual (entry.Offset, "BSE 1."))
|
||||
return base.OpenEntry (arc, entry);
|
||||
int version = arc.File.View.ReadUInt16 (entry.Offset+8);
|
||||
if (version != 0x100 && version != 0x101)
|
||||
return base.OpenEntry (arc, entry);
|
||||
|
||||
ushort checksum = arc.File.View.ReadUInt16 (entry.Offset+0xA);
|
||||
uint key = arc.File.View.ReadUInt32 (entry.Offset+0xC);
|
||||
var header = arc.File.View.ReadBytes (entry.Offset+0x10, 0x40);
|
||||
if (0x101 == version)
|
||||
DecryptBse (header, new BseGenerator101 (key));
|
||||
else
|
||||
DecryptBse (header, new BseGenerator100 (key));
|
||||
var body = arc.File.CreateStream (entry.Offset+0x50, entry.Size-0x50);
|
||||
return new PrefixStream (header, body);
|
||||
}
|
||||
|
||||
void DecryptBse (byte[] data, IBseGenerator decoder)
|
||||
{
|
||||
var decoded = new bool[0x40];
|
||||
for (int i = 0; i < decoded.Length; ++i)
|
||||
{
|
||||
int dst = decoder.NextKey() & 0x3F;
|
||||
while (decoded[dst])
|
||||
{
|
||||
dst = (dst + 1) & 0x3F;
|
||||
}
|
||||
int shift = decoder.NextKey() & 7;
|
||||
bool right_shift = (decoder.NextKey() & 1) == 0;
|
||||
byte symbol = (byte)(data[dst] - decoder.NextKey());
|
||||
if (right_shift)
|
||||
{
|
||||
data[dst] = Binary.RotByteR (symbol, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
data[dst] = Binary.RotByteL (symbol, shift);
|
||||
}
|
||||
decoded[dst] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class BgiDecoderBase : MsbBitStream
|
||||
@ -295,4 +341,43 @@ namespace GameRes.Formats.BGI
|
||||
return dst_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
internal interface IBseGenerator
|
||||
{
|
||||
int NextKey ();
|
||||
}
|
||||
|
||||
internal class BseGenerator100 : IBseGenerator
|
||||
{
|
||||
int m_key;
|
||||
|
||||
public BseGenerator100 (uint key)
|
||||
{
|
||||
m_key = (int)key;
|
||||
}
|
||||
|
||||
public int NextKey ()
|
||||
{
|
||||
uint v = (uint)(((m_key * 257 >> 8) + m_key * 97 + 23) ^ 0xA6CD9B75);
|
||||
m_key = (int)Binary.RotR (v, 16);
|
||||
return m_key;
|
||||
}
|
||||
}
|
||||
|
||||
internal class BseGenerator101 : IBseGenerator
|
||||
{
|
||||
int m_key;
|
||||
|
||||
public BseGenerator101 (uint key)
|
||||
{
|
||||
m_key = (int)key;
|
||||
}
|
||||
|
||||
public int NextKey ()
|
||||
{
|
||||
uint v = (uint)((m_key * 127 >> 7) + m_key * 83 + 53) ^ 0xB97A7E5C;
|
||||
m_key = (int)Binary.RotR (v, 16);
|
||||
return m_key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user