From 5d94af9cfa18cc237a2352bb924a63169778093e Mon Sep 17 00:00:00 2001 From: morkt Date: Sun, 27 Jan 2019 02:28:21 +0400 Subject: [PATCH] (PAC/LUNA): support 64-bit offsets. --- ArcFormats/LunaSoft/ArcPAC.cs | 41 ++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/ArcFormats/LunaSoft/ArcPAC.cs b/ArcFormats/LunaSoft/ArcPAC.cs index bfad8871..e6bc68ed 100644 --- a/ArcFormats/LunaSoft/ArcPAC.cs +++ b/ArcFormats/LunaSoft/ArcPAC.cs @@ -45,23 +45,44 @@ namespace GameRes.Formats.LunaSoft if (!IsSaneCount (count)) return null; long base_offset = file.View.ReadUInt32 (8); - - uint current_offset = 0x10; var dir = new List (count); + if (!ReadIndex (file, dir, count, base_offset) && + !ReadIndex (file, dir, count, base_offset, true)) + return null; + return new ArcFile (file, this, dir); + } + + bool ReadIndex (ArcView file, List dir, int count, long base_offset, bool long_offsets = false) + { + Func read_offset; + uint size_pos; + if (long_offsets) + { + read_offset = idx_off => file.View.ReadInt64 (idx_off); + size_pos = 0x108; + } + else + { + read_offset = idx_off => file.View.ReadUInt32 (idx_off); + size_pos = 0x104; + } + dir.Clear(); + uint current_offset = 0x10; for (int i = 0; i < count; ++i) { - uint name_length = file.View.ReadUInt32 (current_offset+0x108); + uint name_length = file.View.ReadUInt32 (current_offset+size_pos+4); + if (name_length > 0x100 || 0 == name_length) + return false; var name = file.View.ReadString (current_offset, name_length); - var entry = FormatCatalog.Instance.Create (name); - current_offset += 0x100; - entry.Offset = base_offset + file.View.ReadUInt32 (current_offset); - entry.Size = file.View.ReadUInt32 (current_offset+4); + var entry = Create (name); + entry.Offset = base_offset + read_offset (current_offset+0x100); + entry.Size = file.View.ReadUInt32 (current_offset+size_pos); if (!entry.CheckPlacement (file.MaxOffset)) - return null; + return false; dir.Add (entry); - current_offset += 0xC; + current_offset += size_pos+8; } - return new ArcFile (file, this, dir); + return true; } } }