From 2a1e13c294189b43684efa32b8b5cf0f24ab35a1 Mon Sep 17 00:00:00 2001 From: morkt Date: Tue, 31 Jan 2017 16:17:48 +0400 Subject: [PATCH] implemented WSM1 archives. --- ArcFormats/Tanaka/ArcWSM.cs | 82 +++++++++++++++++++++++++++++++++++-- supported.html | 11 ++++- 2 files changed, 88 insertions(+), 5 deletions(-) diff --git a/ArcFormats/Tanaka/ArcWSM.cs b/ArcFormats/Tanaka/ArcWSM.cs index ce0b7742..dbac1284 100644 --- a/ArcFormats/Tanaka/ArcWSM.cs +++ b/ArcFormats/Tanaka/ArcWSM.cs @@ -25,19 +25,25 @@ using System.Collections.Generic; using System.ComponentModel.Composition; +using System.IO; using GameRes.Utility; namespace GameRes.Formats.Will { [Export(typeof(ArchiveFormat))] - public class WsmOpener : ArchiveFormat + public class Wsm2Opener : ArchiveFormat { - public override string Tag { get { return "WSM"; } } - public override string Description { get { return "Tanaka Tatsuhiro's engine music archive"; } } + public override string Tag { get { return "WSM2"; } } + public override string Description { get { return "Tanaka Tatsuhiro's engine music archive v2"; } } public override uint Signature { get { return 0x324D5357; } } // 'WSM2' public override bool IsHierarchic { get { return false; } } public override bool CanWrite { get { return false; } } + public Wsm2Opener () + { + Extensions = new string[] { "wsm" }; + } + public override ArcFile TryOpen (ArcView file) { uint index_size = file.View.ReadUInt32 (4); @@ -55,6 +61,8 @@ namespace GameRes.Formats.Will var entry = new Entry { Type = "audio" }; entry.Offset = index.ToUInt32 (table_offset) - 0x14; entry.Size = index.ToUInt32 (table_offset+8) + 0x14; + if (!entry.CheckPlacement (file.MaxOffset)) + return null; table_offset += 0x20; dir.Add (entry); } @@ -77,4 +85,72 @@ namespace GameRes.Formats.Will return new ArcFile (file, this, dir); } } + + [Export(typeof(ArchiveFormat))] + public class Wsm1Opener : ArchiveFormat + { + public override string Tag { get { return "WSM1"; } } + public override string Description { get { return "Tanaka Tatsuhiro's engine music archive v1"; } } + public override uint Signature { get { return 0x314D5357; } } // 'WSM1' + public override bool IsHierarchic { get { return false; } } + public override bool CanWrite { get { return false; } } + + public Wsm1Opener () + { + Extensions = new string[] { "wsm" }; + } + + public override ArcFile TryOpen (ArcView file) + { + uint index_size = file.View.ReadUInt32 (4); + int count = file.View.ReadInt32 (8); + if (!IsSaneCount (count) || index_size >= file.MaxOffset) + return null; + var index = file.View.ReadBytes (0, index_size); + var dir = new List (count); + int index_offset = 0x10; + for (int i = 0; i < count; ++i) + { + int entry_pos = index.ToInt32 (index_offset); + index_offset += 4; + int name_length = index[entry_pos]; + var name = Binary.GetCString (index, entry_pos+1, name_length-1); + if (0 == name.Length) + return null; + entry_pos += name_length; + var entry = new WsmEntry { + Name = string.Format ("{0}.wav", name), + Type = "audio", + Offset = index.ToUInt32 (entry_pos+8), + Size = index.ToUInt32 (entry_pos+12), + }; + if (!entry.CheckPlacement (file.MaxOffset)) + return null; + entry.Format.FormatTag = 1; + entry.Format.Channels = index[entry_pos+2]; + entry.Format.BitsPerSample = index[entry_pos+3]; + entry.Format.SamplesPerSecond = index.ToUInt32 (entry_pos+4); + entry.Format.BlockAlign = (ushort)(entry.Format.Channels * entry.Format.BitsPerSample/8); + entry.Format.AverageBytesPerSecond = entry.Format.SamplesPerSecond * entry.Format.BlockAlign; + dir.Add (entry); + } + return new ArcFile (file, this, dir); + } + + public override Stream OpenEntry (ArcFile arc, Entry entry) + { + var went = (WsmEntry)entry; + using (var riff = new MemoryStream (0x2C)) + { + WaveAudio.WriteRiffHeader (riff, went.Format, entry.Size); + var input = arc.File.CreateStream (entry.Offset, entry.Size); + return new PrefixStream (riff.ToArray(), input); + } + } + } + + internal class WsmEntry : Entry + { + public WaveFormat Format; + } } diff --git a/supported.html b/supported.html index 2347b2bb..24f25fdd 100644 --- a/supported.html +++ b/supported.html @@ -202,6 +202,7 @@ Xross Scramble
*.pacPAC1NoRAGE Brightia Plus
Hana Hiraku
+Hitou Meguri ~Yokujou Juurin Onsen Ki~
Iinari
Kyrie ~Blood Royal 3~
Shiosai no Himei
@@ -339,6 +340,7 @@ Gitai Saimin
Fukou na Kami
Saiminjutsu
Soukan Yuugi 2
+Ura Saiminjutsu 2
*.bmd_BMDYes *.asd-No @@ -449,6 +451,7 @@ Doushite Daite Kurenai no!?ShiinaRio v2.49
Douryou no Oku-san ~Netori Tsuma, Netorare Tsuma~ ShiinaRio v2.46
Draculius ShiinaRio v2.38
Enkaku Sousa 2.36 or 2.37
+Gakushoku no Oba-san The Motion ShiinaRio v2.48
Gensou no Idea ~Oratorio Phantasm Historia~ShiinaRio v2.49
Gohoushi Nurse ~Mayonaka no Kyousei Call~ ShiinaRio v2.50
Hana no Kioku 1-2-3 ShiinaRio v2.10
@@ -492,6 +495,7 @@ Tekoire Princess!ShiinaRio v2.37
Toriko no ChigiriShiinaRio v2.49
Wana ~Hakudaku Mamire no Houkago~ShiinaRio v2.36
Wana II ~Gang Rape~ShiinaRio v2.44
+Yokorenbo ~Immoral Mother~ ShiinaRio v2.44
Yoyogi Hitozuma Senmon GakuinShiinaRio v2.37
Zansho Omimai MoushiagemasuShiinaRio v2.41
@@ -956,6 +960,7 @@ Otto no Mae de Okasarete...
*.arc-NoAI6WIN Gakuen Saimin Reido
Jokei Kazoku 3
+Mama no Oppai ~Ore no Doutei Milk ga Shiboritorareta Ken~
Shinsou Noise
*.akbAKBNo @@ -1383,8 +1388,9 @@ Mite Kudasaimasu?
*.dpm
*.binDPMXNoHot Soup Processor femme fatale
-*.cdt
*.pdt
*.vdtRK1NoNEJII +*.cdt
*.pdt
*.vdt
*.ovdRK1NoNEJII Kidou Houshinki
+Sutadoru!
*.pcd-No *.tacTArc1.10
TArc1.00NoTanukiSoft @@ -1396,12 +1402,13 @@ Dedenden!
*.arcARC0NoWill Bishimai Kutsujoku no Heya
+~Miboujin~ Niku Dorei
*.bmx-No *.mbfMBF0No *.vpkVPK1No *.wrcWVX0No -*.wsmWSM2No +*.wsmWSM1
WSM2No *BCNo

1 Non-encrypted only