-
Notifications
You must be signed in to change notification settings - Fork 164
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[MapleLib] Fixed a parsing issue with the new KMS Base.wz without WzI…
…mage
- Loading branch information
1 parent
1669125
commit 63e2d72
Showing
5 changed files
with
98 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,7 +39,7 @@ public class WzFile : WzObject | |
internal WzDirectory wzDir; | ||
internal WzHeader header; | ||
internal string name = ""; | ||
internal short version = 0; | ||
internal short wzVersionHeader = 0; | ||
internal uint versionHash = 0; | ||
internal short mapleStoryPatchVersion = 0; | ||
internal WzMapleVersion maplepLocalVersion; | ||
|
@@ -141,9 +141,10 @@ public WzFile(string filePath, short gameVersion, WzMapleVersion version) | |
|
||
if (version == WzMapleVersion.GETFROMZLZ) | ||
{ | ||
FileStream zlzStream = File.OpenRead(Path.Combine(Path.GetDirectoryName(filePath), "ZLZ.dll")); | ||
this.WzIv = Util.WzKeyGenerator.GetIvFromZlz(zlzStream); | ||
zlzStream.Close(); | ||
using (FileStream zlzStream = File.OpenRead(Path.Combine(Path.GetDirectoryName(filePath), "ZLZ.dll"))) | ||
{ | ||
this.WzIv = Util.WzKeyGenerator.GetIvFromZlz(zlzStream); | ||
} | ||
} | ||
else | ||
this.WzIv = WzTool.GetIvByMapleVersion(version); | ||
|
@@ -203,19 +204,21 @@ internal WzFileParseStatus ParseMainWzDirectory(bool lazyParse = false) | |
this.Header.FStart = reader.ReadUInt32(); | ||
this.Header.Copyright = reader.ReadString((int)(Header.FStart - 17U)); | ||
|
||
reader.ReadBytes(1); | ||
reader.ReadBytes((int)(Header.FStart - (ulong)reader.BaseStream.Position)); | ||
byte unk1 = reader.ReadByte(); | ||
byte[] unk2 = reader.ReadBytes((int)(Header.FStart - (ulong)reader.BaseStream.Position)); | ||
reader.Header = this.Header; | ||
this.version = reader.ReadInt16(); | ||
this.wzVersionHeader = reader.ReadInt16(); | ||
|
||
if (mapleStoryPatchVersion == -1) | ||
{ | ||
// this step is actually not needed if we actually know the maplestory patch version (the client .exe), but since we dont.. | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
lastbattle
Author
Owner
|
||
// we'll need a bruteforce way around it. | ||
const short MAX_PATCH_VERSION = 10000; // wont be reached for the forseeable future. | ||
|
||
for (int j = 0; j < MAX_PATCH_VERSION; j++) | ||
{ | ||
this.mapleStoryPatchVersion = (short)j; | ||
this.versionHash = CheckAndGetVersionHash(version, mapleStoryPatchVersion); | ||
this.versionHash = CheckAndGetVersionHash(wzVersionHeader, 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) | ||
continue; | ||
|
||
|
@@ -235,61 +238,77 @@ internal WzFileParseStatus ParseMainWzDirectory(bool lazyParse = false) | |
continue; | ||
} | ||
|
||
// test the image and see if its correct by parsing it | ||
bool bCloseTestDirectory = true; | ||
try | ||
{ | ||
List<WzImage> childImages = testDirectory.GetChildImages(); | ||
if (childImages.Count == 0) // coincidentally in msea v194 Map001.wz, the hash matches exactly using mapleStoryPatchVersion of 113, and it fails to decrypt later on (probably 1 in a million chance). | ||
{ | ||
reader.BaseStream.Position = position; // reset | ||
continue; | ||
} | ||
WzImage testImage = childImages[0]; | ||
|
||
try | ||
WzImage testImage = testDirectory.WzImages.FirstOrDefault(); | ||
if (testImage != null) | ||
{ | ||
reader.BaseStream.Position = testImage.Offset; | ||
byte checkByte = reader.ReadByte(); | ||
reader.BaseStream.Position = position; | ||
|
||
switch (checkByte) | ||
try | ||
{ | ||
case 0x73: | ||
case 0x1b: | ||
{ | ||
WzDirectory directory = new WzDirectory(reader, this.name, this.versionHash, this.WzIv, this); | ||
directory.ParseDirectory(lazyParse); | ||
this.wzDir = directory; | ||
return WzFileParseStatus.Success; | ||
} | ||
case 0x30: | ||
case 0x6C: // idk | ||
case 0xBC: // Map002.wz? KMST? | ||
default: | ||
{ | ||
Helpers.ErrorLogger.Log(Helpers.ErrorLevel.MissingFeature, | ||
string.Format("[WzFile.cs] New Wz image header found. checkByte = {0}. File Name = {1}", checkByte, Name)); | ||
// log or something | ||
break; | ||
} | ||
reader.BaseStream.Position = testImage.Offset; | ||
byte checkByte = reader.ReadByte(); | ||
reader.BaseStream.Position = position; | ||
|
||
switch (checkByte) | ||
{ | ||
case 0x73: | ||
case 0x1b: | ||
{ | ||
WzDirectory directory = new WzDirectory(reader, this.name, this.versionHash, this.WzIv, this); | ||
directory.ParseDirectory(lazyParse); | ||
this.wzDir = directory; | ||
|
||
return WzFileParseStatus.Success; | ||
} | ||
case 0x30: | ||
case 0x6C: // idk | ||
case 0xBC: // Map002.wz? KMST? | ||
default: | ||
{ | ||
Helpers.ErrorLogger.Log(Helpers.ErrorLevel.MissingFeature, | ||
string.Format("[WzFile.cs] New Wz image header found. checkByte = {0}. File Name = {1}", checkByte, Name)); | ||
// log or something | ||
break; | ||
} | ||
} | ||
reader.BaseStream.Position = position; // reset | ||
} | ||
reader.BaseStream.Position = position; // reset | ||
} | ||
catch | ||
catch | ||
{ | ||
reader.BaseStream.Position = position; // reset | ||
} | ||
} | ||
else // if there's no image in the WZ file (new KMST Base.wz), test the directory instead | ||
{ | ||
reader.BaseStream.Position = position; // reset | ||
// coincidentally in msea v194 Map001.wz, the hash matches exactly using mapleStoryPatchVersion of 113, and it fails to decrypt later on (probably 1 in a million chance? o_O). | ||
if (mapleStoryPatchVersion == 113) | ||
{ | ||
// hack for now | ||
reader.BaseStream.Position = position; // reset | ||
continue; | ||
} | ||
else | ||
{ | ||
this.wzDir = testDirectory; | ||
bCloseTestDirectory = false; | ||
} | ||
} | ||
return WzFileParseStatus.Success; | ||
} | ||
finally | ||
{ | ||
testDirectory.Dispose(); | ||
if (bCloseTestDirectory) | ||
testDirectory.Dispose(); | ||
} | ||
} | ||
//parseErrorMessage = "Error with game version hash : The specified game version is incorrect and WzLib was unable to determine the version itself"; | ||
return WzFileParseStatus.Error_Game_Ver_Hash; | ||
} | ||
else | ||
{ | ||
this.versionHash = CheckAndGetVersionHash(version, mapleStoryPatchVersion); | ||
this.versionHash = CheckAndGetVersionHash(wzVersionHeader, mapleStoryPatchVersion); | ||
reader.Hash = this.versionHash; | ||
WzDirectory directory = new WzDirectory(reader, this.name, this.versionHash, this.WzIv, this); | ||
directory.ParseDirectory(); | ||
|
@@ -343,7 +362,7 @@ private void CreateWZVersionHash() | |
b = (versionHash >> 16) & 0xFF, | ||
c = (versionHash >> 8) & 0xFF, | ||
d = versionHash & 0xFF; | ||
version = (byte)~(a ^ b ^ c ^ d); | ||
wzVersionHeader = (byte)~(a ^ b ^ c ^ d); | ||
} | ||
|
||
/// <summary> | ||
|
@@ -376,11 +395,12 @@ public void SaveToDisk(string path, WzMapleVersion savingToPreferredWzVer = WzMa | |
} | ||
|
||
WzTool.StringCache.Clear(); | ||
uint totalLen = wzDir.GetImgOffsets(wzDir.GetOffsets(Header.FStart + 2)); | ||
|
||
using (WzBinaryWriter wzWriter = new WzBinaryWriter(File.Create(path), WzIv)) | ||
{ | ||
wzWriter.Hash = versionHash; | ||
|
||
uint totalLen = wzDir.GetImgOffsets(wzDir.GetOffsets(Header.FStart + 2)); | ||
Header.FSize = totalLen - Header.FStart; | ||
for (int i = 0; i < 4; i++) | ||
{ | ||
|
@@ -395,7 +415,7 @@ public void SaveToDisk(string path, WzMapleVersion savingToPreferredWzVer = WzMa | |
{ | ||
wzWriter.Write(new byte[(int)extraHeaderLength]); | ||
} | ||
wzWriter.Write(version); | ||
wzWriter.Write(wzVersionHeader); | ||
wzWriter.Header = Header; | ||
wzDir.SaveDirectory(wzWriter); | ||
wzWriter.StringCache.Clear(); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
For some regions of Maplestory, the version is stored in the EXE file. You can get the version by using System.Diagnostics.FileVersionInfo.FileVersion on the EXE file. To see the version, right click on the Maplestory.exe file and click on "Details" then look at the FileVersion provided by the details. You could use this version as a potential first try.
I see it's used in KMST, KMS, and GMS.