private void ExportImage(WzImage pImage) { Action<IWzImageProperty, string, string> RecursiveDown = null; RecursiveDown = (prop, name, dataname) => { foreach (IWzImageProperty prop2 in prop.WzProperties) { ExportIfExists(exDir, prop2, name, dataname + "." + prop2.Name); if (prop2.WzProperties == null) continue; ExportObject(prop2, dataname + "." + prop2.Name); RecursiveDown(prop2, name + "." + prop2.Name, dataname + "." + prop2.Name); } }; Down(pImage.Name); foreach (IWzImageProperty prop in pImage.WzProperties) { Down(prop.Name); string dataname = prop.Name; foreach (IWzImageProperty prop2 in prop.WzProperties) { ExportIfExists(exDir, prop2, prop2.Name, dataname + "." + prop2.Name); if (prop2.WzProperties == null) continue; ExportObject(prop2, dataname + "." + prop2.Name); RecursiveDown(prop2, prop2.Name, dataname + "." + prop2.Name); } Up(); } Up(); }
private static void VerifyMapPropsKnown(WzImage mapImage) { foreach (IWzImageProperty prop in mapImage.WzProperties) switch (prop.Name) { case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "info": case "life": case "ladderRope": case "reactor": case "back": case "foothold": case "miniMap": case "portal": case "seat": case "ToolTip": continue; default: string error = "Unknown property " + prop.Name + ". While this map can still be edited it is recommended to report this to haha01haha01 for better functionality of the editor."; //MessageBox.Show(error); MapleLib.Helpers.ErrorLogger.Log(ErrorLevel.MissingFeature, error); break; } }
public void loadIntProps(WzImage image) { foreach (IWzImageProperty prop in image["info"].WzProperties) { if (prop is WzCompressedIntProperty) props.Add(prop.Name, InfoTool.GetInt(prop)); } }
public static void DumpMap(WzImage img, string path,string mapname, string streetname) { TextWriter tw = new StreamWriter(path); tw.WriteLine("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"); tw.WriteLine("<imgdir name=\"" + img.Name + "\" mapname=\"" + mapname + "\" streetname=\"" + streetname + "\">"); DumpXML(tw, " ", img.WzProperties); tw.WriteLine("</imgdir>"); tw.Close(); }
public WzImageResource(WzImage img) { this.img = img; this.parsed = img.Parsed; if (!parsed) { img.ParseImage(); } }
public static void GetMapDimensions(WzImage mapImage, out Rectangle VR, out Point mapCenter, out Point mapSize, out Point minimapCenter, out Point minimapSize, out bool hasVR, out bool hasMinimap) { System.Drawing.Rectangle? vr = MapInfo.GetVR(mapImage); hasVR = vr.HasValue; hasMinimap = mapImage["miniMap"] != null; if (!hasMinimap) { // No minimap, generate sizes from VR if (vr == null) { // No minimap and no VR, our only chance of getting sizes is by generating a VR, if that fails we're screwed if (!GetMapVR(mapImage, ref vr)) { throw new NoVRException(); } } minimapSize = new Point(vr.Value.Width + 10, vr.Value.Height + 10); //leave 5 pixels on each side minimapCenter = new Point(5 - vr.Value.Left, 5 - vr.Value.Top); mapSize = new Point(minimapSize.X, minimapSize.Y); mapCenter = new Point(minimapCenter.X, minimapCenter.Y); } else { WzImageProperty miniMap = mapImage["miniMap"]; minimapSize = new Point(InfoTool.GetInt(miniMap["width"]), InfoTool.GetInt(miniMap["height"])); minimapCenter = new Point(InfoTool.GetInt(miniMap["centerX"]), InfoTool.GetInt(miniMap["centerY"])); int topOffs = 0, botOffs = 0, leftOffs = 0, rightOffs = 0; int leftTarget = 69 - minimapCenter.X, topTarget = 86 - minimapCenter.Y, rightTarget = minimapSize.X - 69 - 69, botTarget = minimapSize.Y - 86 - 86; if (vr == null) { // We have no VR info, so set all VRs according to their target vr = new System.Drawing.Rectangle(leftTarget, topTarget, rightTarget, botTarget); } else { if (vr.Value.Left < leftTarget) { leftOffs = leftTarget - vr.Value.Left; } if (vr.Value.Top < topTarget) { topOffs = topTarget - vr.Value.Top; } if (vr.Value.Right > rightTarget) { rightOffs = vr.Value.Right - rightTarget; } if (vr.Value.Bottom > botTarget) { botOffs = vr.Value.Bottom - botTarget; } } mapSize = new Point(minimapSize.X + leftOffs + rightOffs, minimapSize.Y + topOffs + botOffs); mapCenter = new Point(minimapCenter.X + leftOffs, minimapCenter.Y + topOffs); } VR = new Rectangle(vr.Value.X, vr.Value.Y, vr.Value.Width, vr.Value.Height); }
private void ExtractSettingsImage(WzImage settingsImage, Type settingsHolderType) { if (!settingsImage.Parsed) settingsImage.ParseImage(); foreach (FieldInfo fieldInfo in settingsHolderType.GetFields(BindingFlags.Public | BindingFlags.Static)) { string settingName = fieldInfo.Name; IWzImageProperty settingProp = settingsImage[settingName]; byte[] argb; if (settingProp == null) SaveField(settingsImage, fieldInfo); else if (fieldInfo.FieldType.BaseType != null && fieldInfo.FieldType.BaseType.FullName == "System.Enum") fieldInfo.SetValue(null, InfoTool.GetInt(settingProp)); else switch (fieldInfo.FieldType.FullName) { //case "Microsoft.Xna.Framework.Graphics.Color": case "Microsoft.Xna.Framework.Color": if (xnaColorType == null) throw new InvalidDataException("XNA color detected, but XNA type activator is null"); argb = BitConverter.GetBytes((uint)((WzDoubleProperty)settingProp).Value); fieldInfo.SetValue(null, Activator.CreateInstance(xnaColorType, argb[0], argb[1], argb[2], argb[3])); break; case "System.Drawing.Color": argb = BitConverter.GetBytes((uint)((WzDoubleProperty)settingProp).Value); fieldInfo.SetValue(null, System.Drawing.Color.FromArgb(argb[3], argb[2], argb[1], argb[0])); break; case "System.Int32": fieldInfo.SetValue(null, InfoTool.GetInt(settingProp)); break; case "System.Double": fieldInfo.SetValue(null, ((WzDoubleProperty)settingProp).Value); break; case "System.Boolean": fieldInfo.SetValue(null, InfoTool.GetBool(settingProp)); //bool a = (bool)fieldInfo.GetValue(null); break; case "System.Single": fieldInfo.SetValue(null, ((WzByteFloatProperty)settingProp).Value); break; /*case "WzMapleVersion": fieldInfo.SetValue(null, (WzMapleVersion)InfoTool.GetInt(settingProp)); break; case "ItemTypes": fieldInfo.SetValue(null, (ItemTypes)InfoTool.GetInt(settingProp)); break;*/ case "System.Drawing.Size": fieldInfo.SetValue(null, new System.Drawing.Size(((WzVectorProperty)settingProp).X.Value, ((WzVectorProperty)settingProp).Y.Value)); break; case "System.String": fieldInfo.SetValue(null, InfoTool.GetString(settingProp)); break; case "System.Drawing.Bitmap": fieldInfo.SetValue(null, ((WzCanvasProperty)settingProp).PngProperty.GetPNG(false)); break; default: throw new Exception("unrecognized setting type"); } } }
private static MapType GetMapType(WzImage mapImage) { switch (mapImage.Name) { case "MapLogin1.img": case "MapLogin.img": return MapType.MapLogin; case "CashShopPreview.img": return MapType.CashShopPreview; default: return MapType.RegularMap; } }
internal static IWzImageProperty[] ParsePropertyList(uint offset, WzBinaryReader reader, IWzObject parent, WzImage parentImg) { List<IWzImageProperty> properties = new List<IWzImageProperty>(); int entryCount = reader.ReadCompressedInt(); 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, i) { Parent = parent, ParentImage = parentImg }); break; case 0x0B: case 2: properties.Add(new WzUnsignedShortProperty(name, reader.ReadUInt16()) { Parent = parent, ParentImage = parentImg }); break; case 3: properties.Add(new WzCompressedIntProperty(name, reader.ReadCompressedInt()) { Parent = parent, ParentImage = parentImg }); break; case 4: byte type = reader.ReadByte(); if (type == 0x80) properties.Add(new WzByteFloatProperty(name, reader.ReadSingle()) { Parent = parent, ParentImage = parentImg }); else if (type == 0) properties.Add(new WzByteFloatProperty(name, 0f) { Parent = parent, ParentImage = parentImg }); break; case 5: properties.Add(new WzDoubleProperty(name, reader.ReadDouble()) { Parent = parent, ParentImage = parentImg }); break; case 8: properties.Add(new WzStringProperty(name, reader.ReadStringBlock(offset)) { Parent = parent }); break; case 9: int eob = (int)(reader.ReadUInt32() + reader.BaseStream.Position); WzExtendedProperty exProp = new WzExtendedProperty(offset, eob, name); exProp.Parent = parent; exProp.ParentImage = parentImg; exProp.ParseExtendedProperty(reader); properties.Add(exProp); if (reader.BaseStream.Position != eob) reader.BaseStream.Position = eob; break; default: { Console.WriteLine("Unknown type: {0} | {1}", ptype, name); break; } } } return properties.ToArray(); }
//yes I know this is a shitty workaround public static WzImage LoadMap(string xmlpath, ref string mapname, ref string streetname) { XmlDocument document = new XmlDocument(); document.Load(xmlpath); WzImage wo = null; foreach (XmlNode node in document) { if (node is XmlElement) { XmlElement element = (XmlElement)node; wo = new WzImage(element.GetAttribute("name")); mapname = element.GetAttribute("mapname"); streetname = element.GetAttribute("streetname"); ParseXML(element, wo); } } wo.Changed = true; return wo; }
public override void ParseImage() { WzStringProperty link = (WzStringProperty)((WzSubProperty)((WzImage)ParentObject)["info"])["link"]; if (link != null) { LinkedImage = (WzImage)Program.WzManager.GetWzFileByName("reactor")[link.Value + ".img"]; ExtractPNGFromImage(LinkedImage); } else ExtractPNGFromImage((WzImage)ParentObject); }
public static NpcInfo Load(WzImage parentObject) { string id = /*WzInfoTools.RemoveLeadingZeros(*/WzInfoTools.RemoveExtension(parentObject.Name)/*)*/; return new NpcInfo(null, new System.Drawing.Point(), id, WzInfoTools.GetNpcNameById(id), parentObject); }
internal static IExtended ParseExtendedProp(WzBinaryReader reader, uint offset, int endOfBlock, string name, IWzObject parent, WzImage imgParent) { switch (reader.ReadByte()) { case 0x1B: return ExtractMore(reader, offset, endOfBlock, name, reader.ReadStringAtOffset(offset + reader.ReadInt32()), parent, imgParent); case 0x73: return ExtractMore(reader, offset, endOfBlock, name, "", parent, imgParent); default: throw new System.Exception("Invlid byte read at ParseExtendedProp"); } }
internal string[] GetPathsFromImage(WzImage img, string curPath) { List<string> objList = new List<string>(); foreach (IWzImageProperty prop in img.WzProperties) { objList.Add(curPath + "/" + prop.Name); objList.AddRange(GetPathsFromProperty(prop, curPath + "/" + prop.Name)); } return objList.ToArray(); }
public void LoadReactors(WzImage mapImage, Board mapBoard) { WzSubProperty reactorParent = (WzSubProperty)mapImage["reactor"]; if (reactorParent == null) return; foreach (WzSubProperty reactor in reactorParent.WzProperties) { int x = InfoTool.GetInt(reactor["x"]); int y = InfoTool.GetInt(reactor["y"]); int reactorTime = InfoTool.GetInt(reactor["reactorTime"]); string name = InfoTool.GetOptionalString(reactor["name"]); string id = InfoTool.GetString(reactor["id"]); bool flip = InfoTool.GetBool(reactor["f"]); mapBoard.BoardItems.Reactors.Add((ReactorInstance)Program.InfoManager.Reactors[id].CreateInstance(mapBoard, x, y, reactorTime, name, flip)); } }
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 (FilePath == null) { Helpers.ErrorLogger.Log(Helpers.ErrorLevel.Critical, "[Error] Path is null"); return; } WzBinaryReader reader = new WzBinaryReader(File.Open(FilePath, 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 (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.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"); } 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.WzDirectory = directory; } }
/// <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); }
public void LoadToolTips(WzImage mapImage, Board mapBoard) { WzSubProperty tooltipsParent = (WzSubProperty)mapImage["ToolTip"]; if (tooltipsParent == null) { return; } WzImage tooltipsStringImage = (WzImage)Program.WzManager.String["ToolTipHelp.img"]; if (!tooltipsStringImage.Parsed) { tooltipsStringImage.ParseImage(); } WzSubProperty tooltipStrings = (WzSubProperty)tooltipsStringImage["Mapobject"][mapBoard.MapInfo.id.ToString()]; if (tooltipStrings == null) { return; } for (int i = 0; true; i++) { string num = i.ToString(); WzSubProperty tooltipString = (WzSubProperty)tooltipStrings[num]; WzSubProperty tooltipProp = (WzSubProperty)tooltipsParent[num]; WzSubProperty tooltipChar = (WzSubProperty)tooltipsParent[num + "char"]; if (tooltipString == null && tooltipProp == null) break; if (tooltipString == null ^ tooltipProp == null) continue; string title = InfoTool.GetOptionalString(tooltipString["Title"]); string desc = InfoTool.GetOptionalString(tooltipString["Desc"]); int x1 = InfoTool.GetInt(tooltipProp["x1"]); int x2 = InfoTool.GetInt(tooltipProp["x2"]); int y1 = InfoTool.GetInt(tooltipProp["y1"]); int y2 = InfoTool.GetInt(tooltipProp["y2"]); Microsoft.Xna.Framework.Rectangle tooltipPos = new Microsoft.Xna.Framework.Rectangle(x1, y1, x2 - x1, y2 - y1); ToolTipInstance tt = new ToolTipInstance(mapBoard, tooltipPos, title, desc, i); mapBoard.BoardItems.ToolTips.Add(tt); if (tooltipChar != null) { x1 = InfoTool.GetInt(tooltipChar["x1"]); x2 = InfoTool.GetInt(tooltipChar["x2"]); y1 = InfoTool.GetInt(tooltipChar["y1"]); y2 = InfoTool.GetInt(tooltipChar["y2"]); tooltipPos = new Microsoft.Xna.Framework.Rectangle(x1, y1, x2 - x1, y2 - y1); ToolTipChar ttc = new ToolTipChar(mapBoard, tooltipPos, tt); mapBoard.BoardItems.CharacterToolTips.Add(ttc); } } }
/// <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 static AWzImageProperty ParseExtendedProp(WzBinaryReader pReader, uint pOffset, int pEndOfBlock, string pName, AWzObject pParent, WzImage pImgParent) { byte b = pReader.ReadByte(); switch (b) { case 0x1B: return(ExtractMore(pReader, pOffset, pEndOfBlock, pName, pReader.ReadStringAtOffset(pOffset + pReader.ReadInt32()), pParent, pImgParent)); case 0x73: return(ExtractMore(pReader, pOffset, pEndOfBlock, pName, pReader.ReadString(), pParent, pImgParent)); default: return(null); //throw new Exception("Invlid type at ParseExtendedProp: " + b); } }
private bool TryDecodeWithWZVersionNumber(WzBinaryReader reader, int useWzVersionHeader, int useMapleStoryPatchVersion, bool lazyParse) { this.mapleStoryPatchVersion = (short)useMapleStoryPatchVersion; 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; long fallbackOffsetPosition = 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 = fallbackOffsetPosition; return(false); } // 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 = fallbackOffsetPosition; 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(true); } 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 = fallbackOffsetPosition; // reset } catch { reader.BaseStream.Position = fallbackOffsetPosition; // reset return(false); } return(true); } 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 = fallbackOffsetPosition; // reset return(false); } else { this.wzDir = testDirectory; bCloseTestDirectory = false; return(true); } } } finally { if (bCloseTestDirectory) { testDirectory.Dispose(); } } }
/// <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(); } }
private void LoadChairs(WzImage mapImage, Board mapBoard) { WzSubProperty chairParent = (WzSubProperty)mapImage["seat"]; if (chairParent != null) { foreach (WzVectorProperty chair in chairParent.WzProperties) { mapBoard.BoardItems.Chairs.Add(new Chair(mapBoard, chair.X.Value, chair.Y.Value)); } } mapBoard.BoardItems.Chairs.Sort(new Comparison<Chair>( delegate(Chair a, Chair b) { if (a.X > b.X) return 1; else if (a.X < b.X) return -1; else { if (a.Y > b.Y) return 1; else if (a.Y < b.Y) return -1; else return 0; } })); for (int i = 0; i < mapBoard.BoardItems.Chairs.Count - 1; i++) { Chair a = mapBoard.BoardItems.Chairs[i]; Chair b = mapBoard.BoardItems.Chairs[i + 1]; if (a.Y == b.Y && a.X == b.X) //removing b is more comfortable because that way we don't need to decrease i { if (a.Parent == null && b.Parent != null) { mapBoard.BoardItems.Chairs.Remove(a); i--; } else mapBoard.BoardItems.Chairs.Remove(b); } } }
/// <summary> /// Removes an image from the list /// </summary> /// <param name="image">The image to remove</param> public void RemoveImage(WzImage image) { images.Remove(image); image.Parent = null; }
private void SaveSettingsImage(WzImage settingsImage, Type settingsHolderType) { if (!settingsImage.Parsed) settingsImage.ParseImage(); foreach (FieldInfo fieldInfo in settingsHolderType.GetFields(BindingFlags.Public | BindingFlags.Static)) { SaveField(settingsImage, fieldInfo); } settingsImage.Changed = true; }
public void LoadPortals(WzImage mapImage, Board mapBoard) { WzSubProperty portalParent = (WzSubProperty)mapImage["portal"]; foreach (WzSubProperty portal in portalParent.WzProperties) { int x = InfoTool.GetInt(portal["x"]); int y = InfoTool.GetInt(portal["y"]); string pt = Program.InfoManager.PortalTypeById[InfoTool.GetInt(portal["pt"])]; int tm = InfoTool.GetInt(portal["tm"]); string tn = InfoTool.GetString(portal["tn"]); string pn = InfoTool.GetString(portal["pn"]); string image = InfoTool.GetOptionalString(portal["image"]); string script = InfoTool.GetOptionalString(portal["script"]); int? verticalImpact = InfoTool.GetOptionalInt(portal["verticalImpact"]); int? horizontalImpact = InfoTool.GetOptionalInt(portal["horizontalImpact"]); int? hRange = InfoTool.GetOptionalInt(portal["hRange"]); int? vRange = InfoTool.GetOptionalInt(portal["vRange"]); int? delay = InfoTool.GetOptionalInt(portal["delay"]); MapleBool hideTooltip = InfoTool.GetOptionalBool(portal["hideTooltip"]); MapleBool onlyOnce = InfoTool.GetOptionalBool(portal["onlyOnce"]); mapBoard.BoardItems.Portals.Add(PortalInfo.GetPortalInfoByType(pt).CreateInstance(mapBoard, x, y, pn, tn, tm, script, delay, hideTooltip, onlyOnce, horizontalImpact, verticalImpact, image, hRange, vRange)); } }
public void Save() { bool settingsExist = File.Exists(wzPath); WzFile wzFile; if (settingsExist) { wzFile = new WzFile(wzPath, 1337, WzMapleVersion.CLASSIC); wzFile.ParseWzFile(); } else { wzFile = new WzFile(1337, WzMapleVersion.CLASSIC); wzFile.Header.Copyright = "Wz settings file generated by MapleLib's WzSettings module created by haha01haha01"; wzFile.Header.RecalculateFileStart(); WzImage US = new WzImage("UserSettings.img") { Changed = true, Parsed = true }; WzImage AS = new WzImage("ApplicationSettings.img") { Changed = true, Parsed = true }; wzFile.WzDirectory.WzImages.Add(US); wzFile.WzDirectory.WzImages.Add(AS); } SaveSettingsImage((WzImage)wzFile["UserSettings.img"], userSettingsType); SaveSettingsImage((WzImage)wzFile["ApplicationSettings.img"], appSettingsType); if (settingsExist) { string tempFile = Path.GetTempFileName(); string settingsPath = wzFile.FilePath; wzFile.SaveToDisk(tempFile); wzFile.Dispose(); File.Delete(settingsPath); File.Move(tempFile, settingsPath); } else wzFile.SaveToDisk(wzPath); }
public void LoadRopes(WzImage mapImage, Board mapBoard) { WzSubProperty ropeParent = (WzSubProperty)mapImage["ladderRope"]; foreach (WzSubProperty rope in ropeParent.WzProperties) { int x = InfoTool.GetInt(rope["x"]); int y1 = InfoTool.GetInt(rope["y1"]); int y2 = InfoTool.GetInt(rope["y2"]); bool uf = InfoTool.GetBool(rope["uf"]); int page = InfoTool.GetInt(rope["page"]); bool l = InfoTool.GetBool(rope["l"]); mapBoard.BoardItems.Ropes.Add(new Rope(mapBoard, x, y1, y2, l, page, uf)); } }
internal static AWzImageProperty ExtractMore(WzBinaryReader pReader, uint pOffset, int pEndOfBlock, string pName, string pImageName, AWzObject pParent, WzImage pImgParent) { switch (pImageName) { case "Property": WzSubProperty subProp = new WzSubProperty(pName) { Parent = pParent, ParentImage = pImgParent }; pReader.BaseStream.Position += 2; subProp.AddProperties(ParsePropertyList(pOffset, pReader, subProp, pImgParent)); return(subProp); case "Canvas": WzCanvasProperty canvasProp = new WzCanvasProperty(pName) { Parent = pParent, ParentImage = pImgParent }; pReader.BaseStream.Position++; if (pReader.ReadByte() == 1) { pReader.BaseStream.Position += 2; canvasProp.AddProperties(ParsePropertyList(pOffset, pReader, canvasProp, pImgParent)); } canvasProp.PngProperty = new WzPngProperty(pReader) { Parent = canvasProp, ParentImage = pImgParent }; return(canvasProp); case "Shape2D#Vector2D": WzVectorProperty vecProp = new WzVectorProperty(pName) { Parent = pParent, ParentImage = pImgParent }; vecProp.X = new WzCompressedIntProperty("X", pReader.ReadCompressedInt()) { Parent = vecProp, ParentImage = pImgParent }; vecProp.Y = new WzCompressedIntProperty("Y", pReader.ReadCompressedInt()) { Parent = vecProp, ParentImage = pImgParent }; return(vecProp); case "Shape2D#Convex2D": WzConvexProperty convexProp = new WzConvexProperty(pName) { Parent = pParent, ParentImage = pImgParent }; int convexEntryCount = pReader.ReadCompressedInt(); for (int i = 0; i < convexEntryCount; i++) { AWzImageProperty imgProp = ParseExtendedProp(pReader, pOffset, 0, pName, convexProp, pImgParent); if (imgProp != null) { convexProp.AddProperty(imgProp); } } return(convexProp); case "Sound_DX8": WzSoundProperty soundProp = new WzSoundProperty(pName) { Parent = pParent, ParentImage = pImgParent }; soundProp.ParseSound(pReader); return(soundProp); case "UOL": pReader.BaseStream.Position++; byte b = pReader.ReadByte(); switch (b) { case 0: return(new WzUOLProperty(pName, pReader.ReadString()) { Parent = pParent, ParentImage = pImgParent }); case 1: return(new WzUOLProperty(pName, pReader.ReadStringAtOffset(pOffset + pReader.ReadInt32())) { Parent = pParent, ParentImage = pImgParent }); default: throw new Exception("Unsupported UOL type: " + b); } default: throw new Exception("Unknown image name: " + pImageName); } }
public List<string> VerifyMapPropsKnown(WzImage mapImage, bool userless) { List<string> copyPropNames = new List<string>(); foreach (WzImageProperty prop in mapImage.WzProperties) { switch (prop.Name) { case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "info": case "life": case "ladderRope": case "reactor": case "back": case "foothold": case "miniMap": case "portal": case "seat": case "ToolTip": case "clock": case "shipObj": case "area": case "healer": case "pulley": case "BuffZone": case "swimArea": continue; case "coconut": // The coconut event. Prop is copied but not edit-supported, we don't need to notify the user since it has no stateful objects. (e.g. 109080002) case "user": // A map prop that dresses the user with predefined items according to his job. No stateful objects. (e.g. 930000010) case "noSkill": // Preset in Monster Carnival maps, can only guess by its name that it blocks skills. Nothing stateful. (e.g. 980031100) case "snowMan": // I don't even know what is this for; it seems to only have 1 prop with a path to the snowman, which points to a nonexistant image. (e.g. 889100001) case "weather": // This has something to do with cash weather items, and exists in some nautlius maps (e.g. 108000500) case "mobMassacre": // This is the Mu Lung Dojo header property (e.g. 926021200) case "battleField": // The sheep vs wolf event and other useless maps (e.g. 109090300, 910040100) copyPropNames.Add(prop.Name); continue; case "snowBall": // The snowball/snowman event. It has the snowman itself, which is a stateful object (somewhat of a mob), but we do not support it. case "monsterCarnival": // The Monster Carnival. It has an immense amount of info and stateful objects, including the mobs and guardians. We do not support it. (e.g. 980000201) copyPropNames.Add(prop.Name); if (!userless) { MessageBox.Show("The map you are opening has the feature \"" + prop.Name + "\", which is purposely not supported in the editor.\r\nTo get around this, HaCreator will copy the original feature's data byte-to-byte. This might cause the feature to stop working if it depends on map objects, such as footholds or mobs."); } continue; default: string loggerSuffix = ", map " + mapImage.Name + ((mapImage.WzFileParent != null) ? (" of version " + Enum.GetName(typeof(WzMapleVersion), mapImage.WzFileParent.MapleVersion) + ", v" + mapImage.WzFileParent.Version.ToString()) : ""); string error = "Unknown property " + prop.Name + loggerSuffix; MapleLib.Helpers.ErrorLogger.Log(ErrorLevel.MissingFeature, error); copyPropNames.Add(prop.Name); break; } } return copyPropNames; }
/// <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); }
private static bool GetMapVR(WzImage mapImage, ref System.Drawing.Rectangle? VR) { WzSubProperty fhParent = (WzSubProperty)mapImage["foothold"]; if (fhParent == null) { VR = null; return false; } int mostRight = int.MinValue, mostLeft = int.MaxValue, mostTop = int.MaxValue, mostBottom = int.MinValue; foreach (WzSubProperty fhLayer in fhParent.WzProperties) { foreach (WzSubProperty fhCat in fhLayer.WzProperties) { foreach (WzSubProperty fh in fhCat.WzProperties) { int x1 = InfoTool.GetInt(fh["x1"]); int x2 = InfoTool.GetInt(fh["x2"]); int y1 = InfoTool.GetInt(fh["y1"]); int y2 = InfoTool.GetInt(fh["y2"]); if (x1 > mostRight) mostRight = x1; if (x1 < mostLeft) mostLeft = x1; if (x2 > mostRight) mostRight = x2; if (x2 < mostLeft) mostLeft = x2; if (y1 > mostBottom) mostBottom = y1; if (y1 < mostTop) mostTop = y1; if (y2 > mostBottom) mostBottom = y2; if (y2 < mostTop) mostTop = y2; } } } if (mostRight == int.MinValue || mostLeft == int.MaxValue || mostTop == int.MaxValue || mostBottom == int.MinValue) { VR = null; return false; } int VRLeft = mostLeft - 10; int VRRight = mostRight + 10; int VRBottom = mostBottom + 110; int VRTop = Math.Min(mostBottom - 600, mostTop - 360); VR = new System.Drawing.Rectangle(VRLeft, VRTop, VRRight - VRLeft, VRBottom - VRTop); return true; }
/// <summary> /// Parses .lua property /// </summary> /// <param name="offset"></param> /// <param name="reader"></param> /// <param name="parent"></param> /// <param name="parentImg"></param> /// <returns></returns> internal static WzLuaProperty ParseLuaProperty(uint offset, WzBinaryReader reader, WzObject parent, WzImage parentImg) { // 28 71 4F EF 1B 65 F9 1F A7 48 8D 11 73 E7 F0 27 55 09 DD 3C 07 32 D7 38 21 57 84 70 C1 79 9A 3F 49 F7 79 03 41 F4 9D B9 1B 5F CF 26 80 3D EC 25 5F 9C // [compressed int] [bytes] int length = reader.ReadCompressedInt(); byte[] rawEncBytes = reader.ReadBytes(length); WzLuaProperty lua = new WzLuaProperty("Script", rawEncBytes) { Parent = parent }; return(lua); }
private void SaveField(WzImage settingsImage, FieldInfo fieldInfo) { string settingName = fieldInfo.Name; if (fieldInfo.FieldType.BaseType != null && fieldInfo.FieldType.BaseType.FullName == "System.Enum") SetWzProperty(settingsImage, settingName, WzPropertyType.CompressedInt, fieldInfo.GetValue(null)); else switch (fieldInfo.FieldType.FullName) { //case "Microsoft.Xna.Framework.Graphics.Color": case "Microsoft.Xna.Framework.Color": object xnaColor = fieldInfo.GetValue(null); //for some odd reason .NET requires casting the result to uint before it can be //casted to double SetWzProperty(settingsImage, settingName, WzPropertyType.Double, (double)(uint)xnaColor.GetType().GetProperty("PackedValue").GetValue(xnaColor, null)); break; case "System.Drawing.Color": SetWzProperty(settingsImage, settingName, WzPropertyType.Double, (double)((System.Drawing.Color)fieldInfo.GetValue(null)).ToArgb()); break; case "System.Int32": SetWzProperty(settingsImage, settingName, WzPropertyType.CompressedInt, fieldInfo.GetValue(null)); break; case "System.Double": SetWzProperty(settingsImage, settingName, WzPropertyType.Double, fieldInfo.GetValue(null)); break; case "Single": SetWzProperty(settingsImage, settingName, WzPropertyType.ByteFloat, fieldInfo.GetValue(null)); break; case "System.Drawing.Size": SetWzProperty(settingsImage, settingName, WzPropertyType.Vector, fieldInfo.GetValue(null)); break; case "System.String": SetWzProperty(settingsImage, settingName, WzPropertyType.String, fieldInfo.GetValue(null)); break; case "System.Drawing.Bitmap": SetWzProperty(settingsImage, settingName, WzPropertyType.Canvas, fieldInfo.GetValue(null)); break; case "System.Boolean": SetWzProperty(settingsImage, settingName, WzPropertyType.CompressedInt, (bool)fieldInfo.GetValue(null) ? 1 : 0); break; } }
internal static List <IWzImageProperty> ParsePropertyList(uint offset, WzBinaryReader reader, IWzObject parent, WzImage parentImg) { int entryCount = reader.ReadCompressedInt(); List <IWzImageProperty> properties = new List <IWzImageProperty>(entryCount); for (int i = 0; i < entryCount; i++) { string name = reader.ReadStringBlock(offset); switch (reader.ReadByte()) { case 0: properties.Add(new WzNullProperty(name) { Parent = parent /*, ParentImage = parentImg*/ }); break; case 0x0B: case 2: properties.Add(new WzUnsignedShortProperty(name, reader.ReadUInt16()) { Parent = parent /*, ParentImage = parentImg*/ }); break; case 3: properties.Add(new WzCompressedIntProperty(name, reader.ReadCompressedInt()) { Parent = parent /*, ParentImage = parentImg*/ }); break; case 4: byte type = reader.ReadByte(); if (type == 0x80) { properties.Add(new WzByteFloatProperty(name, reader.ReadSingle()) { Parent = parent /*, ParentImage = parentImg*/ }); } else if (type == 0) { properties.Add(new WzByteFloatProperty(name, 0f) { Parent = parent /*, ParentImage = parentImg*/ }); } break; case 5: properties.Add(new WzDoubleProperty(name, reader.ReadDouble()) { Parent = parent /*, ParentImage = parentImg*/ }); break; case 8: properties.Add(new WzStringProperty(name, reader.ReadStringBlock(offset)) { Parent = parent }); break; case 9: int eob = (int)(reader.ReadUInt32() + reader.BaseStream.Position); IWzImageProperty 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); }
private void SetWzProperty(WzImage parentImage, string propName, WzPropertyType propType, object value) { IWzImageProperty property = parentImage[propName]; if (property != null) { if (property.PropertyType == propType) property.SetValue(value); else { property.Remove(); CreateWzProp(parentImage, propType, propName, value); } } else CreateWzProp(parentImage, propType, propName, value); }
internal static IExtended ParseExtendedProp(WzBinaryReader reader, uint offset, int endOfBlock, string name, IWzObject parent, WzImage imgParent) { switch (reader.ReadByte()) { case 0x1B: return(ExtractMore(reader, offset, endOfBlock, name, reader.ReadStringAtOffset(offset + reader.ReadInt32()), parent, imgParent)); case 0x73: return(ExtractMore(reader, offset, endOfBlock, name, "", parent, imgParent)); default: throw new System.Exception("Invlid byte read at ParseExtendedProp"); } }
public IWzObject[] GetObjectsFromImage(WzImage img) { List<IWzObject> objList = new List<IWzObject>(); foreach (IWzImageProperty prop in img.WzProperties) { objList.Add(prop); objList.AddRange(GetObjectsFromProperty(prop)); } return objList.ToArray(); }
internal static IExtended ExtractMore(WzBinaryReader reader, uint offset, int eob, string name, string iname, IWzObject parent, WzImage imgParent) { if (iname == "") { iname = reader.ReadString(); } switch (iname) { case "Property": WzSubProperty subProp = new WzSubProperty(name) { Parent = parent }; reader.BaseStream.Position += 2; subProp.AddProperties(IWzImageProperty.ParsePropertyList(offset, reader, subProp, imgParent)); return(subProp); case "Canvas": WzCanvasProperty canvasProp = new WzCanvasProperty(name) { Parent = parent }; reader.BaseStream.Position++; if (reader.ReadByte() == 1) { reader.BaseStream.Position += 2; canvasProp.AddProperties(IWzImageProperty.ParsePropertyList(offset, reader, canvasProp, imgParent)); } canvasProp.PngProperty = new WzPngProperty(reader, imgParent.parseEverything) { Parent = canvasProp }; return(canvasProp); case "Shape2D#Vector2D": WzVectorProperty vecProp = new WzVectorProperty(name) { Parent = parent }; vecProp.X = new WzCompressedIntProperty("X", reader.ReadCompressedInt()) { Parent = vecProp }; vecProp.Y = new WzCompressedIntProperty("Y", reader.ReadCompressedInt()) { Parent = vecProp }; return(vecProp); case "Shape2D#Convex2D": WzConvexProperty convexProp = new WzConvexProperty(name) { Parent = parent }; int convexEntryCount = reader.ReadCompressedInt(); convexProp.WzProperties.Capacity = convexEntryCount; //performance thing for (int i = 0; i < convexEntryCount; i++) { convexProp.AddProperty(ParseExtendedProp(reader, offset, 0, name, convexProp, imgParent)); } return(convexProp); case "Sound_DX8": WzSoundProperty soundProp = new WzSoundProperty(name, reader, imgParent.parseEverything) { Parent = parent }; return(soundProp); case "UOL": reader.BaseStream.Position++; switch (reader.ReadByte()) { case 0: return(new WzUOLProperty(name, reader.ReadString()) { Parent = parent }); case 1: return(new WzUOLProperty(name, reader.ReadStringAtOffset(offset + reader.ReadInt32())) { Parent = parent }); } throw new Exception("Unsupported UOL type"); default: throw new Exception("Unknown iname: " + iname); } }
internal static IExtended ExtractMore(WzBinaryReader reader, uint offset, int eob, string name, string iname, IWzObject parent, WzImage imgParent) { if (iname == "") iname = reader.ReadString(); switch (iname) { case "Property": WzSubProperty subProp = new WzSubProperty(name) { Parent = parent }; reader.BaseStream.Position += 2; subProp.AddProperties(IWzImageProperty.ParsePropertyList(offset, reader, subProp, imgParent)); return subProp; case "Canvas": WzCanvasProperty canvasProp = new WzCanvasProperty(name) { Parent = parent }; reader.BaseStream.Position++; if (reader.ReadByte() == 1) { reader.BaseStream.Position += 2; canvasProp.AddProperties(IWzImageProperty.ParsePropertyList(offset, reader, canvasProp, imgParent)); } canvasProp.PngProperty = new WzPngProperty(reader, imgParent.parseEverything) { Parent = canvasProp }; return canvasProp; case "Shape2D#Vector2D": WzVectorProperty vecProp = new WzVectorProperty(name) { Parent = parent }; vecProp.X = new WzCompressedIntProperty("X", reader.ReadCompressedInt()) { Parent = vecProp }; vecProp.Y = new WzCompressedIntProperty("Y", reader.ReadCompressedInt()) { Parent = vecProp }; return vecProp; case "Shape2D#Convex2D": WzConvexProperty convexProp = new WzConvexProperty(name) { Parent = parent }; int convexEntryCount = reader.ReadCompressedInt(); convexProp.WzProperties.Capacity = convexEntryCount; //performance thing for (int i = 0; i < convexEntryCount; i++) { convexProp.AddProperty(ParseExtendedProp(reader, offset, 0, name, convexProp, imgParent)); } return convexProp; case "Sound_DX8": WzSoundProperty soundProp = new WzSoundProperty(name, reader, imgParent.parseEverything) { Parent = parent }; return soundProp; case "UOL": reader.BaseStream.Position++; switch (reader.ReadByte()) { case 0: return new WzUOLProperty(name, reader.ReadString()) { Parent = parent }; case 1: return new WzUOLProperty(name, reader.ReadStringAtOffset(offset + reader.ReadInt32())) { Parent = parent }; } throw new Exception("Unsupported UOL type"); default: throw new Exception("Unknown iname: " + iname); } }
/// <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); }
internal static List<IWzImageProperty> ParsePropertyList(uint offset, WzBinaryReader reader, IWzObject parent, WzImage parentImg) { int entryCount = reader.ReadCompressedInt(); List<IWzImageProperty> properties = new List<IWzImageProperty>(entryCount); for (int i = 0; i < entryCount; i++) { string name = reader.ReadStringBlock(offset); switch (reader.ReadByte()) { case 0: properties.Add(new WzNullProperty(name) { Parent = parent/*, ParentImage = parentImg*/ }); break; case 0x0B: case 2: properties.Add(new WzUnsignedShortProperty(name, reader.ReadUInt16()) { Parent = parent/*, ParentImage = parentImg*/ }); break; case 3: properties.Add(new WzCompressedIntProperty(name, reader.ReadCompressedInt()) { Parent = parent/*, ParentImage = parentImg*/ }); break; case 4: byte type = reader.ReadByte(); if (type == 0x80) properties.Add(new WzByteFloatProperty(name, reader.ReadSingle()) { Parent = parent/*, ParentImage = parentImg*/ }); else if (type == 0) properties.Add(new WzByteFloatProperty(name, 0f) { Parent = parent/*, ParentImage = parentImg*/ }); break; case 5: properties.Add(new WzDoubleProperty(name, reader.ReadDouble()) { Parent = parent/*, ParentImage = parentImg*/ }); break; case 8: properties.Add(new WzStringProperty(name, reader.ReadStringBlock(offset)) { Parent = parent }); break; case 9: int eob = (int)(reader.ReadUInt32() + reader.BaseStream.Position); IWzImageProperty 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; }
private void ExtractSettingsImage(WzImage settingsImage, Type settingsHolderType) { if (!settingsImage.Parsed) { settingsImage.ParseImage(); } foreach (FieldInfo fieldInfo in settingsHolderType.GetFields(BindingFlags.Public | BindingFlags.Static)) { string settingName = fieldInfo.Name; WzImageProperty settingProp = settingsImage[settingName]; byte[] argb; if (settingProp == null) { SaveField(settingsImage, fieldInfo); } else if (fieldInfo.FieldType.BaseType != null && fieldInfo.FieldType.BaseType.FullName == "System.Enum") { fieldInfo.SetValue(null, InfoTool.GetInt(settingProp)); } else { switch (fieldInfo.FieldType.FullName) { //case "Microsoft.Xna.Framework.Graphics.Color": case "Microsoft.Xna.Framework.Color": if (xnaColorType == null) { throw new InvalidDataException("XNA color detected, but XNA type activator is null"); } argb = BitConverter.GetBytes((uint)((WzDoubleProperty)settingProp).Value); fieldInfo.SetValue(null, Activator.CreateInstance(xnaColorType, argb[0], argb[1], argb[2], argb[3])); break; case "System.Drawing.Color": argb = BitConverter.GetBytes((uint)((WzDoubleProperty)settingProp).Value); fieldInfo.SetValue(null, System.Drawing.Color.FromArgb(argb[3], argb[2], argb[1], argb[0])); break; case "System.Int32": fieldInfo.SetValue(null, InfoTool.GetInt(settingProp)); break; case "System.Double": fieldInfo.SetValue(null, ((WzDoubleProperty)settingProp).Value); break; case "System.Boolean": fieldInfo.SetValue(null, InfoTool.GetBool(settingProp)); //bool a = (bool)fieldInfo.GetValue(null); break; case "System.Single": fieldInfo.SetValue(null, ((WzFloatProperty)settingProp).Value); break; /*case "WzMapleVersion": * fieldInfo.SetValue(null, (WzMapleVersion)InfoTool.GetInt(settingProp)); * break; * case "ItemTypes": * fieldInfo.SetValue(null, (ItemTypes)InfoTool.GetInt(settingProp)); * break;*/ case "System.Drawing.Size": fieldInfo.SetValue(null, new System.Drawing.Size(((WzVectorProperty)settingProp).X.Value, ((WzVectorProperty)settingProp).Y.Value)); break; case "System.String": fieldInfo.SetValue(null, InfoTool.GetString(settingProp)); break; case "System.Drawing.Bitmap": fieldInfo.SetValue(null, ((WzCanvasProperty)settingProp).PngProperty.GetPNG(false)); break; default: throw new Exception("unrecognized setting type"); } } } }
private void ExtractPNGFromImage(WzImage image) { WzCanvasProperty reactorImage = WzInfoTools.GetReactorImage(image); if (reactorImage != null) { Image = reactorImage.PngProperty.GetPNG(false); Origin = WzInfoTools.VectorToSystemPoint((WzVectorProperty)reactorImage["origin"]); } else { Image = new Bitmap(1, 1); Origin = new System.Drawing.Point(); } }
/// <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; 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); 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(); } }
public static ReactorInfo Load(WzImage parentObject) { return new ReactorInfo(null, new System.Drawing.Point(), /*WzInfoTools.RemoveLeadingZeros(*/WzInfoTools.RemoveExtension(parentObject.Name)/*)*/, parentObject); }
/// <summary> /// Adds a WzImage to the list of wz images /// </summary> /// <param name="img">The WzImage to add</param> public void AddImage(WzImage img) { images.Add(img); img.Parent = this; }