diff --git a/MapleLib/WzLib/Util/WzBinaryReader.cs b/MapleLib/WzLib/Util/WzBinaryReader.cs
index 7016b223..f76c4621 100644
--- a/MapleLib/WzLib/Util/WzBinaryReader.cs
+++ b/MapleLib/WzLib/Util/WzBinaryReader.cs
@@ -40,6 +40,23 @@ public WzBinaryReader(Stream input, byte[] WzIv)
#endregion
#region Methods
+ ///
+ /// Sets the base stream position to the header FStart + offset
+ ///
+ ///
+ public void SetOffsetFromFStartToPosition(int offset)
+ {
+ BaseStream.Position = Header.FStart + offset;
+ }
+
+ public void RollbackStreamPosition(int byOffset)
+ {
+ if (BaseStream.Position < byOffset)
+ throw new Exception("Cant rollback stream position below 0");
+
+ BaseStream.Position -= byOffset;
+ }
+
public string ReadStringAtOffset(long Offset)
{
return ReadStringAtOffset(Offset, false);
diff --git a/MapleLib/WzLib/Util/WzBinaryWriter.cs b/MapleLib/WzLib/Util/WzBinaryWriter.cs
index 0e0e4d88..fbbe9724 100644
--- a/MapleLib/WzLib/Util/WzBinaryWriter.cs
+++ b/MapleLib/WzLib/Util/WzBinaryWriter.cs
@@ -14,9 +14,11 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* You should have received a copy of the GNU General Public License
along with this program. If not, see .*/
+using System;
using System.Collections;
using System.IO;
using MapleLib.MapleCryptoLib;
+using MapleLib.WzLib.WzStructure.Enums;
namespace MapleLib.WzLib.Util
{
@@ -59,10 +61,12 @@ public WzBinaryWriter(Stream output, byte[] WzIv, bool leaveOpen)
/// ?InternalSerializeString@@YAHPAGPAUIWzArchive@@EE@Z
///
///
- /// 0x73
- /// 0x1B
+ /// bExistID_0x73 0x73
+ /// bNewID_0x1b 0x1B
public void WriteStringValue(string s, int withoutOffset, int withOffset)
{
+ // if length is > 4 and the string cache contains the string
+ // writes the offset instead
if (s.Length > 4 && StringCache.ContainsKey(s))
{
Write((byte)withOffset);
@@ -80,24 +84,37 @@ public void WriteStringValue(string s, int withoutOffset, int withOffset)
}
}
- public void WriteWzObjectValue(string s, byte type)
+ ///
+ /// Writes the Wz object value
+ ///
+ ///
+ ///
+ ///
+ /// true if the Wz object value is written as an offset in the Wz file, else if not
+ public bool WriteWzObjectValue(string stringObjectValue, WzDirectoryType type)
{
- string storeName = string.Format("{0}_{1}", type, s);
- if (s.Length > 4 && StringCache.ContainsKey(storeName))
+ string storeName = string.Format("{0}_{1}", (byte) type, stringObjectValue);
+
+ // if length is > 4 and the string cache contains the string
+ // writes the offset instead
+ if (stringObjectValue.Length > 4 && StringCache.ContainsKey(storeName))
{
- Write((byte)2);
+ Write((byte)WzDirectoryType.RetrieveStringFromOffset_2); // 2
Write((int)StringCache[storeName]);
+
+ return true;
}
else
{
int sOffset = (int)(this.BaseStream.Position - Header.FStart);
- Write(type);
- Write(s);
+ Write((byte)type);
+ Write(stringObjectValue);
if (!StringCache.ContainsKey(storeName))
{
StringCache[storeName] = sOffset;
}
}
+ return false;
}
public override void Write(string value)
diff --git a/MapleLib/WzLib/WzDirectory.cs b/MapleLib/WzLib/WzDirectory.cs
index 935c150e..81a54be8 100644
--- a/MapleLib/WzLib/WzDirectory.cs
+++ b/MapleLib/WzLib/WzDirectory.cs
@@ -230,6 +230,7 @@ internal void ParseDirectory(bool lazyParse = false)
}
default:
{
+ reader.PrintHexBytes(20);
throw new Exception("[WzDirectory] Unknown directory. type = " + type);
}
}
diff --git a/MapleLib/WzLib/WzFile.cs b/MapleLib/WzLib/WzFile.cs
index 683e1913..94778f0b 100644
--- a/MapleLib/WzLib/WzFile.cs
+++ b/MapleLib/WzLib/WzFile.cs
@@ -40,15 +40,16 @@ public class WzFile : WzObject
internal WzDirectory wzDir;
internal WzHeader header;
internal string name = "";
+
internal ushort wzVersionHeader = 0;
internal const ushort wzVersionHeader64bit_start = 770; // 777 for KMS, GMS v230 uses 778.. wut
+
internal uint versionHash = 0;
internal short mapleStoryPatchVersion = 0;
internal WzMapleVersion maplepLocalVersion;
internal MapleStoryLocalisation mapleLocaleVersion = MapleStoryLocalisation.Not_Known;
- internal bool b64BitClient = false; // KMS update after Q4 2021, ver 1.2.357
- internal bool b64BitClient_withVerHeader = false; //
+ internal bool wz_withEncryptVersionHeader = true; // KMS update after Q4 2021, ver 1.2.357
internal byte[] WzIv;
#endregion
@@ -102,7 +103,7 @@ public override WzObjectType ObjectType
///
public MapleStoryLocalisation MapleLocaleVersion { get { return mapleLocaleVersion; } private set { } }
- public bool Is64BitWzFile { get { return b64BitClient; } private set { } }
+ public bool Is64BitWzFile { get { return !wz_withEncryptVersionHeader; } private set { } }
public override WzObject Parent { get { return null; } internal set { } }
@@ -166,9 +167,6 @@ public WzFile(string filePath, short gameVersion, WzMapleVersion version)
}
else
this.WzIv = WzTool.GetIvByMapleVersion(version);
-
- string[] filePathSplit = Regex.Split(filePath, @"\\");
- this.b64BitClient = filePathSplit.Contains("Data"); // TODO: Find a better way of identifying 64-bit client/ WZ from the WZ files instead. This might break if it isnt installed in the right path, esp. private servers
}
///
@@ -183,8 +181,6 @@ public WzFile(string filePath, byte[] wzIv)
maplepLocalVersion = WzMapleVersion.CUSTOM;
this.WzIv = wzIv;
-
- this.b64BitClient = false; // TODO
}
///
@@ -235,15 +231,15 @@ internal WzFileParseStatus ParseMainWzDirectory(bool lazyParse = false)
// the value of wzVersionHeader is less important. It is used for reading/writing from/to WzFile Header, and calculating the versionHash.
// it can be any number if the client is 64-bit. Assigning 777 is just for convenience when calculating the versionHash.
- this.wzVersionHeader = b64BitClient && !b64BitClient_withVerHeader ? wzVersionHeader64bit_start : reader.ReadUInt16();
+ this.wzVersionHeader = this.wz_withEncryptVersionHeader ? reader.ReadUInt16() : wzVersionHeader64bit_start;
if (mapleStoryPatchVersion == -1)
{
// for 64-bit client, return immediately if version 777 works correctly.
// -- the latest KMS update seems to have changed it to 778? 779?
- if (b64BitClient)
+ if (!this.wz_withEncryptVersionHeader)
{
- for (ushort maplestoryVerToDecode = wzVersionHeader64bit_start; maplestoryVerToDecode < wzVersionHeader64bit_start + 20; maplestoryVerToDecode++)
+ for (ushort maplestoryVerToDecode = wzVersionHeader64bit_start; maplestoryVerToDecode < wzVersionHeader64bit_start + 10; maplestoryVerToDecode++) // 770 ~ 780
{
if (TryDecodeWithWZVersionNumber(reader, wzVersionHeader, maplestoryVerToDecode, lazyParse))
{
@@ -290,40 +286,40 @@ private void Check64BitClient(WzBinaryReader reader)
{
if (this.Header.FSize >= 2)
{
- this.wzVersionHeader = reader.ReadUInt16();
- if (this.wzVersionHeader > 0xff)
+ reader.BaseStream.Position = this.header.FStart; // go back to 0x3C
+
+ int encver = reader.ReadUInt16();
+ if (encver > 0xff) // encver always less than 256
{
- b64BitClient = true;
+ this.wz_withEncryptVersionHeader = false;
}
- else if (this.wzVersionHeader == 0x80)
+ else if (encver == 0x80)
{
- // there's an exceptional case that the first field of data part is a compressed int which determines the property count,
+ // 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 WzFile won't greater than 65536 (0xFFFF).
+ // 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 (this.Header.FSize >= 5)
{
reader.BaseStream.Position = this.header.FStart; // go back to 0x3C
- int propCount = reader.ReadCompressedInt();
- if (propCount > 0 && (propCount & 0xFF) == 0 && propCount <= 0xFFFF)
+ int propCount = reader.ReadInt32();
+ if (propCount > 0 && (propCount & 0xff) == 0 && propCount <= 0xffff)
{
- b64BitClient = true;
+ this.wz_withEncryptVersionHeader = false;
}
}
- } else if (this.wzVersionHeader == 0x21) // or 33
+ } else
{
- b64BitClient = true;
- // but read the header
- // the latest KMS seems to include this back in again.. damn
- this.b64BitClient_withVerHeader = true; // ugly hack, but until i've found a better way without breaking compatibility of old WZs.
+ // old wz file with header version
}
}
else
{
- // Obviously, if data part have only 1 byte, encVer must be deleted.
- b64BitClient = true;
+ // Obviously, if data part have only 1 byte, encver must be deleted.
+ this.wz_withEncryptVersionHeader = false;
}
+
// reset position
reader.BaseStream.Position = this.Header.FStart;
}
@@ -587,7 +583,7 @@ public void SaveToDisk(string path, bool? override_saveAs64BitWZ, WzMapleVersion
// MapleStory UserKey
bool bIsWzUserKeyDefault = MapleCryptoConstants.IsDefaultMapleStoryUserKey(); // check if its saving to the same UserKey.
// Save WZ as 64-bit wz format
- bool bSaveAs64BitWZ = override_saveAs64BitWZ != null ? (bool)override_saveAs64BitWZ : b64BitClient;
+ bool bWZ_withEncryptVersionHeader = this.wz_withEncryptVersionHeader;
CreateWZVersionHash();
wzDir.SetVersionHash(versionHash);
@@ -605,7 +601,7 @@ public void SaveToDisk(string path, bool? override_saveAs64BitWZ, WzMapleVersion
{
wzWriter.Hash = versionHash;
- uint totalLen = wzDir.GetImgOffsets(wzDir.GetOffsets(Header.FStart + (bSaveAs64BitWZ && !this.b64BitClient_withVerHeader ? 0 : 2u)));
+ uint totalLen = wzDir.GetImgOffsets(wzDir.GetOffsets(Header.FStart + (bWZ_withEncryptVersionHeader ? 2u: 0)));
Header.FSize = totalLen - Header.FStart;
for (int i = 0; i < 4; i++)
{
@@ -620,7 +616,7 @@ public void SaveToDisk(string path, bool? override_saveAs64BitWZ, WzMapleVersion
{
wzWriter.Write(new byte[(int)extraHeaderLength]);
}
- if (!bSaveAs64BitWZ || this.b64BitClient_withVerHeader)
+ if (bWZ_withEncryptVersionHeader)
wzWriter.Write(wzVersionHeader);
wzWriter.Header = Header;
diff --git a/MapleLib/WzLib/WzStructure/MapInfo.cs b/MapleLib/WzLib/WzStructure/MapInfo.cs
index ecb17f4b..786adf81 100644
--- a/MapleLib/WzLib/WzStructure/MapInfo.cs
+++ b/MapleLib/WzLib/WzStructure/MapInfo.cs
@@ -310,7 +310,7 @@ public MapInfo(WzImage image, string strMapName, string strStreetName, string st
fs = InfoTool.GetFloat(prop);
break;
case "protectItem":
- protectItem = InfoTool.GetInt(prop);
+ protectItem = InfoTool.GetInt(prop); // could also be a WzSubProperty in later versions. "Map002.wz\\Map\\Map2\\211000200.img\\info\\protectItem"
break;
case "createMobInterval":
createMobInterval = InfoTool.GetInt(prop);
diff --git a/MapleLib/WzSettings.cs b/MapleLib/WzSettings.cs
index 12aa2d9a..85835ec4 100644
--- a/MapleLib/WzSettings.cs
+++ b/MapleLib/WzSettings.cs
@@ -15,18 +15,11 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
along with this program. If not, see .*/
using System;
-using MapleLib.WzLib.WzProperties;
using System.Reflection;
-using MapleLib.WzLib.WzStructure;
using System.IO;
using Newtonsoft.Json.Linq;
using System.Drawing;
-using System.Collections;
using Newtonsoft.Json;
-using Spine;
-using System.Security.Principal;
-using Microsoft.Xna.Framework.Media;
-using System.Windows.Controls;
namespace MapleLib.WzLib
{