diff --git a/WzComparerR2.Common/Controls/GraphicsDeviceControl.cs b/WzComparerR2.Common/Controls/GraphicsDeviceControl.cs index 8dcb70fe..c5c17f86 100644 --- a/WzComparerR2.Common/Controls/GraphicsDeviceControl.cs +++ b/WzComparerR2.Common/Controls/GraphicsDeviceControl.cs @@ -83,7 +83,10 @@ protected override void OnCreateControl() this.swapChainRT = new SwapChainRenderTarget(graphicsDeviceService.GraphicsDevice, this.Handle, ClientSize.Width, - ClientSize.Height); + ClientSize.Height) + { + PresentInterval = PresentInterval.Immediate + }; // Register the service, so components like ContentManager can find it. services.AddService(graphicsDeviceService); @@ -270,7 +273,10 @@ string HandleDeviceReset() this.graphicsDeviceService.GraphicsDevice, this.Handle, clientSize.Width, - clientSize.Height); + clientSize.Height) + { + PresentInterval = PresentInterval.Immediate + }; } catch (Exception e) { diff --git a/WzComparerR2.Common/Rendering/Effect/EffectCompiler.bat b/WzComparerR2.Common/Rendering/Effect/EffectCompiler.bat index 1de0c247..943ee18c 100644 --- a/WzComparerR2.Common/Rendering/Effect/EffectCompiler.bat +++ b/WzComparerR2.Common/Rendering/Effect/EffectCompiler.bat @@ -1,7 +1,7 @@ @echo off setlocal -SET MGFX="%ProgramFiles(x86)%\MSBuild\MonoGame\v3.0\Tools\2MGFX.exe" -CALL %MGFX% "PngEffect.fx" "PngEffect.mgfxo" /Profile:DirectX_11 +dotnet tool install --global dotnet-mgfxc --version 3.8.0.1641 +mgfxc "PngEffect.fx" "PngEffect.mgfxo" /Profile:DirectX_11 endlocal \ No newline at end of file diff --git a/WzComparerR2.Common/Rendering/Effect/PngEffect.mgfxo b/WzComparerR2.Common/Rendering/Effect/PngEffect.mgfxo index 70b288ef..392784db 100644 Binary files a/WzComparerR2.Common/Rendering/Effect/PngEffect.mgfxo and b/WzComparerR2.Common/Rendering/Effect/PngEffect.mgfxo differ diff --git a/WzComparerR2.WzLib/Wz_Crypto.cs b/WzComparerR2.WzLib/Wz_Crypto.cs index b01b8b42..f4f0bbcc 100644 --- a/WzComparerR2.WzLib/Wz_Crypto.cs +++ b/WzComparerR2.WzLib/Wz_Crypto.cs @@ -94,7 +94,7 @@ public void LoadListWz(string path) public void DetectEncryption(Wz_File f) { int old_off = (int)f.FileStream.Position; - f.FileStream.Position = 62; + f.FileStream.Position = f.Header.DataStartPosition; if (f.ReadInt32() <= 0) //只有文件头 无法预判 { return; diff --git a/WzComparerR2.WzLib/Wz_File.cs b/WzComparerR2.WzLib/Wz_File.cs index 0bda0273..7ac42052 100644 --- a/WzComparerR2.WzLib/Wz_File.cs +++ b/WzComparerR2.WzLib/Wz_File.cs @@ -121,12 +121,60 @@ private bool GetHeader(string fileName) string signature = new string(this.BReader.ReadChars(4)); if (signature != "PKG1") { goto __failed; } - long datasize = this.BReader.ReadInt64(); - int headersize = this.BReader.ReadInt32(); - string copyright = new string(this.BReader.ReadChars(headersize - (int)this.FileStream.Position)); - int encver = this.BReader.ReadUInt16(); + long dataSize = this.BReader.ReadInt64(); + int headerSize = this.BReader.ReadInt32(); + string copyright = new string(this.BReader.ReadChars(headerSize - (int)this.FileStream.Position)); + + // encver detecting: + // Since KMST1132, wz removed the 2 bytes encver, and use a fixed wzver '777'. + // Here we try to read the first 2 bytes from data part and guess if it looks like an encver. + bool encverMissing = false; + int encver = -1; + if (dataSize >= 2) + { + this.fileStream.Position = headerSize; + encver = this.BReader.ReadUInt16(); + // encver always less than 256 + if (encver > 0xff) + { + encverMissing = true; + } + else if (encver == 0x80) + { + // there's an exceptional case that the first field of data part is a compressed int which determined property count, + // if the value greater than 127 and also to be a multiple of 256, the first 5 bytes will become to + // 80 00 xx xx xx + // so we additional check the int value, at most time the child node count in a wz won't greater than 65536. + if (dataSize >= 5) + { + this.fileStream.Position = headerSize; + int propCount = this.ReadInt32(); + if (propCount > 0 && (propCount & 0xff) == 0 && propCount <= 0xffff) + { + encverMissing = true; + } + } + } + } + else + { + // Obviously, if data part have only 1 byte, encver must be deleted. + encverMissing = true; + } + + int dataStartPos = headerSize + (encverMissing ? 0 : 2); + this.Header = new Wz_Header(signature, copyright, fileName, headerSize, dataSize, filesize, dataStartPos); + + if (encverMissing) + { + // not sure if nexon will change this magic version, just hard coded. + this.Header.SetWzVersion(777); + } + else + { + this.Header.SetOrdinalVersionDetector(encver); + } - this.Header = new Wz_Header(signature, copyright, fileName, headersize, datasize, filesize, encver); return true; __failed: diff --git a/WzComparerR2.WzLib/Wz_Header.cs b/WzComparerR2.WzLib/Wz_Header.cs index 756c3827..8e0ada88 100644 --- a/WzComparerR2.WzLib/Wz_Header.cs +++ b/WzComparerR2.WzLib/Wz_Header.cs @@ -6,7 +6,7 @@ namespace WzComparerR2.WzLib { public class Wz_Header { - public Wz_Header(string signature, string copyright, string file_name, int head_size, long data_size, long file_size, int encVersion) + public Wz_Header(string signature, string copyright, string file_name, int head_size, long data_size, long file_size, long dataStartPosition) { this.Signature = signature; this.Copyright = copyright; @@ -14,74 +14,141 @@ public Wz_Header(string signature, string copyright, string file_name, int head_ this.HeaderSize = head_size; this.DataSize = data_size; this.FileSize = file_size; - this.EncryptedVersion = encVersion; + this.DataStartPosition = dataStartPosition; this.VersionChecked = false; - - this.c_version_test = new List(); - this.hash_version_test = new List(); - this.startVersion = -1; } - public string Signature { get; set; } - public string Copyright { get; set; } - public string FileName { get; set; } + public string Signature { get; private set; } + public string Copyright { get; private set; } + public string FileName { get; private set; } - public int HeaderSize { get; set; } - public long DataSize { get; set; } - public long FileSize { get; set; } - public int EncryptedVersion { get; set; } + public int HeaderSize { get; private set; } + public long DataSize { get; private set; } + public long FileSize { get; private set; } + public long DataStartPosition { get; private set; } public bool VersionChecked { get; set; } - private List c_version_test; - private List hash_version_test; - private int startVersion; + public int WzVersion => this.versionDetector?.WzVersion ?? 0; + public uint HashVersion => this.versionDetector?.HashVersion ?? 0; + public bool TryGetNextVersion() => this.versionDetector?.TryGetNextVersion() ?? false; + + private IWzVersionDetector versionDetector; + + public void SetWzVersion(int wzVersion) + { + this.versionDetector = new FixedVersion(wzVersion); + } - public int WzVersion + public void SetOrdinalVersionDetector(int encryptedVersion) { - get + this.versionDetector = new OrdinalVersionDetector(encryptedVersion); + } + + public static int CalcHashVersion(int wzVersion) + { + int sum = 0; + string versionStr = wzVersion.ToString(System.Globalization.CultureInfo.InvariantCulture); + for (int j = 0; j < versionStr.Length; j++) { - int idx = this.c_version_test.Count - 1; - return idx > -1 ? this.c_version_test[idx] : 0; + sum <<= 5; + sum += (int)versionStr[j] + 1; } + + return sum; + } + + public interface IWzVersionDetector + { + bool TryGetNextVersion(); + int WzVersion { get; } + uint HashVersion { get; } } - public uint HashVersion + public class FixedVersion : IWzVersionDetector { - get + public FixedVersion(int wzVersion) + { + this.WzVersion = wzVersion; + this.HashVersion = (uint)CalcHashVersion(wzVersion); + } + + private bool hasReturned; + + + public int WzVersion { get; private set; } + + public uint HashVersion { get; private set; } + + public bool TryGetNextVersion() { - int idx = this.hash_version_test.Count - 1; - return idx > -1 ? this.hash_version_test[idx] : 0; + if (!hasReturned) + { + hasReturned = true; + return true; + } + + return false; } } - public bool TryGetNextVersion() + public class OrdinalVersionDetector : IWzVersionDetector { - for (int i = startVersion + 1; i < Int16.MaxValue; i++) + public OrdinalVersionDetector(int encryptVersion) + { + this.EncryptedVersion = encryptVersion; + this.versionTest = new List(); + this.hasVersionTest = new List(); + this.startVersion = -1; + } + + public int EncryptedVersion { get; private set; } + + private int startVersion; + private List versionTest; + private List hasVersionTest; + + public int WzVersion { - int sum = 0; - string versionStr = i.ToString(System.Globalization.CultureInfo.InvariantCulture); - for (int j = 0; j < versionStr.Length; j++) + get { - sum <<= 5; - sum += (int)versionStr[j] + 1; + int idx = this.versionTest.Count - 1; + return idx > -1 ? this.versionTest[idx] : 0; } - int enc = 0xff - ^ ((sum >> 24) & 0xFF) - ^ ((sum >> 16) & 0xFF) - ^ ((sum >> 8) & 0xFF) - ^ ((sum) & 0xFF); + } - if (enc == EncryptedVersion) + public uint HashVersion + { + get { - this.c_version_test.Add(i); - this.hash_version_test.Add((uint)sum); - startVersion = i; - return true; + int idx = this.hasVersionTest.Count - 1; + return idx > -1 ? this.hasVersionTest[idx] : 0; } } - return false; + public bool TryGetNextVersion() + { + for (int i = startVersion + 1; i < Int16.MaxValue; i++) + { + int sum = CalcHashVersion(i); + int enc = 0xff + ^ ((sum >> 24) & 0xFF) + ^ ((sum >> 16) & 0xFF) + ^ ((sum >> 8) & 0xFF) + ^ ((sum) & 0xFF); + + // if encver does not passed, try every version one by one + if (enc == this.EncryptedVersion) + { + this.versionTest.Add(i); + this.hasVersionTest.Add((uint)sum); + startVersion = i; + return true; + } + } + + return false; + } } } } diff --git a/WzComparerR2.WzLib/Wz_Image.cs b/WzComparerR2.WzLib/Wz_Image.cs index 3f804a2b..757b16da 100644 --- a/WzComparerR2.WzLib/Wz_Image.cs +++ b/WzComparerR2.WzLib/Wz_Image.cs @@ -75,7 +75,12 @@ public bool TryExtract(out Exception e) { try { - TryDetectEnc(); + this.TryDetectEnc(); + if (this.Encryption == null) + { + e = null; + return false; + } } catch (Exception ex) { @@ -231,7 +236,7 @@ private void TryDetectEnc() return; } } - + var oldenc = crypto.EncType; crypto.EncType = Wz_Crypto.Wz_CryptoKeyType.KMS; if (IsIllegalTag()) { @@ -253,7 +258,7 @@ private void TryDetectEnc() return; } - crypto.EncType = Wz_Crypto.Wz_CryptoKeyType.Unknown; + crypto.EncType = oldenc; } private bool IsIllegalTag() diff --git a/WzComparerR2.WzLib/Wz_Structure.cs b/WzComparerR2.WzLib/Wz_Structure.cs index 968905b9..521296ea 100644 --- a/WzComparerR2.WzLib/Wz_Structure.cs +++ b/WzComparerR2.WzLib/Wz_Structure.cs @@ -90,7 +90,7 @@ public Wz_File LoadFile(string fileName, Wz_Node node, bool useBaseWz = false, b } node.Value = file; file.Node = node; - file.FileStream.Position = 62; + file.FileStream.Position = file.Header.DataStartPosition; file.GetDirTree(node, useBaseWz, loadWzAsFolder); file.DetectWzType(); file.DetectWzVersion(); @@ -171,7 +171,7 @@ public bool IsKMST1125WzFormat(string fileName) { this.encryption.DetectEncryption(file); } - file.FileStream.Position = 62; + file.FileStream.Position = file.Header.DataStartPosition; file.GetDirTree(tempNode); return file.ImageCount == 0; } diff --git a/WzComparerR2/FrmPatcher.cs b/WzComparerR2/FrmPatcher.cs index 7fdb1b95..e82b3e5c 100644 --- a/WzComparerR2/FrmPatcher.cs +++ b/WzComparerR2/FrmPatcher.cs @@ -223,7 +223,8 @@ private void ExecutePatch(string patchFile, string msFolder, bool prePatch) { patcher = new WzPatcher(patchFile); patcher.PatchingStateChanged += new EventHandler(patcher_PatchingStateChanged); - AppendStateText("패치 확인중... "); + AppendStateText($"패치 파일명: {patchFile}\r\n"); + AppendStateText("패치 확인중..."); patcher.OpenDecompress(); AppendStateText("완료\r\n"); //if (prePatch)