internal static WZObject ParseExtendedProperty(string name, WZBinaryReader r, WZObject parent, WZImage f, bool encrypted) { string type = r.ReadWZStringBlock(encrypted); switch (type) { case "Property": r.Skip(2); return(new WZSubProperty(name, parent, r, f)); case "Canvas": return(new WZCanvasProperty(name, parent, r, f)); case "Shape2D#Vector2D": return(new WZPointProperty(name, parent, r, f)); case "Shape2D#Convex2D": return(new WZConvexProperty(name, parent, r, f)); case "Sound_DX8": return(new WZAudioProperty(name, parent, r, f)); case "UOL": r.Skip(1); return(new WZLinkProperty(name, parent, r, f)); default: return(WZUtil.Die <WZObject>($"Unknown ExtendedProperty type \"{type}\"")); } }
internal WZSubProperty(string name, WZObject parent, WZBinaryReader r, WZImage container) : base(name, parent, default(WZNothing), container, true, WZObjectType.SubProperty) { foreach (WZObject c in WZExtendedParser.ParsePropertyList(r, this, Image, Image._encrypted)) { Add(c); } }
internal WZDelayedProperty(string name, WZObject parent, WZImage container, WZBinaryReader r, bool children, WZObjectType type) : base(name, parent, default(T), container, children, type) { _offset = r.Position; _parsed = Parse(r, true, out _value); _r = r; }
private static float ReadSingle(WZBinaryReader reader) { byte t = reader.ReadByte(); return(t == 0x80 ? reader.ReadSingle() : (t == 0 ? 0f : WZUtil.Die <float>("Unknown byte while reading WZSingleProperty."))); }
internal WZImage(string name, WZObject parent, WZFile file, WZBinaryReader reader) : base(name, parent, file, true, WZObjectType.Image) { _r = reader; if ((file._flag & WZReadSelection.EagerParseImage) == WZReadSelection.EagerParseImage) { Parse(); } }
internal static List <WZObject> ParsePropertyList(WZBinaryReader r, WZObject parent, WZImage f, bool encrypted) { int num = r.ReadWZInt(); List <WZObject> ret = new List <WZObject>(num); for (int i = 0; i < num; ++i) { string name = r.ReadWZStringBlock(encrypted); byte type = r.ReadByte(); switch (type) { case 0: ret.Add(new WZNullProperty(name, parent, f)); break; case 0x0B: case 2: ret.Add(new WZUInt16Property(name, parent, r, f)); break; case 0x13: case 3: ret.Add(new WZInt32Property(name, parent, r, f)); break; case 0x14: ret.Add(new WZInt64Property(name, parent, r, f)); break; case 4: ret.Add(new WZSingleProperty(name, parent, r, f)); break; case 5: ret.Add(new WZDoubleProperty(name, parent, r, f)); break; case 8: ret.Add(new WZStringProperty(name, parent, r, f)); break; case 9: uint blockLen = r.ReadUInt32(); ret.Add(ParseExtendedProperty(name, r.Clone(), parent, f, encrypted)); r.Skip(blockLen); break; default: return (WZUtil.Die <List <WZObject> >( $"Unknown property type {type} at ParsePropertyList")); } } return(ret); }
internal void CheckParsed() { if (_parsed) { return; } WZBinaryReader r = _r.Clone(); r.Seek(_offset); Parse(r, false, out _value); }
internal WZConvexProperty(string name, WZObject parent, WZBinaryReader r, WZImage container) : base(name, parent, default(WZNothing), container, true, WZObjectType.Convex) { int count = r.ReadWZInt(); for (int i = 0; i < count; ++i) { Add(WZExtendedParser.ParseExtendedProperty(i.ToString(CultureInfo.InvariantCulture), r, this, Image, Image._encrypted)); } }
private void Parse(WZBinaryReader wzbr, long offset) { wzbr.Seek(offset); int entryCount = wzbr.ReadWZInt(); for (int i = 0; i < entryCount; ++i) { byte type = wzbr.ReadByte(); string name = null; switch (type) { case 2: int x = wzbr.ReadInt32(); wzbr.PeekFor(() => { wzbr.Seek(x + File._fstart); type = wzbr.ReadByte(); name = wzbr.ReadWZString(File._encrypted); }); break; case 3: case 4: name = wzbr.ReadWZString(File._encrypted); break; case 1: // wzbr.Skip(10); // continue; default: WZUtil.Die($"Unknown object type {type} in WzDirectory."); break; } if (name == null) { WZUtil.Die("Failed to read WZDirectory entry name."); } int size = wzbr.ReadWZInt(); wzbr.ReadWZInt(); uint woffset = wzbr.ReadWZOffset(File._fstart); switch (type) { case 3: Add(new WZDirectory(name, this, File, wzbr.Clone(), woffset)); break; case 4: Add(new WZImage(name, this, File, File.GetSubstream(woffset, size))); break; } } }
internal override bool Parse(WZBinaryReader r, bool initial, out string result) { if (!initial || (File._flag & WZReadSelection.EagerParseStrings) == WZReadSelection.EagerParseStrings) { result = string.Intern(r.ReadWZStringBlock(Image._encrypted)); return(true); } else { r.SkipWZStringBlock(); result = null; return(false); } }
internal override bool Parse(WZBinaryReader r, bool initial, out byte[] result) { r.Skip(1); int blockLen = r.ReadWZInt(); // sound data length Duration = r.ReadWZInt(); // sound duration r.Skip(1 + 16 + 16 + 2); // Byte, Major type GUID, Sub type GUID, byte, byte Guid fmt = new Guid(r.ReadBytes(16)); if (fmt == WaveFormatExGuid) { if (initial) { r.Skip(r.ReadWZInt()); } else { _header = r.ReadBytes(r.ReadWZInt()); if (_header.Length != 18 + GetCbSize(_header)) { _header = null; // TODO FIXME figure out what those gibberish headers are } // But in any case they don't affect our uses // File._aes.DecryptBytesAsciiKey(_header); //if (_header.Length != 18 + GetCbSize(_header)) // Debug.WriteLine("Failed to parse WAVEFORMATEX header at node {0}", Path); //throw new WZException($"Failed to parse WAVEFORMATEX header at node {Path}"); } } else if (fmt != NoHeaderGuid) { Debug.WriteLine("New format guid {0} @ {1}", fmt, Path); } if (!initial || (File._flag & WZReadSelection.EagerParseAudio) == WZReadSelection.EagerParseAudio) { result = r.ReadBytes(blockLen); return(true); } else { r.Skip(blockLen); result = null; return(false); } }
internal WZDoubleProperty(string name, WZObject parent, WZBinaryReader reader, WZImage container) : base(name, parent, reader.ReadDouble(), container, false, WZObjectType.Double) { }
internal WZStringProperty(string name, WZObject parent, WZBinaryReader reader, WZImage container) : base(name, parent, container, reader, false, WZObjectType.String) { }
internal WZSingleProperty(string name, WZObject parent, WZBinaryReader reader, WZImage container) : base(name, parent, ReadSingle(reader), container, false, WZObjectType.Single) { }
private static unsafe Bitmap ParsePNG(int width, int height, int format1, int scale, byte[] data) { byte[] dec; using (MemoryStream @in = new MemoryStream(data, 0, data.Length)) { dec = WZBinaryReader.Inflate(@in); } int decLen = dec.Length; width >>= scale; height >>= scale; switch (format1) { case 0x001: { if (decLen != width * height * 2) { Debug.WriteLine("Warning; dec.Length != 2wh; ARGB4444"); } Bitmap ret = new Bitmap(width, height, PixelFormat.Format32bppArgb); BitmapData bd = ret.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); try { fixed(byte *t = dec) { byte *u = t, s = (byte *)bd.Scan0; for (int i = 0; i < decLen; i++) { *s++ = (byte)((*u & 0x0F) * 0x11); *s++ = (byte)(((*u++ & 0xF0) >> 4) * 0x11); } } } finally { ret.UnlockBits(bd); } return(ret); } case 0x002: if (decLen != width * height * 4) { Debug.WriteLine("Warning; dec.Length != 4wh; 32BPP"); } return(BitmapFromBytes(width, height, PixelFormat.Format32bppArgb, dec)); case 0x201: if (decLen != width * height * 2) { Debug.WriteLine("Warning; dec.Length != 2wh; 16BPP"); } return(BitmapFromBytes(width, height, PixelFormat.Format16bppRgb565, dec)); case 0x402: { Bitmap ret = new Bitmap(width, height, PixelFormat.Format32bppArgb); BitmapData bd = ret.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); try { fixed(byte *decP = dec) { UnDXT.DecompressImage((byte *)bd.Scan0, width, height, decP, UnDXT.kDxt3); } } finally { ret.UnlockBits(bd); } return(ret); } default: Debug.WriteLine("Unknown bitmap type format1:{0} scale:{1}", format1, scale); return(null); } }
internal WZUInt16Property(string name, WZObject parent, WZBinaryReader reader, WZImage container) : base(name, parent, reader.ReadUInt16(), container, false, WZObjectType.UInt16) { }
internal WZInt64Property(string name, WZObject parent, WZBinaryReader reader, WZImage container) : base(name, parent, reader.ReadWZLong(), container, false, WZObjectType.Int64) { }
internal WZPointProperty(string name, WZObject parent, WZBinaryReader wzbr, WZImage container) : base(name, parent, new Point(wzbr.ReadWZInt(), wzbr.ReadWZInt()), container, false, WZObjectType.Point) { }
internal WZLinkProperty(string name, WZObject parent, WZBinaryReader reader, WZImage container) : base( name, parent, string.Intern(reader.ReadWZStringBlock(container._encrypted)), container, false, WZObjectType.Link) { }
internal WZCanvasProperty(string name, WZObject parent, WZBinaryReader br, WZImage container) : base(name, parent, container, br, true, WZObjectType.Canvas) { }
internal override bool Parse(WZBinaryReader br, bool initial, out Bitmap result) { bool skip = (File._flag & WZReadSelection.NeverParseCanvas) == WZReadSelection.NeverParseCanvas, eager = (File._flag & WZReadSelection.EagerParseCanvas) == WZReadSelection.EagerParseCanvas; if (initial) { if (skip && eager) { result = null; return(WZUtil.Die <bool>("Both NeverParseCanvas and EagerParseCanvas are set.")); } br.Skip(1); if (br.ReadByte() == 1) { br.Skip(2); List <WZObject> l = WZExtendedParser.ParsePropertyList(br, this, Image, Image._encrypted); if (ChildCount == 0) { l.ForEach(Add); } } _afterChildren = br.Position; } else { br.Position = _afterChildren; } int width = br.ReadWZInt(); // width int height = br.ReadWZInt(); // height int format1 = br.ReadWZInt(); // format 1 int scale = br.ReadByte(); // format 2 br.Skip(4); int blockLen = br.ReadInt32(); if ((initial || skip) && !eager) { br.Skip(blockLen); // block Len & png data result = null; return(skip); } else { br.Skip(1); byte[] header = br.ReadBytes(2); // FLG bit 5 indicates the presence of a preset dictionary // seems like MS doesn't use that? if ((header[1] & 0x20) != 0) { Debug.WriteLine("Warning; zlib with preset dictionary"); result = null; br.Skip(blockLen - 3); return(true); } // zlib header: CMF (byte), FLG (byte) byte[] pngData = br.ReadBytes(blockLen - 3); result = ParsePNG(width, height, format1, scale, // CMF least significant bits 0 to 3 are compression method. only 8 is valid (header[0] & 0xF) != 8 || // CMF << 8 | FLG i.e. header read as a big-endian short is a multiple of 31 (header[0] << 8 | header[1]) % 31 != 0 ? DecryptPNG(pngData) : pngData); return(true); } }
internal abstract bool Parse(WZBinaryReader r, bool initial, out T result);
internal WZDirectory(string name, WZObject parent, WZFile file, WZBinaryReader wzbr, long offset) : base(name, parent, file, true, WZObjectType.Directory) { Parse(wzbr, offset); }