mirror of
https://github.com/crskycode/GARbro.git
synced 2024-11-23 21:55:34 +08:00
(XP3): adjusted reading filenames from archive index.
some modified Kirikiri builds don't store filenames within archives at all, only filename hashes.
This commit is contained in:
parent
37a038b090
commit
5bd63c01cb
@ -184,17 +184,16 @@ namespace GameRes.Formats.KiriKiri
|
||||
entry.Size = (uint)packed_size;
|
||||
entry.UnpackedSize = (uint)file_size;
|
||||
|
||||
int name_size = header.ReadInt16();
|
||||
if (name_size > 0x100 || name_size <= 0)
|
||||
{
|
||||
goto NextEntry;
|
||||
}
|
||||
if (entry.IsEncrypted || ForceEncryptionQuery)
|
||||
entry.Cipher = crypt_algorithm.Value;
|
||||
else
|
||||
entry.Cipher = NoCryptAlgorithm;
|
||||
|
||||
var name = new string (header.ReadChars (name_size));
|
||||
var name = entry.Cipher.ReadName (header);
|
||||
if (null == name)
|
||||
{
|
||||
goto NextEntry;
|
||||
}
|
||||
if (entry.Cipher.ObfuscatedIndex && ObfuscatedPathRe.IsMatch (name))
|
||||
{
|
||||
goto NextEntry;
|
||||
|
@ -71,6 +71,18 @@ namespace GameRes.Formats.KiriKiri
|
||||
public virtual void Init (ArcFile arc)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read entry name from archive index.
|
||||
/// </summary>
|
||||
public virtual string ReadName (BinaryReader header)
|
||||
{
|
||||
int name_size = header.ReadInt16();
|
||||
if (name_size > 0 && name_size <= 0x100)
|
||||
return new string (header.ReadChars (name_size));
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
@ -1021,4 +1033,96 @@ namespace GameRes.Formats.KiriKiri
|
||||
Decrypt (entry, offset, buffer, pos, count);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class RhapsodyCrypt : ICrypt
|
||||
{
|
||||
public string FileListName { get; set; }
|
||||
|
||||
public override void Decrypt (Xp3Entry entry, long offset, byte[] buffer, int pos, int count)
|
||||
{
|
||||
var key = new byte[12];
|
||||
LittleEndian.Pack (entry.Hash, key, 0);
|
||||
LittleEndian.Pack (0x6E1DA9B2u, key, 4);
|
||||
LittleEndian.Pack (0x0040C800u, key, 8);
|
||||
int k = (int)(offset % 12);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
buffer[pos+i] ^= key[k++];
|
||||
if (12 == k)
|
||||
k = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Encrypt (Xp3Entry entry, long offset, byte[] buffer, int pos, int count)
|
||||
{
|
||||
Decrypt (entry, offset, buffer, pos, count);
|
||||
}
|
||||
|
||||
public override string ReadName (BinaryReader header)
|
||||
{
|
||||
if (null == KnownNames)
|
||||
ReadNames();
|
||||
uint key = header.ReadUInt32();
|
||||
uint name_hash = header.ReadUInt32() ^ key;
|
||||
string name;
|
||||
if (KnownNames.TryGetValue (name_hash, out name))
|
||||
return name;
|
||||
uint ext_hash = header.ReadUInt32() ^ key;
|
||||
name = name_hash.ToString ("X8");
|
||||
switch (ext_hash)
|
||||
{
|
||||
case 0x01854675: name += ".png"; break; // GetNameHash (".png")
|
||||
case 0x03D435DE: name += ".map"; break; // GetNameHash (".map")
|
||||
case 0x2D1F13E0: name += ".asd"; break; // GetNameHash (".asd")
|
||||
case 0x482F4319: name += ".tjs"; break; // GetNameHash (".tjs")
|
||||
case 0xB01C48CA: name += ".ks"; break; // GetNameHash (".ks")
|
||||
case 0xC0F7DFB2: name += ".wav"; break; // GetNameHash (".wav")
|
||||
case 0xE3A31D19: name += ".jpg"; break; // GetNameHash (".jpg")
|
||||
case 0xE7F3FEEB: name += ".ogg"; break; // GetNameHash (".ogg")
|
||||
default: name += ext_hash.ToString ("X8"); break;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
static uint GetNameHash (string name)
|
||||
{
|
||||
uint hash = 0;
|
||||
for (int i = 0; i < name.Length; ++i)
|
||||
{
|
||||
int c = char.ToLowerInvariant (name[i]);
|
||||
hash = 0x1000193u * hash ^ (byte)c;
|
||||
hash = 0x1000193u * hash ^ (byte)(c >> 8);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
void ReadNames ()
|
||||
{
|
||||
var dir = FormatCatalog.Instance.DataDirectory;
|
||||
var names_file = Path.Combine (dir, FileListName);
|
||||
var names = new Dictionary<uint, string>();
|
||||
try
|
||||
{
|
||||
using (var reader = new StreamReader (names_file))
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
var name = reader.ReadLine();
|
||||
if (null == name)
|
||||
break;
|
||||
names[GetNameHash (name)] = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception X)
|
||||
{
|
||||
System.Diagnostics.Trace.WriteLine (X.Message, "[RhapsodyCrypt]");
|
||||
}
|
||||
KnownNames = names;
|
||||
}
|
||||
|
||||
[NonSerialized]
|
||||
Dictionary<uint, string> KnownNames = null;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user