(KiriKiri.ChinReactionCrypt): modification.

This commit is contained in:
morkt 2016-09-11 23:45:07 +04:00
parent bc82a2bdfb
commit 72f6d329f1

View File

@ -46,6 +46,17 @@ namespace GameRes.Formats.KiriKiri
[Serializable] [Serializable]
public class ChainReactionCrypt : ICrypt public class ChainReactionCrypt : ICrypt
{ {
readonly string m_list_bin;
public ChainReactionCrypt () : this ("plugin/list.bin")
{
}
public ChainReactionCrypt (string list_file)
{
m_list_bin = list_file;
}
public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count) public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
{ {
uint limit = GetEncryptionLimit (entry); uint limit = GetEncryptionLimit (entry);
@ -64,7 +75,7 @@ namespace GameRes.Formats.KiriKiri
// Decrypt (entry, offset, values, pos, count); // Decrypt (entry, offset, values, pos, count);
} }
uint GetEncryptionLimit (Xp3Entry entry) internal uint GetEncryptionLimit (Xp3Entry entry)
{ {
uint limit; uint limit;
if (EncryptionThresholdMap != null && EncryptionThresholdMap.TryGetValue (entry.Hash, out limit)) if (EncryptionThresholdMap != null && EncryptionThresholdMap.TryGetValue (entry.Hash, out limit))
@ -78,19 +89,19 @@ namespace GameRes.Formats.KiriKiri
public override void Init (ArcFile arc) public override void Init (ArcFile arc)
{ {
var list_bin = arc.Dir.FirstOrDefault (e => e.Name == "plugin/list.bin") as Xp3Entry; var bin = ReadListBin (arc);
if (null == list_bin || list_bin.UnpackedSize <= 0x30) if (null == bin || bin.Length <= 0x30)
return; return;
var bin = new byte[list_bin.UnpackedSize];
using (var input = arc.OpenEntry (list_bin))
input.Read (bin, 0, bin.Length);
if (!Binary.AsciiEqual (bin, "\"\x0D\x0A"))
{
for (int i = 0; i < 3; ++i) for (int i = 0; i < 3; ++i)
{ {
bin = DecodeListBin (bin); bin = DecodeListBin (bin);
if (null == bin) if (null == bin)
return; return;
} }
}
if (null == EncryptionThresholdMap) if (null == EncryptionThresholdMap)
EncryptionThresholdMap = new Dictionary<uint, uint>(); EncryptionThresholdMap = new Dictionary<uint, uint>();
else else
@ -99,6 +110,17 @@ namespace GameRes.Formats.KiriKiri
ParseListBin (bin); ParseListBin (bin);
} }
internal byte[] ReadListBin (ArcFile arc)
{
var list_bin = arc.Dir.FirstOrDefault (e => e.Name == m_list_bin) as Xp3Entry;
if (null == list_bin)
return null;
var bin = new byte[list_bin.UnpackedSize];
using (var input = arc.OpenEntry (list_bin))
input.Read (bin, 0, bin.Length);
return bin;
}
void ParseListBin (byte[] data) void ParseListBin (byte[] data)
{ {
using (var mem = new MemoryStream (data)) using (var mem = new MemoryStream (data))
@ -203,4 +225,30 @@ namespace GameRes.Formats.KiriKiri
} }
} }
} }
[Serializable]
public class HachukanoCrypt : ChainReactionCrypt
{
public HachukanoCrypt () : base ("plugins/list.txt")
{
StartupTjsNotEncrypted = true;
}
public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
{
uint limit = GetEncryptionLimit (entry);
switch (limit)
{
case 0: return;
case 1: limit = 0x100; break;
case 2: limit = 0x200; break;
case 3: limit = entry.Size; break;
}
uint key = entry.Hash;
for (int i = 0; i < count && offset < limit; ++i, ++offset)
{
values[pos+i] ^= (byte)(offset ^ (key >> (((int)offset & 3) << 3)));
}
}
}
} }