From 9af7f41ef53e66edfc7da31faf8d13c8751ba695 Mon Sep 17 00:00:00 2001 From: morkt Date: Fri, 18 Mar 2016 06:23:51 +0400 Subject: [PATCH] guess keys of DXA archives. --- ArcFormats/DxLib/ArcDX.cs | 52 ++++++++++++++++++++++++++++++++++++--- supported.html | 5 +++- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/ArcFormats/DxLib/ArcDX.cs b/ArcFormats/DxLib/ArcDX.cs index 63c281fb..9e8c1067 100644 --- a/ArcFormats/DxLib/ArcDX.cs +++ b/ArcFormats/DxLib/ArcDX.cs @@ -61,13 +61,15 @@ namespace GameRes.Formats.DxLib public DxOpener () { Extensions = new string[] { "dxa", "hud", "usi", "med", "dat" }; - Signatures = new uint[] { 0x19EF8ED4, 0xA9FCCEDD, 0x0AEE0FD3, 0 }; + Signatures = new uint[] { 0x19EF8ED4, 0xA9FCCEDD, 0x0AEE0FD3, 0x5523F211, 0 }; } public static IList KnownKeys = new List(); public override ArcFile TryOpen (ArcView file) { + if (file.MaxOffset < 0x1C) + return null; uint signature = file.View.ReadUInt32 (0); foreach (var key in KnownKeys) { @@ -79,13 +81,53 @@ namespace GameRes.Formats.DxLib var dir = ReadIndex (file, version, key); if (null != dir) { - // move last used key to the top of the known keys list - KnownKeys.Remove (key); + if (KnownKeys[0] != key) + { + // move last used key to the top of the known keys list + KnownKeys.Remove (key); + KnownKeys.Insert (0, key); + } + return new DxArchive (file, this, dir, key); + } + return null; + } + } + return GuessKey (file); + } + + ArcFile GuessKey (ArcView file) + { + if (file.MaxOffset > uint.MaxValue) + return null; + var key = new byte[12]; + for (short version = 4; version >= 1; --version) + { + file.View.Read (0, key, 0, 12); + key[0] ^= (byte)'D'; + key[1] ^= (byte)'X'; + key[2] ^= (byte)version; + int base_offset = version > 3 ? 0x1C : 0x18; + key[8] ^= (byte)base_offset; + uint key0 = LittleEndian.ToUInt32 (key, 0); + uint index_offset = file.View.ReadUInt32 (12) ^ key0; + if (index_offset <= base_offset || index_offset >= file.MaxOffset) + continue; + uint index_size = (uint)(file.MaxOffset - index_offset); + if (index_size > 0xFFFFFF) + continue; + key[4] ^= (byte)index_size; + key[5] ^= (byte)(index_size >> 8); + key[6] ^= (byte)(index_size >> 16); + try + { + var dir = ReadIndex (file, version, key); + if (null != dir) + { KnownKeys.Insert (0, key); return new DxArchive (file, this, dir, key); } - break; } + catch { /* ignore parse errors */ } } return null; } @@ -184,6 +226,8 @@ namespace GameRes.Formats.DxLib FileTable = LittleEndian.ToUInt32 (header, 0x0c), DirTable = LittleEndian.ToUInt32 (header, 0x10), }; + if (dx.DirTable >= dx.IndexSize || dx.FileTable >= dx.IndexSize) + return null; using (var encrypted = file.CreateStream (dx.IndexOffset, dx.IndexSize)) using (var index = new EncryptedStream (encrypted, dx.IndexOffset, key)) using (var reader = new IndexReader (dx, version, index)) diff --git a/supported.html b/supported.html index d1e30e66..4c86af39 100644 --- a/supported.html +++ b/supported.html @@ -34,6 +34,7 @@ Remember11
11gatsu no Arcadia
Chou Dengeki Stryker
Chou Jikuu Bakuren Monogatari ~door pi chu~
+Eiken Kikaku
H2O -Footprints in the Sand-
Melty Moment
Traveling Stars
@@ -424,6 +425,7 @@ X Change 2
X Change 2R
Ryoujoku Gojuusou
Hissatsu Chikannin II
+Tokumei Sentai Sirenger
Tokumei Sentai Yuzu Ranger
*.cwpCWDPYes @@ -455,7 +457,7 @@ Gakuen ~Nerawareta Chitai~
Kimon Youitan
Unbalance
-*.lib
*.datLIB
LIBP
LIBUNoMalie +*.lib
*.datLIB
LIBP
LIBUencryptedNoMalie Angel Crown
Dies irae
Dies irae ~Amantes amentes~
@@ -577,6 +579,7 @@ Soukai no Valkyria
Ashita wa Kitto, Haremasu you ni
Cross Quartz
Hyakki Yakou
+Saikyou Goshujin-sama! -Mighty My Master-
*.tcdTCD3NoTopCat Atori no Sora to Shinchuu no Tsuki