(Seraph): try to read index from ScnPac file.

This commit is contained in:
morkt 2019-01-11 18:12:20 +04:00
parent 18078d858d
commit a2331dfec7

View File

@ -91,7 +91,7 @@ namespace GameRes.Formats.Seraphim
return null; return null;
foreach (var scheme in KnownSchemes.Values.Where (s => s.IndexOffset < file.MaxOffset)) foreach (var scheme in KnownSchemes.Values.Where (s => s.IndexOffset < file.MaxOffset))
{ {
var dir = ReadIndex (file, scheme); var dir = ReadIndex (file, scheme.IndexOffset, file.MaxOffset);
if (dir != null) if (dir != null)
{ {
if (scheme.EventMap != null) if (scheme.EventMap != null)
@ -100,19 +100,29 @@ namespace GameRes.Formats.Seraphim
return new ArcFile (file, this, dir); return new ArcFile (file, this, dir);
} }
} }
var scnpac_name = VFS.ChangeFileName (file.Name, "ScnPac.dat");
if (!VFS.FileExists (scnpac_name))
return null;
using (var scnpac = VFS.OpenView (scnpac_name))
{
uint first_offset = scnpac.View.ReadUInt32 (4);
uint index_offset = scnpac.View.ReadUInt32 (first_offset-4);
var dir = ReadIndex (scnpac, index_offset, file.MaxOffset);
if (dir != null)
return new ArcFile (file, this, dir);
}
return null; return null;
} }
// 3 @ ScnPac.Dat : FF 18 05 XX XX XX XX // 3 @ ScnPac.Dat : FF 18 05 XX XX XX XX
// FF 16 05 XX XX XX XX // FF 16 05 XX XX XX XX
List<Entry> ReadIndex (ArcView file, ArchPacScheme scheme) List<Entry> ReadIndex (ArcView file, long index_offset, long max_offset)
{ {
long index_offset = scheme.IndexOffset;
int base_count = file.View.ReadInt32 (index_offset); int base_count = file.View.ReadInt32 (index_offset);
int file_count = file.View.ReadInt32 (index_offset + 4); int file_count = file.View.ReadInt32 (index_offset + 4);
index_offset += 8; index_offset += 8;
if (base_count <= 0 || base_count > 0x100 || !IsSaneCount (file_count)) if (base_count <= 0 || base_count > 0x40 || !IsSaneCount (file_count))
return null; return null;
var base_offsets = new List<Tuple<uint, int>> (base_count); var base_offsets = new List<Tuple<uint, int>> (base_count);
int total_count = 0; int total_count = 0;
@ -120,7 +130,7 @@ namespace GameRes.Formats.Seraphim
{ {
uint offset = file.View.ReadUInt32 (index_offset); uint offset = file.View.ReadUInt32 (index_offset);
int count = file.View.ReadInt32 (index_offset+4); int count = file.View.ReadInt32 (index_offset+4);
if (count <= 0 || count > file_count || offset > file.MaxOffset) if (count <= 0 || count > file_count || offset > max_offset)
return null; return null;
total_count += count; total_count += count;
if (total_count > file_count) if (total_count > file_count)
@ -150,7 +160,7 @@ namespace GameRes.Formats.Seraphim
return null; return null;
entry.Size = (uint)(next_offset - entry.Offset); entry.Size = (uint)(next_offset - entry.Offset);
entry.Offset += base_offsets[j].Item1; entry.Offset += base_offsets[j].Item1;
if (!entry.CheckPlacement (file.MaxOffset)) if (!entry.CheckPlacement (max_offset))
return null; return null;
if (entry.Size > 0) if (entry.Size > 0)
dir.Add (entry); dir.Add (entry);