From 76053cb400b55a11669ef56deea6f44f1bc26bed Mon Sep 17 00:00:00 2001 From: lastbattle <4586194+lastbattle@users.noreply.github.com> Date: Sat, 1 Jan 2022 15:17:21 +0800 Subject: [PATCH] [WzLib] Refractoring --- .../MapleCryptoLib/MapleCryptoConstants.cs | 2 ++ MapleLib/WzLib/Util/WzBinaryReader.cs | 4 ++-- MapleLib/WzLib/Util/WzBinaryWriter.cs | 23 +++++++++++++++---- MapleLib/WzLib/Util/WzTool.cs | 2 +- MapleLib/WzLib/WzDirectory.cs | 9 ++++---- MapleLib/WzLib/WzFile.cs | 16 ++++++------- MapleLib/WzLib/WzImage.cs | 5 ++-- MapleLib/WzLib/WzImageProperty.cs | 4 ++-- .../WzLib/WzProperties/WzBinaryProperty.cs | 2 +- .../WzLib/WzProperties/WzCanvasProperty.cs | 4 ++-- .../WzLib/WzProperties/WzConvexProperty.cs | 8 ++++--- .../WzLib/WzProperties/WzStringProperty.cs | 2 +- MapleLib/WzLib/WzProperties/WzSubProperty.cs | 4 ++-- MapleLib/WzLib/WzProperties/WzUOLProperty.cs | 4 ++-- .../WzLib/WzProperties/WzVectorProperty.cs | 4 ++-- MapleLib/WzSettings.cs | 3 --- 16 files changed, 56 insertions(+), 40 deletions(-) diff --git a/MapleLib/MapleCryptoLib/MapleCryptoConstants.cs b/MapleLib/MapleCryptoLib/MapleCryptoConstants.cs index fe280570..48f0d8bd 100644 --- a/MapleLib/MapleCryptoLib/MapleCryptoConstants.cs +++ b/MapleLib/MapleCryptoLib/MapleCryptoConstants.cs @@ -86,11 +86,13 @@ public static bool IsDefaultMapleStoryUserKey() }; /// + /// ?s_BasicKey@CAESCipher@@2PAEA /// IV used to create the WzKey for GMS /// public static byte[] WZ_GMSIV = new byte[4] { 0x4D, 0x23, 0xC7, 0x2B }; /// + /// ?s_BasicKey@CAESCipher@@2PAEA /// IV used to create the WzKey for the latest version of GMS, MSEA, or KMS /// public static byte[] WZ_MSEAIV = new byte[4] { 0xB9, 0x7D, 0x63, 0xE9 }; diff --git a/MapleLib/WzLib/Util/WzBinaryReader.cs b/MapleLib/WzLib/Util/WzBinaryReader.cs index b5ebaae6..3c8f5471 100644 --- a/MapleLib/WzLib/Util/WzBinaryReader.cs +++ b/MapleLib/WzLib/Util/WzBinaryReader.cs @@ -204,10 +204,10 @@ public string ReadStringBlock(uint offset) switch (ReadByte()) { case 0: - case 0x73: + case WzImage.WzImageHeaderByte_WithoutOffset: return ReadString(); case 1: - case 0x1B: + case WzImage.WzImageHeaderByte_WithOffset: return ReadStringAtOffset(offset + ReadInt32()); default: return ""; diff --git a/MapleLib/WzLib/Util/WzBinaryWriter.cs b/MapleLib/WzLib/Util/WzBinaryWriter.cs index 46cae7f9..ec05a719 100644 --- a/MapleLib/WzLib/Util/WzBinaryWriter.cs +++ b/MapleLib/WzLib/Util/WzBinaryWriter.cs @@ -15,9 +15,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the along with this program. If not, see .*/ using System.Collections; -using System.Collections.Generic; using System.IO; -using System.Text; using MapleLib.MapleCryptoLib; namespace MapleLib.WzLib.Util @@ -29,7 +27,7 @@ public class WzBinaryWriter : BinaryWriter { #region Properties public WzMutableKey WzKey { get; set; } - public uint Hash { get; set; } + public uint Hash { get; } public Hashtable StringCache { get; set; } public WzHeader Header { get; set; } public bool LeaveOpen { get; internal set; } @@ -37,7 +35,15 @@ public class WzBinaryWriter : BinaryWriter #region Constructors public WzBinaryWriter(Stream output, byte[] WzIv) - : this(output, WzIv, false) { } + : this(output, WzIv, false) + { + this.Hash = 0; + } + + public WzBinaryWriter(Stream output, byte[] WzIv, uint Hash) + : this(output, WzIv, false) { + this.Hash = Hash; + } public WzBinaryWriter(Stream output, byte[] WzIv, bool leaveOpen) : base(output) @@ -49,6 +55,12 @@ public WzBinaryWriter(Stream output, byte[] WzIv, bool leaveOpen) #endregion #region Methods + /// + /// ?InternalSerializeString@@YAHPAGPAUIWzArchive@@EE@Z + /// + /// + /// + /// public void WriteStringValue(string s, int withoutOffset, int withOffset) { if (s.Length > 4 && StringCache.ContainsKey(s)) @@ -102,6 +114,7 @@ public override void Write(string value) if (value[i] > sbyte.MaxValue) { unicode = true; + break; } } @@ -224,7 +237,7 @@ public void WriteOffset(uint value) { uint encOffset = (uint)BaseStream.Position; encOffset = (encOffset - Header.FStart) ^ 0xFFFFFFFF; - encOffset *= Hash; + encOffset *= Hash; // could this be removed? encOffset -= MapleCryptoConstants.WZ_OffsetConstant; encOffset = RotateLeft(encOffset, (byte)(encOffset & 0x1F)); uint writeOffset = encOffset ^ (value - (Header.FStart * 2)); diff --git a/MapleLib/WzLib/Util/WzTool.cs b/MapleLib/WzLib/Util/WzTool.cs index 35552896..baeacd26 100644 --- a/MapleLib/WzLib/Util/WzTool.cs +++ b/MapleLib/WzLib/Util/WzTool.cs @@ -249,7 +249,7 @@ public static bool IsDataWzHotfixFile(string path) { byte firstByte = reader.ReadByte(); - result = firstByte == WzImage.WzImageHeaderByte; // check the first byte. It should be 0x73 that represends a WzImage + result = firstByte == WzImage.WzImageHeaderByte_WithoutOffset; // check the first byte. It should be 0x73 that represends a WzImage } return result; diff --git a/MapleLib/WzLib/WzDirectory.cs b/MapleLib/WzLib/WzDirectory.cs index 9454fca3..e98a077b 100644 --- a/MapleLib/WzLib/WzDirectory.cs +++ b/MapleLib/WzLib/WzDirectory.cs @@ -232,7 +232,7 @@ internal void ParseDirectory(bool lazyParse = false) reader.BaseStream.Position = rememberPos; fsize = reader.ReadCompressedInt(); checksum = reader.ReadCompressedInt(); - offset = reader.ReadOffset(); + offset = reader.ReadOffset(); // IWzArchive::Getposition(pArchive) if (type == 3) { @@ -263,14 +263,15 @@ internal void ParseDirectory(bool lazyParse = false) } } - // Offsets are calculated manually - if (this.wzFile != null && this.wzFile.b64BitClient) // This only applies for 64-bit client based WZ files. + // Offsets are calculated manually as a work-around, until I've figured out how + // the new offsets are calculated for 64-bit based WZ file.. + if (this.wzFile != null && this.wzFile.b64BitClient) { long startOffset = reader.BaseStream.Position; foreach (WzImage image in WzImages) { image.Offset = (uint)startOffset; - startOffset += image.BlockSize; // TODO: Test saving the wz after it is changed. This may break + startOffset += image.BlockSize; } } diff --git a/MapleLib/WzLib/WzFile.cs b/MapleLib/WzLib/WzFile.cs index 4fcea5d6..b0b513c1 100644 --- a/MapleLib/WzLib/WzFile.cs +++ b/MapleLib/WzLib/WzFile.cs @@ -224,10 +224,12 @@ internal WzFileParseStatus ParseMainWzDirectory(bool lazyParse = false) this.Header.Ident = reader.ReadString(4); this.Header.FSize = reader.ReadUInt64(); this.Header.FStart = reader.ReadUInt32(); - this.Header.Copyright = reader.ReadString((int)(Header.FStart - 17U)); + //this.Header.Copyright = reader.ReadNullTerminatedString(); + this.Header.Copyright = reader.ReadString((int)(Header.FStart - 17U)); byte unk1 = reader.ReadByte(); byte[] unk2 = reader.ReadBytes((int)(Header.FStart - (ulong)reader.BaseStream.Position)); + reader.Header = this.Header; this.wzVersionHeader = 0; @@ -258,8 +260,8 @@ internal WzFileParseStatus ParseMainWzDirectory(bool lazyParse = false) if (!this.b64BitClient) { this.versionHash = CheckAndGetVersionHash(wzVersionHeader, mapleStoryPatchVersion); + reader.Hash = this.versionHash; } - reader.Hash = this.versionHash; WzDirectory directory = new WzDirectory(reader, this.name, this.versionHash, this.WzIv, this); directory.ParseDirectory(); this.wzDir = directory; @@ -276,9 +278,9 @@ private bool TryDecodeWithWZVersionNumber(WzBinaryReader reader, int useWzVersio this.versionHash = CheckAndGetVersionHash(useWzVersionHeader, mapleStoryPatchVersion); if (this.versionHash == 0) // ugly hack, but that's the only way if the version number isnt known (nexon stores this in the .exe) return false; + reader.Hash = this.versionHash; } - reader.Hash = this.versionHash; long fallbackOffsetPosition = reader.BaseStream.Position; // save position to rollback to, if should parsing fail from here WzDirectory testDirectory; try @@ -309,8 +311,8 @@ private bool TryDecodeWithWZVersionNumber(WzBinaryReader reader, int useWzVersio switch (checkByte) { - case 0x73: - case 0x1b: + case WzImage.WzImageHeaderByte_WithoutOffset: // 0x73 + case WzImage.WzImageHeaderByte_WithOffset: { WzDirectory directory = new WzDirectory(reader, this.name, this.versionHash, this.WzIv, this); directory.ParseDirectory(lazyParse); @@ -511,10 +513,8 @@ public void SaveToDisk(string path, bool? bSaveAs64BitWzFile, WzMapleVersion sav WzTool.StringCache.Clear(); - using (WzBinaryWriter wzWriter = new WzBinaryWriter(File.Create(path), WzIv)) + using (WzBinaryWriter wzWriter = new WzBinaryWriter(File.Create(path), WzIv, versionHash)) { - wzWriter.Hash = versionHash; - uint totalLen = wzDir.GetImgOffsets(wzDir.GetOffsets(Header.FStart + 2)); Header.FSize = totalLen - Header.FStart; for (int i = 0; i < 4; i++) diff --git a/MapleLib/WzLib/WzImage.cs b/MapleLib/WzLib/WzImage.cs index 27d250af..1ea0a9cd 100644 --- a/MapleLib/WzLib/WzImage.cs +++ b/MapleLib/WzLib/WzImage.cs @@ -31,7 +31,8 @@ public class WzImage : WzObject, IPropertyContainer { //TODO: nest wzproperties in a wzsubproperty inside of WzImage - public const int WzImageHeaderByte = 0x73; + public const int WzImageHeaderByte_WithoutOffset = 0x73; + public const int WzImageHeaderByte_WithOffset = 0x1B; #region Fields internal bool parsed = false; @@ -355,7 +356,7 @@ public bool ParseImage(bool forceReadFromData = false) } return false; // unhandled for now, if it isnt an .lua image } - case WzImageHeaderByte: + case WzImageHeaderByte_WithoutOffset: { string prop = reader.ReadString(); ushort val = reader.ReadUInt16(); diff --git a/MapleLib/WzLib/WzImageProperty.cs b/MapleLib/WzLib/WzImageProperty.cs index d688dfd5..babf06a1 100644 --- a/MapleLib/WzLib/WzImageProperty.cs +++ b/MapleLib/WzLib/WzImageProperty.cs @@ -193,10 +193,10 @@ internal static WzExtended ParseExtendedProp(WzBinaryReader reader, uint offset, switch (reader.ReadByte()) { case 0x01: - case 0x1B: + case WzImage.WzImageHeaderByte_WithOffset: return ExtractMore(reader, offset, endOfBlock, name, reader.ReadStringAtOffset(offset + reader.ReadInt32()), parent, imgParent); case 0x00: - case 0x73: + case WzImage.WzImageHeaderByte_WithoutOffset: return ExtractMore(reader, offset, endOfBlock, name, "", parent, imgParent); default: throw new System.Exception("Invalid byte read at ParseExtendedProp"); diff --git a/MapleLib/WzLib/WzProperties/WzBinaryProperty.cs b/MapleLib/WzLib/WzProperties/WzBinaryProperty.cs index 60a71de4..1de0a7d1 100644 --- a/MapleLib/WzLib/WzProperties/WzBinaryProperty.cs +++ b/MapleLib/WzLib/WzProperties/WzBinaryProperty.cs @@ -93,7 +93,7 @@ public override void SetValue(object value) public override void WriteValue(WzBinaryWriter writer) { byte[] data = GetBytes(false); - writer.WriteStringValue("Sound_DX8", 0x73, 0x1B); + writer.WriteStringValue("Sound_DX8", WzImage.WzImageHeaderByte_WithoutOffset, WzImage.WzImageHeaderByte_WithOffset); writer.Write((byte)0); writer.WriteCompressedInt(data.Length); writer.WriteCompressedInt(len_ms); diff --git a/MapleLib/WzLib/WzProperties/WzCanvasProperty.cs b/MapleLib/WzLib/WzProperties/WzCanvasProperty.cs index 54fd16a5..26590ff4 100644 --- a/MapleLib/WzLib/WzProperties/WzCanvasProperty.cs +++ b/MapleLib/WzLib/WzProperties/WzCanvasProperty.cs @@ -162,9 +162,9 @@ public override WzImageProperty GetFromPath(string path) } return ret; } - public override void WriteValue(MapleLib.WzLib.Util.WzBinaryWriter writer) + public override void WriteValue(WzBinaryWriter writer) { - writer.WriteStringValue("Canvas", 0x73, 0x1B); + writer.WriteStringValue("Canvas", WzImage.WzImageHeaderByte_WithoutOffset, WzImage.WzImageHeaderByte_WithOffset); writer.Write((byte)0); if (properties.Count > 0) // subproperty in the canvas { diff --git a/MapleLib/WzLib/WzProperties/WzConvexProperty.cs b/MapleLib/WzLib/WzProperties/WzConvexProperty.cs index 2d46ec03..687739ee 100644 --- a/MapleLib/WzLib/WzProperties/WzConvexProperty.cs +++ b/MapleLib/WzLib/WzProperties/WzConvexProperty.cs @@ -130,11 +130,13 @@ public override WzImageProperty GetFromPath(string path) } return ret; } - public override void WriteValue(MapleLib.WzLib.Util.WzBinaryWriter writer) + public override void WriteValue(WzBinaryWriter writer) { List extendedProps = new List(properties.Count); - foreach (WzImageProperty prop in properties) if (prop is WzExtended) extendedProps.Add((WzExtended)prop); - writer.WriteStringValue("Shape2D#Convex2D", 0x73, 0x1B); + foreach (WzImageProperty prop in properties) + if (prop is WzExtended) + extendedProps.Add((WzExtended)prop); + writer.WriteStringValue("Shape2D#Convex2D", WzImage.WzImageHeaderByte_WithoutOffset, WzImage.WzImageHeaderByte_WithOffset); writer.WriteCompressedInt(extendedProps.Count); foreach (WzImageProperty imgProperty in properties) diff --git a/MapleLib/WzLib/WzProperties/WzStringProperty.cs b/MapleLib/WzLib/WzProperties/WzStringProperty.cs index 7643cd48..7b21ff66 100644 --- a/MapleLib/WzLib/WzProperties/WzStringProperty.cs +++ b/MapleLib/WzLib/WzProperties/WzStringProperty.cs @@ -59,7 +59,7 @@ public override WzImageProperty DeepClone() /// The name of the property /// public override string Name { get { return name; } set { name = value; } } - public override void WriteValue(MapleLib.WzLib.Util.WzBinaryWriter writer) + public override void WriteValue(WzBinaryWriter writer) { writer.Write((byte)8); writer.WriteStringValue(Value, 0, 1); diff --git a/MapleLib/WzLib/WzProperties/WzSubProperty.cs b/MapleLib/WzLib/WzProperties/WzSubProperty.cs index 1a187f25..4232c2c9 100644 --- a/MapleLib/WzLib/WzProperties/WzSubProperty.cs +++ b/MapleLib/WzLib/WzProperties/WzSubProperty.cs @@ -130,7 +130,7 @@ public override WzImageProperty GetFromPath(string path) } return ret; } - public override void WriteValue(MapleLib.WzLib.Util.WzBinaryWriter writer) + public override void WriteValue(WzBinaryWriter writer) { bool bIsLuaProperty = false; if (properties.Count == 1 && properties[0] is WzLuaProperty) @@ -138,7 +138,7 @@ public override void WriteValue(MapleLib.WzLib.Util.WzBinaryWriter writer) bIsLuaProperty = true; } if (!bIsLuaProperty) - writer.WriteStringValue("Property", 0x73, 0x1B); + writer.WriteStringValue("Property", WzImage.WzImageHeaderByte_WithoutOffset, WzImage.WzImageHeaderByte_WithOffset); WzImageProperty.WritePropertyList(writer, properties); } diff --git a/MapleLib/WzLib/WzProperties/WzUOLProperty.cs b/MapleLib/WzLib/WzProperties/WzUOLProperty.cs index 6c299d45..633c8dfc 100644 --- a/MapleLib/WzLib/WzProperties/WzUOLProperty.cs +++ b/MapleLib/WzLib/WzProperties/WzUOLProperty.cs @@ -105,9 +105,9 @@ public override WzImageProperty GetFromPath(string path) /// public override WzPropertyType PropertyType { get { return WzPropertyType.UOL; } } - public override void WriteValue(MapleLib.WzLib.Util.WzBinaryWriter writer) + public override void WriteValue(WzBinaryWriter writer) { - writer.WriteStringValue("UOL", 0x73, 0x1B); + writer.WriteStringValue("UOL", WzImage.WzImageHeaderByte_WithoutOffset, WzImage.WzImageHeaderByte_WithOffset); writer.Write((byte)0); writer.WriteStringValue(Value, 0, 1); } diff --git a/MapleLib/WzLib/WzProperties/WzVectorProperty.cs b/MapleLib/WzLib/WzProperties/WzVectorProperty.cs index c6a1eefd..2cf8120d 100644 --- a/MapleLib/WzLib/WzProperties/WzVectorProperty.cs +++ b/MapleLib/WzLib/WzProperties/WzVectorProperty.cs @@ -69,9 +69,9 @@ public override WzImageProperty DeepClone() /// The WzPropertyType of the property /// public override WzPropertyType PropertyType { get { return WzPropertyType.Vector; } } - public override void WriteValue(MapleLib.WzLib.Util.WzBinaryWriter writer) + public override void WriteValue(WzBinaryWriter writer) { - writer.WriteStringValue("Shape2D#Vector2D", 0x73, 0x1B); + writer.WriteStringValue("Shape2D#Vector2D", WzImage.WzImageHeaderByte_WithoutOffset, WzImage.WzImageHeaderByte_WithOffset); writer.WriteCompressedInt(X.Value); writer.WriteCompressedInt(Y.Value); } diff --git a/MapleLib/WzSettings.cs b/MapleLib/WzSettings.cs index 027c3ae2..6af643d9 100644 --- a/MapleLib/WzSettings.cs +++ b/MapleLib/WzSettings.cs @@ -15,9 +15,6 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the along with this program. If not, see .*/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using MapleLib.WzLib.WzProperties; using System.Reflection; using MapleLib.WzLib.WzStructure;