/// <summary>Creates and loads a WZ file from a path. The Stream created will be disposed when the WZ file is disposed.</summary> /// <param name="path"> The path where the WZ file is located. </param> /// <param name="variant"> The variant of this WZ file. </param> /// <param name="encrypted"> Whether the WZ file is encrypted outside a WZ image. </param> /// <param name="flag"> WZ parsing flags. </param> public unsafe WZFile(string path, WZVariant variant, bool encrypted, WZReadSelection flag = WZReadSelection.None) { _variant = variant; _encrypted = encrypted; _flag = flag; _aes = new WZAES(_variant); _bpo = new MemoryMappedFile(path); _r = new WZBinaryReader(_bpo.Pointer, _bpo.Length, _aes, 0); Parse(); }
private static void Run(string inWz, string outPath, WZVariant wzVar, bool initialEnc) { Console.WriteLine("Input .wz: {0}{1}Output .nx: {2}", Path.GetFullPath(inWz), Environment.NewLine, Path.GetFullPath(outPath)); Stopwatch swOperation = new Stopwatch(); Stopwatch fullTimer = new Stopwatch(); Action <string> reportDone = str => { Console.WriteLine("done. E{0} T{1}", swOperation.Elapsed, fullTimer.Elapsed); swOperation.Restart(); Console.Write(str); }; fullTimer.Start(); swOperation.Start(); Console.Write("Parsing input WZ... ".PadRight(31)); WZReadSelection rFlags = WZReadSelection.EagerParseImage | WZReadSelection.EagerParseStrings; if (!dumpImg) { rFlags |= WZReadSelection.NeverParseCanvas; } using (WZFile wzf = new WZFile(inWz, wzVar, initialEnc, rFlags)) using ( FileStream outFs = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) using (BinaryWriter bw = new BinaryWriter(outFs)) { DumpState state = new DumpState(); reportDone("Writing header... ".PadRight(31)); bw.Write(PKG4); bw.Write(new byte[(4 + 8) * 4]); reportDone("Writing nodes... ".PadRight(31)); outFs.EnsureMultiple(4); ulong nodeOffset = (ulong)bw.BaseStream.Position; List <WZObject> nodeLevel = new List <WZObject> { wzf.MainDirectory }; while (nodeLevel.Count > 0) { WriteNodeLevel(ref nodeLevel, state, bw); } ulong stringOffset; uint stringCount = (uint)state.Strings.Count; { reportDone("Writing string data...".PadRight(31)); Dictionary <uint, string> strings = state.Strings.ToDictionary(kvp => kvp.Value, kvp => kvp.Key); ulong[] offsets = new ulong[stringCount]; for (uint idx = 0; idx < stringCount; ++idx) { outFs.EnsureMultiple(2); offsets[idx] = (ulong)bw.BaseStream.Position; WriteString(strings[idx], bw); } outFs.EnsureMultiple(8); stringOffset = (ulong)bw.BaseStream.Position; for (uint idx = 0; idx < stringCount; ++idx) { bw.Write(offsets[idx]); } } ulong bitmapOffset = 0UL; uint bitmapCount = 0U; if (dumpImg) { reportDone("Writing canvas data...".PadRight(31)); bitmapCount = (uint)state.Canvases.Count; ulong[] offsets = new ulong[bitmapCount]; long cId = 0; foreach (WZCanvasProperty cNode in state.Canvases) { outFs.EnsureMultiple(8); offsets[cId++] = (ulong)bw.BaseStream.Position; WriteBitmap(cNode, bw); } outFs.EnsureMultiple(8); bitmapOffset = (ulong)bw.BaseStream.Position; for (uint idx = 0; idx < bitmapCount; ++idx) { bw.Write(offsets[idx]); } } ulong soundOffset = 0UL; uint soundCount = 0U; if (dumpSnd) { reportDone("Writing MP3 data... ".PadRight(31)); soundCount = (uint)state.MP3s.Count; ulong[] offsets = new ulong[soundCount]; long cId = 0; foreach (WZAudioProperty mNode in state.MP3s) { outFs.EnsureMultiple(8); offsets[cId++] = (ulong)bw.BaseStream.Position; WriteMP3(mNode, bw); } outFs.EnsureMultiple(8); soundOffset = (ulong)bw.BaseStream.Position; for (uint idx = 0; idx < soundCount; ++idx) { bw.Write(offsets[idx]); } } reportDone("Writing linked node data... ".PadRight(31)); byte[] uolReplace = new byte[16]; foreach (KeyValuePair <WZUOLProperty, Action <BinaryWriter, byte[]> > pair in state.UOLs) { WZObject result = pair.Key.FinalTarget; if (result == null) { continue; } bw.BaseStream.Position = (long)(nodeOffset + state.GetNodeID(result) * 20 + 4); bw.BaseStream.Read(uolReplace, 0, 16); pair.Value(bw, uolReplace); } reportDone("Finalising... ".PadRight(31)); bw.Seek(4, SeekOrigin.Begin); bw.Write((uint)state.Nodes.Count); bw.Write(nodeOffset); bw.Write(stringCount); bw.Write(stringOffset); bw.Write(bitmapCount); bw.Write(bitmapOffset); bw.Write(soundCount); bw.Write(soundOffset); reportDone("Completed!"); } }