/// <summary> /// Parses a wz list file on the disk /// </summary> /// <param name="filePath">Path to the wz file</param> /// <param name="wzIv"></param> public static List <string> ParseListFile(string filePath, byte[] wzIv) { var listEntries = new List <string>(); var wzFileBytes = File.ReadAllBytes(filePath); var wzParser = new WzBinaryReader(new MemoryStream(wzFileBytes), wzIv); while (wzParser.PeekChar() != -1) { var len = wzParser.ReadInt32(); var strChrs = new char[len]; for (var i = 0; i < len; i++) { strChrs[i] = (char)wzParser.ReadInt16(); } wzParser.ReadUInt16(); //encrypted null var decryptedStr = wzParser.DecryptString(strChrs); listEntries.Add(decryptedStr); } wzParser.Close(); var lastIndex = listEntries.Count - 1; var lastEntry = listEntries[lastIndex]; listEntries[lastIndex] = lastEntry.Substring(0, lastEntry.Length - 1) + "g"; return(listEntries); }
/// <summary> /// Parses the wz list file /// </summary> public void ParseWzFile() { //WzTools.CreateWzKey(WzMapleVersion.GMS);//what? WzBinaryReader wzParser = new WzBinaryReader(new MemoryStream(wzFileBytes), WzIv); while (wzParser.PeekChar() != -1) { int Len = wzParser.ReadInt32(); char[] List = new char[Len]; for (int i = 0; i < Len; i++) { List[i] = (char)wzParser.ReadInt16(); } wzParser.ReadUInt16(); string Decrypted = wzParser.DecryptString(List); if (wzParser.PeekChar() == -1) { if (Decrypted[Decrypted.Length - 1] == '/') { Decrypted = Decrypted.TrimEnd("/".ToCharArray()) + "g"; // Last char should always be a g (.img) } } listEntries.Add(Decrypted); } wzParser.Close(); }
internal void ParseMainWzDirectory() { if (FilePath == null) { _log.Error("Path is null"); return; } if (!File.Exists(FilePath)) { var message = $"WZ File does not exist at path: '{FilePath}'"; _log.Error(message); throw new FileNotFoundException(message); } var reader = new WzBinaryReader(File.Open(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read), _wzIv); Header = new WzHeader { Ident = reader.ReadString(4), FSize = reader.ReadUInt64(), FStart = reader.ReadUInt32(), Copyright = reader.ReadNullTerminatedString() }; reader.ReadBytes((int)(Header.FStart - reader.BaseStream.Position)); reader.Header = Header; _version = reader.ReadInt16(); if (Version == -1 && !CalculateVersion(reader)) { throw new InvalidDataException( "Error with game version hash : The specified game version is incorrect"); } _versionHash = GetVersionHash(_version, Version); reader.Hash = _versionHash; var tempDirectory = new WzDirectory(reader, Name, _versionHash, _wzIv, this); tempDirectory.ParseDirectory(); WzDirectory = tempDirectory; }
private void ParseMainWzDirectory(byte[] wzIv) { if (FilePath == null) { throw new ArgumentNullException(nameof(FilePath), "WZ File path is null"); } if (!File.Exists(FilePath)) { throw new FileNotFoundException($"WZ File does not exist at path: '{FilePath}'"); } var mmf = MemoryMappedFile.CreateFromFile(FilePath); var reader = new WzBinaryReader(mmf.CreateViewStream(), wzIv); Header = new WzHeader { Ident = reader.ReadString(4), FSize = reader.ReadUInt64(), FStart = reader.ReadUInt32(), Copyright = reader.ReadNullTerminatedString() }; reader.ReadBytes((int)(Header.FStart - reader.BaseStream.Position)); reader.Header = Header; _version = reader.ReadInt16(); if (Version == -1 && !CalculateVersion(reader)) { throw new InvalidDataException( "Error with game version hash : The specified game version is incorrect"); } _versionHash = GetVersionHash(_version, Version); reader.Hash = _versionHash; var tempDirectory = new WzDirectory(reader, Name, _versionHash, wzIv, this); tempDirectory.ParseDirectory(); WzDirectory = tempDirectory; }
/// <summary> /// Parses the wz list file /// </summary> public void ParseWzFile() { using (WzBinaryReader wzParser = new WzBinaryReader(new MemoryStream(mWzFileBytes), mWzIv)) { while (wzParser.PeekChar() != -1) { int Len = wzParser.ReadInt32(); char[] List = new char[Len]; for (int i = 0; i < Len; i++) { List[i] = (char)wzParser.ReadInt16(); } wzParser.ReadUInt16(); string Decrypted = wzParser.DecryptString(List); if (wzParser.PeekChar() == -1) { if (Decrypted[Decrypted.Length - 1] == '/') { Decrypted = Decrypted.TrimEnd("/".ToCharArray()) + "g"; // Last char should always be a g (.img) } } mListEntries.Add(Decrypted); } } }
/// <summary> /// Parse directories in the WZ file /// </summary> /// <param name="parseErrorMessage"></param> /// <param name="lazyParse">Only load the firt WzDirectory found if true</param> /// <returns></returns> internal bool ParseMainWzDirectory(out string parseErrorMessage, bool lazyParse = false) { if (this.path == null) { Helpers.ErrorLogger.Log(Helpers.ErrorLevel.Critical, "[Error] Path is null"); parseErrorMessage = "[Error] Path is null"; return(false); } WzBinaryReader reader = new WzBinaryReader(File.Open(this.path, FileMode.Open, FileAccess.Read, FileShare.Read), WzIv); this.Header = new WzHeader(); this.Header.Ident = reader.ReadString(4); this.Header.FSize = reader.ReadUInt64(); this.Header.FStart = reader.ReadUInt32(); this.Header.Copyright = reader.ReadNullTerminatedString(); reader.ReadBytes((int)(Header.FStart - reader.BaseStream.Position)); reader.Header = this.Header; this.version = reader.ReadInt16(); if (mapleStoryPatchVersion == -1) { 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 = GetVersionHash(version, mapleStoryPatchVersion); if (this.versionHash == 0) { continue; } reader.Hash = this.versionHash; long position = reader.BaseStream.Position; // save position to rollback to, if should parsing fail from here WzDirectory testDirectory; try { testDirectory = new WzDirectory(reader, this.name, this.versionHash, this.WzIv, this); testDirectory.ParseDirectory(lazyParse); } catch { reader.BaseStream.Position = position; continue; } 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 { 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; parseErrorMessage = "Success"; return(true); } default: { Helpers.ErrorLogger.Log(Helpers.ErrorLevel.MissingFeature, "New Wz image header found. checkByte = " + checkByte); // log or something break; } } reader.BaseStream.Position = position; // reset } catch { reader.BaseStream.Position = position; // reset } } finally { testDirectory.Dispose(); } } parseErrorMessage = "Error with game version hash : The specified game version is incorrect and WzLib was unable to determine the version itself"; } else { this.versionHash = GetVersionHash(version, mapleStoryPatchVersion); reader.Hash = this.versionHash; WzDirectory directory = new WzDirectory(reader, this.name, this.versionHash, this.WzIv, this); directory.ParseDirectory(); this.wzDir = directory; } parseErrorMessage = "Success"; return(true); }
/// <summary> /// Parses the WzDirectory /// </summary> internal void ParseDirectory() { int entryCount = reader.ReadCompressedInt(); for (int i = 0; i < entryCount; i++) { byte type = reader.ReadByte(); string fname = null; int fsize; int checksum; uint offset; long rememberPos = 0; if (type == 1) //01 XX 00 00 00 00 00 OFFSET (4 bytes) { int unknown = reader.ReadInt32(); reader.ReadInt16(); uint offs = reader.ReadOffset(); continue; } else if (type == 2) { int stringOffset = reader.ReadInt32(); rememberPos = reader.BaseStream.Position; reader.BaseStream.Position = reader.Header.FStart + stringOffset; type = reader.ReadByte(); fname = reader.ReadString(); } else if (type == 3 || type == 4) { fname = reader.ReadString(); rememberPos = reader.BaseStream.Position; } else { } reader.BaseStream.Position = rememberPos; fsize = reader.ReadCompressedInt(); checksum = reader.ReadCompressedInt(); offset = reader.ReadOffset(); if (type == 3) { WzDirectory subDir = new WzDirectory(reader, fname, hash, WzIv, wzFile); subDir.BlockSize = fsize; subDir.Checksum = checksum; subDir.Offset = offset; subDir.Parent = this; subDirs.Add(subDir); } else { WzImage img = new WzImage(fname, reader); img.BlockSize = fsize; img.Checksum = checksum; img.Offset = offset; img.Parent = this; images.Add(img); } } foreach (WzDirectory subdir in subDirs) { reader.BaseStream.Position = subdir.offset; subdir.ParseDirectory(); } }
internal static List <WzImageProperty> ParsePropertyList(uint offset, WzBinaryReader reader, WzObject parent, WzImage parentImg) { int entryCount = reader.ReadCompressedInt(); List <WzImageProperty> properties = new List <WzImageProperty>(entryCount); for (int i = 0; i < entryCount; i++) { string name = reader.ReadStringBlock(offset); byte ptype = reader.ReadByte(); switch (ptype) { case 0: properties.Add(new WzNullProperty(name) { Parent = parent }); break; case 11: case 2: properties.Add(new WzShortProperty(name, reader.ReadInt16()) { Parent = parent }); break; case 3: case 19: properties.Add(new WzIntProperty(name, reader.ReadCompressedInt()) { Parent = parent }); break; case 20: properties.Add(new WzLongProperty(name, reader.ReadLong()) { Parent = parent }); break; case 4: byte type = reader.ReadByte(); if (type == 0x80) { properties.Add(new WzFloatProperty(name, reader.ReadSingle()) { Parent = parent }); } else if (type == 0) { properties.Add(new WzFloatProperty(name, 0f) { Parent = parent }); } break; case 5: properties.Add(new WzDoubleProperty(name, reader.ReadDouble()) { Parent = parent }); break; case 8: properties.Add(new WzStringProperty(name, reader.ReadStringBlock(offset)) { Parent = parent }); break; case 9: int eob = (int)(reader.ReadUInt32() + reader.BaseStream.Position); WzImageProperty exProp = ParseExtendedProp(reader, offset, eob, name, parent, parentImg); properties.Add(exProp); if (reader.BaseStream.Position != eob) { reader.BaseStream.Position = eob; } break; default: throw new Exception("Unknown property type at ParsePropertyList"); } } return(properties); }
/// <summary> /// Parses the WzDirectory /// <paramref name="lazyParse">Only parses the first directory</paramref> /// </summary> internal void ParseDirectory(bool lazyParse = false) { //Debug.WriteLine(HexTool.ToString( reader.ReadBytes(20))); //reader.BaseStream.Position = reader.BaseStream.Position - 20; int entryCount = reader.ReadCompressedInt(); for (int i = 0; i < entryCount; i++) { byte type = reader.ReadByte(); string fname = null; int fsize; int checksum; uint offset; long rememberPos = 0; switch (type) { case 1: //01 XX 00 00 00 00 00 OFFSET (4 bytes) { int unknown = reader.ReadInt32(); reader.ReadInt16(); uint offs = reader.ReadOffset(); continue; } case 2: { int stringOffset = reader.ReadInt32(); rememberPos = reader.BaseStream.Position; reader.BaseStream.Position = reader.Header.FStart + stringOffset; type = reader.ReadByte(); fname = reader.ReadString(); break; } case 3: case 4: { fname = reader.ReadString(); rememberPos = reader.BaseStream.Position; break; } default: { break; } } reader.BaseStream.Position = rememberPos; fsize = reader.ReadCompressedInt(); checksum = reader.ReadCompressedInt(); offset = reader.ReadOffset(); if (type == 3) { WzDirectory subDir = new WzDirectory(reader, fname, hash, WzIv, wzFile); subDir.BlockSize = fsize; subDir.Checksum = checksum; subDir.Offset = offset; subDir.Parent = this; subDirs.Add(subDir); if (lazyParse) { break; } } else { WzImage img = new WzImage(fname, reader); img.BlockSize = fsize; img.Checksum = checksum; img.Offset = offset; img.Parent = this; images.Add(img); if (lazyParse) { break; } } } foreach (WzDirectory subdir in subDirs) { reader.BaseStream.Position = subdir.offset; subdir.ParseDirectory(); } }
/// <summary> /// Parses the WzDirectory /// </summary> internal void ParseDirectory(WzFile parent = null) { //Array.Copy(mReader.WzKey, keyCopy, mReader.WzKey.Length); int entryCount = mReader.ReadCompressedInt(); for (int i = 0; i < entryCount; i++) { byte type = mReader.ReadByte(); string fname = null; int fsize; int checksum; uint offset; long rememberPos = 0; switch (type) { case 1: { mReader.ReadInt32(); mReader.ReadInt16(); mReader.ReadOffset(); continue; } case 2: { int stringOffset = mReader.ReadInt32(); rememberPos = mReader.BaseStream.Position; mReader.BaseStream.Position = mReader.Header.FStart + stringOffset; type = mReader.ReadByte(); fname = mReader.ReadString().Trim(); } break; case 3: case 4: fname = mReader.ReadString().Trim(); rememberPos = mReader.BaseStream.Position; break; } mReader.BaseStream.Position = rememberPos; fsize = mReader.ReadCompressedInt(); checksum = mReader.ReadCompressedInt(); offset = mReader.ReadOffset(); if (type == 3) { WzDirectory subDir = new WzDirectory(mReader, fname, mHash, mWzIv) { BlockSize = fsize, Checksum = checksum, Offset = offset, Parent = parent ?? this }; if (parent != null) { parent.mSubDirs.Add(subDir); } mSubDirs.Add(subDir); } else { WzImage img = new WzImage(fname, mReader) { BlockSize = fsize, Checksum = checksum, Offset = offset, Parent = parent ?? this }; if (parent != null) { parent.mImages.Add(img); } mImages.Add(img); } } foreach (WzDirectory subdir in mSubDirs) { mReader.BaseStream.Position = subdir.mOffset; subdir.ParseDirectory(); } }
/// <summary> /// Parse directories in the WZ file /// </summary> /// <param name="parseErrorMessage"></param> /// <param name="lazyParse">Only load the firt WzDirectory found if true</param> /// <returns></returns> internal WzFileParseStatus ParseMainWzDirectory(bool lazyParse = false) { if (this.path == null) { Helpers.ErrorLogger.Log(Helpers.ErrorLevel.Critical, "[Error] Path is null"); return(WzFileParseStatus.Path_Is_Null); } WzBinaryReader reader = new WzBinaryReader(File.Open(this.path, FileMode.Open, FileAccess.Read, FileShare.Read), WzIv); this.Header = new WzHeader(); 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)); reader.ReadBytes(1); reader.ReadBytes((int)(Header.FStart - (ulong)reader.BaseStream.Position)); reader.Header = this.Header; this.version = reader.ReadInt16(); if (mapleStoryPatchVersion == -1) { 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); 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; } reader.Hash = this.versionHash; long position = reader.BaseStream.Position; // save position to rollback to, if should parsing fail from here WzDirectory testDirectory; try { testDirectory = new WzDirectory(reader, this.name, this.versionHash, this.WzIv, this); testDirectory.ParseDirectory(lazyParse); } catch (Exception exp) { Debug.WriteLine(exp.ToString()); reader.BaseStream.Position = position; continue; } 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 { 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 } catch { reader.BaseStream.Position = position; // reset } } finally { 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); reader.Hash = this.versionHash; WzDirectory directory = new WzDirectory(reader, this.name, this.versionHash, this.WzIv, this); directory.ParseDirectory(); this.wzDir = directory; } return(WzFileParseStatus.Success); }
/// <summary> /// Parse directories in the WZ file /// </summary> /// <param name="parseErrorMessage"></param> /// <param name="lazyParse">Only load the firt WzDirectory found if true</param> /// <returns></returns> internal WzFileParseStatus ParseMainWzDirectory(bool lazyParse = false) { if (this.path == null) { Helpers.ErrorLogger.Log(Helpers.ErrorLevel.Critical, "[Error] Path is null"); return(WzFileParseStatus.Path_Is_Null); } WzBinaryReader reader = new WzBinaryReader(File.Open(this.path, FileMode.Open, FileAccess.Read, FileShare.Read), WzIv); this.Header = new WzHeader(); 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)); byte unk1 = reader.ReadByte(); byte[] unk2 = reader.ReadBytes((int)(Header.FStart - (ulong)reader.BaseStream.Position)); reader.Header = this.Header; this.wzVersionHeader = reader.ReadInt16(); if (mapleStoryPatchVersion == -1) { // Attempt to get version from MapleStory.exe first short maplestoryVerDetectedFromClient = GetMapleStoryVerFromExe(this.path, out this.mapleLocaleVersion); // this step is actually not needed if we know the maplestory patch version (the client .exe), but since we dont.. // we'll need a bruteforce way around it. const short MAX_PATCH_VERSION = 10000; // wont be reached for the forseeable future. for (int j = maplestoryVerDetectedFromClient; j < MAX_PATCH_VERSION; j++) { this.mapleStoryPatchVersion = (short)j; 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; } reader.Hash = this.versionHash; long position = reader.BaseStream.Position; // save position to rollback to, if should parsing fail from here WzDirectory testDirectory; try { testDirectory = new WzDirectory(reader, this.name, this.versionHash, this.WzIv, this); testDirectory.ParseDirectory(lazyParse); } catch (Exception exp) { Debug.WriteLine(exp.ToString()); reader.BaseStream.Position = position; continue; } // test the image and see if its correct by parsing it bool bCloseTestDirectory = true; try { WzImage testImage = testDirectory.WzImages.FirstOrDefault(); if (testImage != null) { try { 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 } catch { reader.BaseStream.Position = position; // reset } } else // if there's no image in the WZ file (new KMST Base.wz), test the directory instead { // 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). // damn, technical debt accumulating here if (mapleStoryPatchVersion == 113) { // hack for now reader.BaseStream.Position = position; // reset continue; } else { this.wzDir = testDirectory; bCloseTestDirectory = false; return(WzFileParseStatus.Success); } } } finally { 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(wzVersionHeader, mapleStoryPatchVersion); reader.Hash = this.versionHash; WzDirectory directory = new WzDirectory(reader, this.name, this.versionHash, this.WzIv, this); directory.ParseDirectory(); this.wzDir = directory; } return(WzFileParseStatus.Success); }
/// <summary> /// Parses the WzDirectory /// <paramref name="lazyParse">Only parses the first directory</paramref> /// </summary> internal void ParseDirectory(bool lazyParse = false) { //Debug.WriteLine(HexTool.ToString( reader.ReadBytes(20))); //reader.BaseStream.Position = reader.BaseStream.Position - 20; long available = reader.Available(); if (available == 0) { return; } int entryCount = reader.ReadCompressedInt(); if (entryCount < 0 || entryCount > 100000) // probably nothing > 100k folders for now. { throw new Exception("Invalid wz version used for decryption, try parsing other version numbers."); } for (int i = 0; i < entryCount; i++) { byte type = reader.ReadByte(); string fname = null; int fsize; int checksum; uint offset; long rememberPos = 0; switch (type) { case 1: //01 XX 00 00 00 00 00 OFFSET (4 bytes) { int unknown = reader.ReadInt32(); reader.ReadInt16(); uint offs = reader.ReadOffset(); continue; } case 2: { int stringOffset = reader.ReadInt32(); rememberPos = reader.BaseStream.Position; reader.BaseStream.Position = reader.Header.FStart + stringOffset; type = reader.ReadByte(); fname = reader.ReadString(); break; } case 3: case 4: { fname = reader.ReadString(); rememberPos = reader.BaseStream.Position; break; } default: { throw new Exception("[WzDirectory] Unknown directory. type = " + type); } } reader.BaseStream.Position = rememberPos; fsize = reader.ReadCompressedInt(); checksum = reader.ReadCompressedInt(); offset = reader.ReadOffset(); // IWzArchive::Getposition(pArchive) if (type == 3) { WzDirectory subDir = new WzDirectory(reader, fname, hash, WzIv, wzFile) { BlockSize = fsize, Checksum = checksum, Offset = offset, Parent = this }; subDirs.Add(subDir); if (lazyParse) { break; } } else { WzImage img = new WzImage(fname, reader, checksum) { BlockSize = fsize, Offset = offset, Parent = this }; images.Add(img); if (lazyParse) { break; } } } foreach (WzDirectory subdir in subDirs) { if (subdir.Checksum != 0) { reader.BaseStream.Position = subdir.offset; subdir.ParseDirectory(); } } }
internal void ParseMainWzDirectory() { if (FilePath == null) { Log.LogCritical("Path is null"); return; } var reader = new WzBinaryReader(File.Open(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read), _wzIv); Header = new WzHeader { Ident = reader.ReadString(4), FSize = reader.ReadUInt64(), FStart = reader.ReadUInt32(), Copyright = reader.ReadNullTerminatedString() }; reader.ReadBytes((int)(Header.FStart - reader.BaseStream.Position)); reader.Header = Header; _version = reader.ReadInt16(); if (FileVersion == -1) { for (var j = 0; j < short.MaxValue; j++) { FileVersion = (short)j; _versionHash = GetVersionHash(_version, FileVersion); if (_versionHash != 0) { reader.Hash = _versionHash; var position = reader.BaseStream.Position; WzDirectory testDirectory; try { testDirectory = new WzDirectory(reader, Name, _versionHash, _wzIv, this); testDirectory.ParseDirectory(); } catch { reader.BaseStream.Position = position; continue; } var testImage = testDirectory.GetChildImages()[0]; try { reader.BaseStream.Position = testImage.Offset; var checkByte = reader.ReadByte(); reader.BaseStream.Position = position; testDirectory.Dispose(); switch (checkByte) { case 0x73: case 0x1b: { var directory = new WzDirectory(reader, Name, _versionHash, _wzIv, this); directory.ParseDirectory(); WzDirectory = directory; return; } } reader.BaseStream.Position = position; } catch { reader.BaseStream.Position = position; } } } throw new Exception( "Error with game version hash : The specified game version is incorrect and WzLib was unable to determine the version itself"); } { _versionHash = GetVersionHash(_version, FileVersion); reader.Hash = _versionHash; var directory = new WzDirectory(reader, Name, _versionHash, _wzIv, this); directory.ParseDirectory(); WzDirectory = directory; } }
internal static List <AWzImageProperty> ParsePropertyList(uint pOffset, WzBinaryReader pReader, AWzObject pParent, WzImage pParentImg) { List <AWzImageProperty> properties = new List <AWzImageProperty>(); int entryCount = pReader.ReadCompressedInt(); for (int i = 0; i < entryCount; i++) { string name = pReader.ReadStringBlock(pOffset).Trim(); byte b = pReader.ReadByte(); switch (b) { case 0: properties.Add(new WzNullProperty(name) { Parent = pParent, ParentImage = pParentImg }); break; case 2: case 11: //UShort properties.Add(new WzShortProperty(name, pReader.ReadInt16()) { Parent = pParent, ParentImage = pParentImg }); break; case 3: case 19: //UInt properties.Add(new WzCompressedIntProperty(name, pReader.ReadCompressedInt()) { Parent = pParent, ParentImage = pParentImg }); break; case 4: byte type = pReader.ReadByte(); if (type == 0x80) { properties.Add(new WzByteFloatProperty(name, pReader.ReadSingle()) { Parent = pParent, ParentImage = pParentImg }); } else if (type == 0) { properties.Add(new WzByteFloatProperty(name, 0f) { Parent = pParent, ParentImage = pParentImg }); } break; case 5: properties.Add(new WzDoubleProperty(name, pReader.ReadDouble()) { Parent = pParent, ParentImage = pParentImg }); break; case 8: properties.Add(new WzStringProperty(name, pReader.ReadStringBlock(pOffset)) { Parent = pParent, ParentImage = pParentImg }); break; case 9: int eob = (int)(pReader.ReadUInt32() + pReader.BaseStream.Position); AWzImageProperty exProp = ParseExtendedProp(pReader, pOffset, eob, name, pParent, pParentImg); if (exProp != null) { properties.Add(exProp); } pReader.BaseStream.Position = eob; break; case 20: properties.Add(new WzCompressedLongProperty(name, pReader.ReadCompressedLong()) { Parent = pParent, ParentImage = pParentImg }); break; default: throw new Exception("Unknown property type at ParsePropertyList: " + b + " name: " + name + " offset: " + pReader.getCurrentOffset()); } } return(properties); }
internal void ParseMainWzDirectory() { if (this.path == null) { Helpers.ErrorLogger.Log(Helpers.ErrorLevel.Critical, "[Error] Path is null"); return; } WzBinaryReader reader = new WzBinaryReader(File.Open(this.path, FileMode.Open, FileAccess.Read, FileShare.Read), mapleVersion); this.Header = new WzHeader(); this.Header.Ident = reader.ReadString(4); this.Header.FSize = reader.ReadUInt64(); this.Header.FStart = reader.ReadUInt32(); this.Header.Copyright = reader.ReadNullTerminatedString(); reader.ReadBytes((int)(Header.FStart - reader.BaseStream.Position)); reader.Header = this.Header; this.version = reader.ReadInt16(); if (fileVersion == -1) { for (int j = 0; j < short.MaxValue; j++) { this.fileVersion = (short)j; this.versionHash = GetVersionHash(version, fileVersion); if (this.versionHash != 0) { reader.Hash = this.versionHash; long position = reader.BaseStream.Position; WzDirectory testDirectory = null; try { testDirectory = new WzDirectory(reader, this.name, this.versionHash, this.WzIv, this); testDirectory.ParseDirectory(); } catch { reader.BaseStream.Position = position; continue; } WzImage testImage = testDirectory.GetChildImages()[0]; try { reader.BaseStream.Position = testImage.Offset; byte checkByte = reader.ReadByte(); reader.BaseStream.Position = position; testDirectory.Dispose(); switch (checkByte) { case 0x73: case 0x1b: { WzDirectory directory = new WzDirectory(reader, this.name, this.versionHash, this.WzIv, this); directory.ParseDirectory(); this.wzDir = directory; return; } } reader.BaseStream.Position = position; } catch { reader.BaseStream.Position = position; } } } throw new Exception("Error with game version hash : The specified game version is incorrect and WzLib was unable to determine the version itself"); } else { this.versionHash = GetVersionHash(version, fileVersion); reader.Hash = this.versionHash; WzDirectory directory = new WzDirectory(reader, this.name, this.versionHash, this.WzIv, this); directory.ParseDirectory(); this.wzDir = directory; } }
internal void ParseMainWzDirectory(WzFile parentFile = null) { if (mPath == null) { Console.WriteLine("[Error] Path is null"); return; } byte[] key = WzKeyGenerator.GenerateWzKey(mWzIv); mReader = new WzBinaryReader(File.Open(mPath, FileMode.Open, FileAccess.Read, FileShare.Read), key, true); Header = new WzHeader { Ident = mReader.ReadString(4), FSize = mReader.ReadUInt64(), FStart = mReader.ReadUInt32(), Copyright = mReader.ReadNullTerminatedString() }; int bytesToRead = (int)(Header.FStart - mReader.BaseStream.Position); if (bytesToRead < 0) { throw new Exception("Unable to parse WZ file header"); } mReader.ReadBytes(bytesToRead); mReader.Header = Header; mVersion = mReader.ReadInt16(); if (mFileVersion == -1) { for (int j = 0; j < short.MaxValue; j++) { mFileVersion = (short)j; if (parentFile != null) { mFileVersion = parentFile.mFileVersion; } mVersionHash = GetVersionHash(mVersion, mFileVersion); if (mVersionHash == 0) { continue; } mReader.Hash = mVersionHash; long position = mReader.BaseStream.Position; WzDirectory testDirectory; try { testDirectory = new WzDirectory(mReader, mName, mVersionHash, mWzIv); testDirectory.ParseDirectory(); } catch { mReader.BaseStream.Position = position; continue; } foreach (WzImage s in testDirectory.GetChildImages()) { if (s.Name.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0) { testDirectory.Dispose(); throw new Exception("Invalid file names were detected. An invalid encryption may have been used."); } } WzImage testImage = testDirectory.GetChildImages()[0]; try { mReader.BaseStream.Position = testImage.Offset; byte checkByte = mReader.ReadByte(); mReader.BaseStream.Position = position; testDirectory.Dispose(); switch (checkByte) { case 0x73: case 0x1b: { mHash = mVersionHash; ParseDirectory(parentFile); return; } } mReader.BaseStream.Position = position; } catch { mReader.BaseStream.Position = position; } } throw new Exception("Error with game version hash : The specified game version is incorrect and WzLib was unable to determine the version itself"); } mVersionHash = GetVersionHash(mVersion, mFileVersion); mReader.Hash = mVersionHash; mHash = mVersionHash; ParseDirectory(parentFile); }
/// <summary> /// Parses the WzDirectory /// </summary> internal void ParseDirectory() { var entryCount = _reader.ReadCompressedInt(); for (var i = 0; i < entryCount; i++) { var type = _reader.ReadByte(); string fname = null; long rememberPos = 0; switch (type) { case 1: var unknown = _reader.ReadInt32(); _reader.ReadInt16(); var offs = _reader.ReadOffset(); continue; case 2: var stringOffset = _reader.ReadInt32(); rememberPos = _reader.BaseStream.Position; _reader.BaseStream.Position = _reader.Header.FStart + stringOffset; type = _reader.ReadByte(); fname = _reader.ReadString(); break; case 3: case 4: fname = _reader.ReadString(); rememberPos = _reader.BaseStream.Position; break; } _reader.BaseStream.Position = rememberPos; var fsize = _reader.ReadCompressedInt(); var dirChecksum = _reader.ReadCompressedInt(); var dirOffset = _reader.ReadOffset(); if (type == 3) { var subDir = new WzDirectory(_reader, fname, _hash, WzIv, _wzFile) { BlockSize = fsize, Checksum = dirChecksum, Offset = dirOffset, Parent = this }; WzDirectories.Add(subDir); } else { var img = new WzImage(fname, _reader) { BlockSize = fsize, Checksum = dirChecksum, Offset = dirOffset, Parent = this }; WzImages.Add(img); } } foreach (var subdir in WzDirectories) { _reader.BaseStream.Position = subdir.Offset; subdir.ParseDirectory(); } }