(Seraph): alternative archives layout.

This commit is contained in:
morkt 2018-09-09 17:27:38 +04:00
parent be5a951513
commit 94dac729b6
3 changed files with 57 additions and 13 deletions

View File

@ -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
{

View File

@ -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<Entry> 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);

View File

@ -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<Entry> 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<Entry> 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<Entry> (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<Entry> ReadV2 (ArcView file, int count)
{
int index_offset = 6;
var dir = new List<Entry> (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;
}
}
}