From e6ca959ded9394d817a04334e910b71ebb4abf30 Mon Sep 17 00:00:00 2001 From: morkt Date: Fri, 10 Feb 2017 03:27:39 +0400 Subject: [PATCH] support WARC 1.10 archives. --- ArcFormats/ShiinaRio/ArcWARC.cs | 42 ++++++++++++++++---------- ArcFormats/ShiinaRio/WarcEncryption.cs | 4 ++- supported.html | 7 ++++- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/ArcFormats/ShiinaRio/ArcWARC.cs b/ArcFormats/ShiinaRio/ArcWARC.cs index 3efb004a..aee85ad3 100644 --- a/ArcFormats/ShiinaRio/ArcWARC.cs +++ b/ArcFormats/ShiinaRio/ArcWARC.cs @@ -2,7 +2,7 @@ //! \date Fri Apr 10 03:10:42 2015 //! \brief ShiinaRio engine archive format. // -// Copyright (C) 2015-2016 by morkt +// Copyright (C) 2015-2017 by morkt // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to @@ -83,14 +83,18 @@ namespace GameRes.Formats.ShiinaRio // 椎名里緒 if (!file.View.AsciiEqual (4, " 1.")) return null; int version = file.View.ReadByte (7) - 0x30; + if (version < 1 || version > 7) + return null; version = 100 + version * 10; - if (170 != version && 150 != version && 140 != version && 130 != version && 120 != version) - throw new NotSupportedException ("Not supported WARC version"); - uint index_offset = 0xf182ad82u ^ file.View.ReadUInt32 (8); + uint index_offset = 0xF182AD82u ^ file.View.ReadUInt32 (8); if (index_offset >= file.MaxOffset) return null; - var scheme = QueryEncryption (file.Name); + EncryptionScheme scheme; + if (version > 110) + scheme = QueryEncryption (file.Name); + else + scheme = EncryptionScheme.Warc110; if (null == scheme) return null; var decoder = new Decoder (version, scheme); @@ -111,7 +115,7 @@ namespace GameRes.Formats.ShiinaRio // 椎名里緒 var zindex = new MemoryStream (enc_index, 8, (int)index_length-8); index = new ZLibStream (zindex, CompressionMode.Decompress); } - else + else if (version >= 120) { var unpacked = new byte[max_index_len]; index_length = UnpackRNG (enc_index, 0, index_length, unpacked); @@ -119,6 +123,10 @@ namespace GameRes.Formats.ShiinaRio // 椎名里緒 return null; index = new MemoryStream (unpacked, 0, (int)index_length); } + else + { + index = new MemoryStream (enc_index, 0, (int)index_length); + } using (var header = new BinaryReader (index)) { byte[] name_buf = new byte[decoder.EntryNameSize]; @@ -151,15 +159,14 @@ namespace GameRes.Formats.ShiinaRio // 椎名里緒 var wentry = entry as WarcEntry; if (null == warc || null == wentry || entry.Size < 8) return arc.File.CreateStream (entry.Offset, entry.Size); - var enc_data = new byte[entry.Size]; - if (entry.Size != arc.File.View.Read (entry.Offset, enc_data, 0, entry.Size)) - return Stream.Null; + var enc_data = arc.File.View.ReadBytes (entry.Offset, entry.Size); + if (enc_data.Length <= 8) + return new BinMemoryStream (enc_data, entry.Name); uint sig = LittleEndian.ToUInt32 (enc_data, 0); uint unpacked_size = LittleEndian.ToUInt32 (enc_data, 4); - sig ^= (unpacked_size ^ 0x82AD82) & 0xffffff; - - if (entry.Size > 8) + if (warc.Decoder.WarcVersion > 110) { + sig ^= (unpacked_size ^ 0x82AD82) & 0xFFFFFF; if (0 != (wentry.Flags & 0x80000000u)) // encrypted entry warc.Decoder.Decrypt (enc_data, 8, entry.Size-8); if (warc.Decoder.ExtraCrypt != null) @@ -185,10 +192,13 @@ namespace GameRes.Formats.ShiinaRio // 椎名里緒 { unpacked = new byte[unpacked_size]; unpack (enc_data, unpacked); - if (0 != (wentry.Flags & 0x40000000)) - warc.Decoder.Decrypt2 (unpacked, 0, (uint)unpacked.Length); - if (warc.Decoder.ExtraCrypt != null) - warc.Decoder.ExtraCrypt.Decrypt (unpacked, 0, (uint)unpacked.Length, 0x204); + if (warc.Decoder.WarcVersion > 110) + { + if (0 != (wentry.Flags & 0x40000000)) + warc.Decoder.Decrypt2 (unpacked, 0, (uint)unpacked.Length); + if (warc.Decoder.ExtraCrypt != null) + warc.Decoder.ExtraCrypt.Decrypt (unpacked, 0, (uint)unpacked.Length, 0x204); + } } return new BinMemoryStream (unpacked, entry.Name); } diff --git a/ArcFormats/ShiinaRio/WarcEncryption.cs b/ArcFormats/ShiinaRio/WarcEncryption.cs index b1bd0daa..fa0f0355 100644 --- a/ArcFormats/ShiinaRio/WarcEncryption.cs +++ b/ArcFormats/ShiinaRio/WarcEncryption.cs @@ -42,6 +42,8 @@ namespace GameRes.Formats.ShiinaRio public byte[] DecodeBin; public IByteArray ShiinaImage; public IDecryptExtra ExtraCrypt; + + public static readonly EncryptionScheme Warc110 = new EncryptionScheme { EntryNameSize = 0x10 }; } public interface IByteArray @@ -136,7 +138,7 @@ namespace GameRes.Formats.ShiinaRio void DoEncryption (byte[] data, int index, uint data_length, ContentEncryptor encryptor) { - if (data_length < 3) + if (data_length < 3 || WarcVersion < 120) return; uint effective_length = Math.Min (data_length, 1024u); int a, b; diff --git a/supported.html b/supported.html index 2f7f40eb..c55e1794 100644 --- a/supported.html +++ b/supported.html @@ -254,6 +254,7 @@ Ah, Ojou-sama
Altered Pink ~Tokumu Sentai Duel Ranger~
Amairo*Islenauts
Aozora Gakko no Sensei-kun
+Bishuu ~Chigyaku no Mesu Dorei~
Boku to Koi Suru Ponkotsu Akuma. Suggoi Ecchi!
Cafe Sourire
Coμ
@@ -276,6 +277,7 @@ Hime to Majin to Koi Suru Tamashii
Imouto Style
Inaho no Mirai
Karakara
+Karenai Sekai to Owaru Hana
Kourin no Machi, Lavender no Shoujo
Kozukuri Onsen ~Ippai Tsukutte Ichizoku Hanei~
Kurenai no Tsuki
@@ -383,6 +385,7 @@ Ren no Koi
*.ald-NoAlice Soft Boku dake no Hokenshitsu
Daiteikoku
+Majo no Shokuzai
Momoiro Guardian
Pastel Chime 3 Bind Seeker
Rance 03
@@ -439,11 +442,12 @@ Shouhei-kun no Hani-Kami Life☆
Touka Gettan
*\x00\x00\x04\x00No -*.warWARC 1.7
WARC 1.5
WARC 1.4
WARC 1.3
WARC 1.2NoShiina Rio +*.warWARC 1.7
WARC 1.5
WARC 1.4
WARC 1.3
WARC 1.2
WARC 1.1NoShiina Rio Ao no Juuai ShiinaRio v2.34
Aneiro ShiinaRio v2.49
Bitch Nee-chan ga Seijun na Hazu ga Nai! ShiinaRio v2.50
Bitch Shimai ga Seijun na Hazu ga Nai!! ShiinaRio v2.50
+Calendar Girl ShiinaRio v2.02
Can Fes! ~Itazura Majo to Naisho no Gakuensai~ ShiinaRio v2.47
Chikan Circle ShiinaRio v2.46
Chikan Circle 2 ShiinaRio v2.47
@@ -1422,6 +1426,7 @@ Ryoujoku Joshi Gakuen
*BCNo *.pakGraphic PackDataNocromwell Ikenie Reijou
+Tremolo
*.opkVoiceOggPackFileNo