(XP3): recognize filenames stored in hash table.

This commit is contained in:
morkt
2016-07-01 06:23:03 +04:00
parent 86fb8d4a0e
commit 69e29dc0f9

View File

@@ -148,6 +148,7 @@ namespace GameRes.Formats.KiriKiri
var crypt_algorithm = new Lazy<ICrypt> (QueryCryptAlgorithm); var crypt_algorithm = new Lazy<ICrypt> (QueryCryptAlgorithm);
var filename_map = new Dictionary<uint, string>();
var dir = new List<Entry>(); var dir = new List<Entry>();
dir_offset = 0; dir_offset = 0;
using (var header = new BinaryReader (header_stream, Encoding.Unicode)) using (var header = new BinaryReader (header_stream, Encoding.Unicode))
@@ -155,12 +156,22 @@ namespace GameRes.Formats.KiriKiri
while (-1 != header.PeekChar()) while (-1 != header.PeekChar())
{ {
uint entry_signature = header.ReadUInt32(); uint entry_signature = header.ReadUInt32();
if (0x656c6946 != entry_signature) // "File"
{
break;
}
long entry_size = header.ReadInt64(); long entry_size = header.ReadInt64();
if (entry_size < 0)
return null;
dir_offset += 12 + entry_size; dir_offset += 12 + entry_size;
if (0x6E666E68 == entry_signature) // "hnfn"
{
uint hash = header.ReadUInt32();
int name_size = header.ReadInt16();
entry_size -= 6;
if (name_size * 2 <= entry_size)
{
filename_map[hash] = new string (header.ReadChars (name_size));
}
}
else if (0x656C6946 == entry_signature) // "File"
{
var entry = new Xp3Entry(); var entry = new Xp3Entry();
while (entry_size > 0) while (entry_size > 0)
{ {
@@ -174,7 +185,6 @@ namespace GameRes.Formats.KiriKiri
switch (section) switch (section)
{ {
case 0x6f666e69: // "info" case 0x6f666e69: // "info"
{
if (entry.Size != 0 || !string.IsNullOrEmpty (entry.Name)) if (entry.Size != 0 || !string.IsNullOrEmpty (entry.Name))
{ {
goto NextEntry; // ambiguous entry, ignore goto NextEntry; // ambiguous entry, ignore
@@ -200,19 +210,21 @@ namespace GameRes.Formats.KiriKiri
else else
entry.Cipher = NoCryptAlgorithm; entry.Cipher = NoCryptAlgorithm;
var name = new string (header.ReadChars (name_size)); string name = null;
if (0 == filename_map.Count || !filename_map.TryGetValue (entry.Hash, out name))
{
name = new string (header.ReadChars (name_size));
if (entry.Cipher.ObfuscatedIndex && ObfuscatedPathRe.IsMatch (name)) if (entry.Cipher.ObfuscatedIndex && ObfuscatedPathRe.IsMatch (name))
{ {
goto NextEntry; goto NextEntry;
} }
}
entry.Name = name; entry.Name = name;
entry.Type = FormatCatalog.Instance.GetTypeFromName (entry.Name); entry.Type = FormatCatalog.Instance.GetTypeFromName (entry.Name);
entry.IsEncrypted = !(entry.Cipher is NoCrypt) entry.IsEncrypted = !(entry.Cipher is NoCrypt)
&& !(entry.Cipher.StratupTjsNotEncrypted && "startup.tjs" == name); && !(entry.Cipher.StratupTjsNotEncrypted && "startup.tjs" == name);
break; break;
}
case 0x6d676573: // "segm" case 0x6d676573: // "segm"
{
int segment_count = (int)(section_size / 0x1c); int segment_count = (int)(section_size / 0x1c);
if (segment_count > 0) if (segment_count > 0)
{ {
@@ -237,7 +249,6 @@ namespace GameRes.Formats.KiriKiri
entry.Offset = entry.Segments.First().Offset; entry.Offset = entry.Segments.First().Offset;
} }
break; break;
}
case 0x726c6461: // "adlr" case 0x726c6461: // "adlr"
if (4 == section_size) if (4 == section_size)
entry.Hash = header.ReadUInt32(); entry.Hash = header.ReadUInt32();
@@ -256,10 +267,13 @@ namespace GameRes.Formats.KiriKiri
} }
dir.Add (entry); dir.Add (entry);
} }
}
NextEntry: NextEntry:
header.BaseStream.Position = dir_offset; header.BaseStream.Position = dir_offset;
} }
} }
if (0 == dir.Count)
return null;
var arc = new ArcFile (file, this, dir); var arc = new ArcFile (file, this, dir);
try try
{ {