From 1c96b016775131f6ef766a00b7f5bdf2897bb8cc Mon Sep 17 00:00:00 2001 From: morkt Date: Sun, 28 Feb 2016 11:07:28 +0400 Subject: [PATCH] implemented "war2" audio archives. --- ArcFormats/Sas5/ArcWAR.cs | 106 +++++++++++++++++++++++++++++++------- supported.html | 5 +- 2 files changed, 91 insertions(+), 20 deletions(-) diff --git a/ArcFormats/Sas5/ArcWAR.cs b/ArcFormats/Sas5/ArcWAR.cs index 00c96d34..225585cf 100644 --- a/ArcFormats/Sas5/ArcWAR.cs +++ b/ArcFormats/Sas5/ArcWAR.cs @@ -58,19 +58,7 @@ namespace GameRes.Formats.Sas5 uint entry_size = file.View.ReadUInt32 (12); if (entry_size < 0x18) return null; - - var index = Sec5Opener.LookupIndex (file.Name); - string base_name = Path.GetFileNameWithoutExtension (file.Name); - Func GetEntryName; - if (null == index) - GetEntryName = n => GetDefaultName (base_name, n); - else - GetEntryName = (n) => { - Entry entry; - if (index.TryGetValue (n, out entry)) - return entry.Name; - return GetDefaultName (base_name, n); - }; + var GetEntryName = CreateEntryNameDelegate (file.Name); uint index_offset = 0x10; var dir = new List (count); @@ -105,12 +93,36 @@ namespace GameRes.Formats.Sas5 var went = entry as WarEntry; if (null == went || 0 != went.Format) return arc.File.CreateStream (entry.Offset, entry.Size); + return OpenWavEntry (arc.File, entry.Offset, entry.Size); + } - uint fmt_size = arc.File.View.ReadUInt32 (entry.Offset); - uint data_size = arc.File.View.ReadUInt32 (entry.Offset+4); + internal Func CreateEntryNameDelegate (string arc_name) + { + var index = Sec5Opener.LookupIndex (arc_name); + string base_name = Path.GetFileNameWithoutExtension (arc_name); + if (null == index) + return n => GetDefaultName (base_name, n); + else + return (n) => { + Entry entry; + if (index.TryGetValue (n, out entry)) + return entry.Name; + return GetDefaultName (base_name, n); + }; + } + + internal static string GetDefaultName (string base_name, int n) + { + return string.Format ("{0}#{1:D5}", base_name, n); + } + + internal Stream OpenWavEntry (ArcView file, long offset, uint size) + { + uint fmt_size = file.View.ReadUInt32 (offset); + uint data_size = file.View.ReadUInt32 (offset+4); var wav_header = new byte[8+12+fmt_size+8]; uint total_size = (uint)wav_header.Length + data_size - 8; - arc.File.View.Read (entry.Offset+8, wav_header, 0x14, fmt_size); + file.View.Read (offset+8, wav_header, 0x14, fmt_size); using (var mem = new MemoryStream (wav_header)) using (var buffer = new BinaryWriter (mem)) { @@ -123,13 +135,69 @@ namespace GameRes.Formats.Sas5 buffer.Write (0x61746164); // 'data' buffer.Write (data_size); } - var pcm_data = arc.File.CreateStream (entry.Offset+8+fmt_size, entry.Size-8-fmt_size); + var pcm_data = file.CreateStream (offset+8+fmt_size, size-8-fmt_size); return new PrefixStream (wav_header, pcm_data); } + } - static string GetDefaultName (string base_name, int n) + [Export(typeof(ArchiveFormat))] + public class War2Opener : WarOpener + { + public override string Tag { get { return "WAR2/SAS5"; } } + public override string Description { get { return "SAS5 engine audio archive"; } } + public override uint Signature { get { return 0x32726177; } } // 'war2' + public override bool IsHierarchic { get { return false; } } + public override bool CanCreate { get { return false; } } + + public War2Opener () { - return string.Format ("{0}#{1:D5}", base_name, n); + Extensions = new string[] { "war" }; + } + + public override ArcFile TryOpen (ArcView file) + { + uint header_size = file.View.ReadUInt32 (4); + if (header_size >= file.MaxOffset) + return null; + int count = file.View.ReadInt32 (12); + if (!IsSaneCount (count)) + return null; + var GetEntryName = CreateEntryNameDelegate (file.Name); + + uint index_offset = header_size+8; + uint next_offset = file.View.ReadUInt32 (index_offset); + var dir = new List (count); + for (int i = 0; i < count; ++i) + { + index_offset += 4; + var entry = new Entry { + Name = GetEntryName (i), + Offset = next_offset, + Type = "audio", + }; + next_offset = file.View.ReadUInt32 (index_offset); + entry.Size = (uint)(next_offset - entry.Offset); + if (!entry.CheckPlacement (file.MaxOffset)) + return null; + dir.Add (entry); + } + return new ArcFile (file, this, dir); + } + + public override Stream OpenEntry (ArcFile arc, Entry entry) + { + var offset = entry.Offset; + var end_offset = entry.Offset + entry.Size; + byte id = arc.File.View.ReadByte (offset++); + if (0 != (id & 0x40)) + offset += 12; + if (offset >= end_offset) + return Stream.Null; + uint size = (uint)(end_offset - offset); + int format = id & 0xF; + if (0 == format) + return OpenWavEntry (arc.File, offset, size); + return arc.File.CreateStream (offset, size); } } } diff --git a/supported.html b/supported.html index 032dc4d1..60bfdd34 100644 --- a/supported.html +++ b/supported.html @@ -39,6 +39,7 @@ Make Love Junkies
Natsu no Hitoshizuku
Onedari Milky Pai
Private Nurse
+Reijou Caster Mariko
Salmon Pink
Shisho-san to Issho
Sensei 2
@@ -440,6 +441,7 @@ Dies irae
Dies irae ~Amantes amentes~
Kajiri Kamui Kagura
Paradise Lost
+Sakashiki Hito ni Miru Kokoro
Zettai Meikyuu Grimm
*.mgfMalieGFYes @@ -568,7 +570,8 @@ Shitai o Arau
*.g24-No *.mskRmskNo -*.iar
*.wariar
warNoStudio Ryokucha +*.iar
*.wariar
war
war2NoStudio Ryokucha +Hanikami Clover
Katakoi no Tsuki
Katakoi no Tsuki Extra
Shukufuku no Kane no Oto wa, Sakurairo no Kaze to Tomo ni