mirror of
https://github.com/crskycode/GARbro.git
synced 2025-01-12 04:49:32 +08:00
(XP3): recognize filenames stored in hash table.
This commit is contained in:
parent
86fb8d4a0e
commit
69e29dc0f9
@ -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,26 +156,35 @@ 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;
|
||||||
var entry = new Xp3Entry();
|
if (0x6E666E68 == entry_signature) // "hnfn"
|
||||||
while (entry_size > 0)
|
|
||||||
{
|
{
|
||||||
uint section = header.ReadUInt32();
|
uint hash = header.ReadUInt32();
|
||||||
long section_size = header.ReadInt64();
|
int name_size = header.ReadInt16();
|
||||||
entry_size -= 12;
|
entry_size -= 6;
|
||||||
if (section_size > entry_size)
|
if (name_size * 2 <= entry_size)
|
||||||
break;
|
|
||||||
entry_size -= section_size;
|
|
||||||
long next_section_pos = header.BaseStream.Position + section_size;
|
|
||||||
switch (section)
|
|
||||||
{
|
{
|
||||||
case 0x6f666e69: // "info"
|
filename_map[hash] = new string (header.ReadChars (name_size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (0x656C6946 == entry_signature) // "File"
|
||||||
|
{
|
||||||
|
var entry = new Xp3Entry();
|
||||||
|
while (entry_size > 0)
|
||||||
|
{
|
||||||
|
uint section = header.ReadUInt32();
|
||||||
|
long section_size = header.ReadInt64();
|
||||||
|
entry_size -= 12;
|
||||||
|
if (section_size > entry_size)
|
||||||
|
break;
|
||||||
|
entry_size -= section_size;
|
||||||
|
long next_section_pos = header.BaseStream.Position + section_size;
|
||||||
|
switch (section)
|
||||||
{
|
{
|
||||||
|
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 (entry.Cipher.ObfuscatedIndex && ObfuscatedPathRe.IsMatch (name))
|
if (0 == filename_map.Count || !filename_map.TryGetValue (entry.Hash, out name))
|
||||||
{
|
{
|
||||||
goto NextEntry;
|
name = new string (header.ReadChars (name_size));
|
||||||
|
if (entry.Cipher.ObfuscatedIndex && ObfuscatedPathRe.IsMatch (name))
|
||||||
|
{
|
||||||
|
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,29 +249,31 @@ 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();
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
default: // unknown section
|
default: // unknown section
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
header.BaseStream.Position = next_section_pos;
|
||||||
}
|
}
|
||||||
header.BaseStream.Position = next_section_pos;
|
if (!string.IsNullOrEmpty (entry.Name) && entry.Segments.Any())
|
||||||
}
|
|
||||||
if (!string.IsNullOrEmpty (entry.Name) && entry.Segments.Any())
|
|
||||||
{
|
|
||||||
if (entry.Cipher.ObfuscatedIndex)
|
|
||||||
{
|
{
|
||||||
DeobfuscateEntry (entry);
|
if (entry.Cipher.ObfuscatedIndex)
|
||||||
|
{
|
||||||
|
DeobfuscateEntry (entry);
|
||||||
|
}
|
||||||
|
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
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user