From 94dac729b6b9e73c7618c9a04097c6848226bf68 Mon Sep 17 00:00:00 2001 From: morkt Date: Sun, 9 Sep 2018 17:27:38 +0400 Subject: [PATCH] (Seraph): alternative archives layout. --- ArcFormats/Seraphim/ArcSCN.cs | 13 +++++++--- ArcFormats/Seraphim/ArcSeraph.cs | 16 +++++++++---- ArcFormats/Seraphim/ArcVoice.cs | 41 +++++++++++++++++++++++++++----- 3 files changed, 57 insertions(+), 13 deletions(-) diff --git a/ArcFormats/Seraphim/ArcSCN.cs b/ArcFormats/Seraphim/ArcSCN.cs index 7f9399be..37f62cf7 100644 --- a/ArcFormats/Seraphim/ArcSCN.cs +++ b/ArcFormats/Seraphim/ArcSCN.cs @@ -23,10 +23,10 @@ // IN THE SOFTWARE. // -using System; using System.Collections.Generic; using System.ComponentModel.Composition; using System.IO; +using GameRes.Compression; using GameRes.Utility; namespace GameRes.Formats.Seraphim @@ -79,8 +79,15 @@ namespace GameRes.Formats.Seraphim { if (0 == entry.Size) return Stream.Null; - var input = arc.File.CreateStream (entry.Offset, entry.Size); - if (0 == input.Signature || 0 != (input.Signature & 0xFF000000)) + uint signature = arc.File.View.ReadUInt32 (entry.Offset); + ArcViewStream input; + if (1 == signature && 0x78 == arc.File.View.ReadByte (entry.Offset+4)) + { + input = arc.File.CreateStream (entry.Offset+4, entry.Size-4); + return new ZLibStream (input, CompressionMode.Decompress); + } + input = arc.File.CreateStream (entry.Offset, entry.Size); + if (signature < 4 || 0 != (signature & 0xFF000000)) return input; try { diff --git a/ArcFormats/Seraphim/ArcSeraph.cs b/ArcFormats/Seraphim/ArcSeraph.cs index b236d94d..61b191f4 100644 --- a/ArcFormats/Seraphim/ArcSeraph.cs +++ b/ArcFormats/Seraphim/ArcSeraph.cs @@ -103,6 +103,9 @@ namespace GameRes.Formats.Seraphim return null; } + // 3 @ ScnPac.Dat : FF 18 05 XX XX XX XX + // FF 16 05 XX XX XX XX + List ReadIndex (ArcView file, ArchPacScheme scheme) { long index_offset = scheme.IndexOffset; @@ -165,9 +168,14 @@ namespace GameRes.Formats.Seraphim var input = arc.File.CreateStream (entry.Offset, entry.Size); if (!(entry is PackedEntry)) return input; - if (0x9C78 != (input.Signature & 0xFFFF)) - return input; - return new ZLibStream (input, CompressionMode.Decompress); + if (0x9C78 == (input.Signature & 0xFFFF)) + return new ZLibStream (input, CompressionMode.Decompress); + if (1 == input.Signature && arc.File.View.ReadByte (entry.Offset+4) == 0x78) + { + input.Position = 4; + return new ZLibStream (input, CompressionMode.Decompress); + } + return input; } public override IImageDecoder OpenImage (ArcFile arc, Entry entry) @@ -196,7 +204,7 @@ namespace GameRes.Formats.Seraphim { uint width = input.ReadUInt16(); uint height = input.ReadUInt16(); - if (0x4243 == width || 0 == width || 0 == height || width * height * 3 + 4 != input.Length) + if (width > 0x4300 || 0 == width || 0 == height || width * height * 3 + 4 != input.Length) { input.Position = 0; return new ImageFormatDecoder (input); diff --git a/ArcFormats/Seraphim/ArcVoice.cs b/ArcFormats/Seraphim/ArcVoice.cs index 9d667020..1edf5606 100644 --- a/ArcFormats/Seraphim/ArcVoice.cs +++ b/ArcFormats/Seraphim/ArcVoice.cs @@ -60,14 +60,23 @@ namespace GameRes.Formats.Seraphim int count = file.View.ReadInt16 (0); if (!IsSaneCount (count)) return null; - uint data_offset = 2 + 4 * (uint)count; - if (data_offset > file.View.Reserve (0, data_offset)) - return null; + uint data_offset = 2 + 4 * (uint)count; + uint next_offset = file.View.ReadUInt32 (2); + List dir = null; + if (next_offset < data_offset || next_offset >= file.MaxOffset) + dir = ReadV2 (file, count); + else + dir = ReadV1 (file, count); + if (null == dir) + return null; + return new ArcFile (file, this, dir); + } + + List ReadV1 (ArcView file, int count) + { int index_offset = 2; uint next_offset = file.View.ReadUInt32 (index_offset); - if (next_offset < data_offset) - return null; var dir = new List (count); for (int i = 0; i < count; ++i) { @@ -85,7 +94,27 @@ namespace GameRes.Formats.Seraphim return null; dir.Add (entry); } - return new ArcFile (file, this, dir); + return dir; + } + + List ReadV2 (ArcView file, int count) + { + int index_offset = 6; + var dir = new List (count); + for (int i = 0; i < count; ++i) + { + var entry = new Entry { + Name = string.Format ("{0:D5}.ogg", i), + Type = "audio", + Offset = file.View.ReadUInt32 (index_offset), + Size = file.View.ReadUInt32 (index_offset+4), + }; + if (!entry.CheckPlacement (file.MaxOffset)) + return null; + dir.Add (entry); + index_offset += 12; + } + return dir; } } }