From b9f8e49f3e4a93391895e317422734cece750e58 Mon Sep 17 00:00:00 2001 From: Weber Tsai Date: Wed, 22 Sep 2021 12:50:16 +0800 Subject: [PATCH 1/2] Add Tool for convert nxfile [HaRepacker] Add converter to menu item [MapleLib] Add wzfile to nxfile serializer --- HaRepacker/GUI/MainForm.Designer.cs | 11 +- HaRepacker/GUI/MainForm.cs | 29 +- HaRepacker/GUI/MainForm.resx | 434 +++++++++++++------------- MapleLib/MapleLib.csproj | 4 + MapleLib/WzLib/Nx/WzToNxSerializer.cs | 420 +++++++++++++++++++++++++ MapleLib/packages.config | 1 + 6 files changed, 686 insertions(+), 213 deletions(-) create mode 100644 MapleLib/WzLib/Nx/WzToNxSerializer.cs diff --git a/HaRepacker/GUI/MainForm.Designer.cs b/HaRepacker/GUI/MainForm.Designer.cs index 322aa5e6..7c32c31c 100644 --- a/HaRepacker/GUI/MainForm.Designer.cs +++ b/HaRepacker/GUI/MainForm.Designer.cs @@ -105,6 +105,7 @@ private void InitializeComponent() this.AbortButton = new System.Windows.Forms.Button(); this.tabControl_MainPanels = new System.Windows.Forms.TabControl(); this.button_addTab = new System.Windows.Forms.Button(); + this.nXForamtToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.mainMenu.SuspendLayout(); this.SuspendLayout(); // @@ -397,7 +398,8 @@ private void InitializeComponent() this.exportFilesToXMLToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.xMLToolStripMenuItem, this.rawDataToolStripMenuItem, - this.imgToolStripMenuItem}); + this.imgToolStripMenuItem, + this.nXForamtToolStripMenuItem}); this.exportFilesToXMLToolStripMenuItem.Image = global::HaRepacker.Properties.Resources.folder_go; this.exportFilesToXMLToolStripMenuItem.Name = "exportFilesToXMLToolStripMenuItem"; resources.ApplyResources(this.exportFilesToXMLToolStripMenuItem, "exportFilesToXMLToolStripMenuItem"); @@ -627,6 +629,12 @@ private void InitializeComponent() this.button_addTab.UseVisualStyleBackColor = true; this.button_addTab.Click += new System.EventHandler(this.Button_addTab_Click); // + // nXForamtToolStripMenuItem + // + this.nXForamtToolStripMenuItem.Name = "nXForamtToolStripMenuItem"; + resources.ApplyResources(this.nXForamtToolStripMenuItem, "nXForamtToolStripMenuItem"); + this.nXForamtToolStripMenuItem.Click += new System.EventHandler(this.nXForamtToolStripMenuItem_Click); + // // MainForm // resources.ApplyResources(this, "$this"); @@ -722,6 +730,7 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripSeparator toolStripSeparator9; private System.Windows.Forms.ToolStripSeparator toolStripSeparator8; private System.Windows.Forms.ToolStripSeparator toolStripSeparator7; + private System.Windows.Forms.ToolStripMenuItem nXForamtToolStripMenuItem; } } diff --git a/HaRepacker/GUI/MainForm.cs b/HaRepacker/GUI/MainForm.cs index 43fd9cc6..7de10b01 100644 --- a/HaRepacker/GUI/MainForm.cs +++ b/HaRepacker/GUI/MainForm.cs @@ -31,6 +31,7 @@ using static MapleLib.Configuration.UserSettings; using HaSharedLibrary; using MapleLib.MapleCryptoLib; +using MapleLib.WzLib.Nx; namespace HaRepacker.GUI { @@ -1014,7 +1015,7 @@ private void RunWzFilesExtraction(object param) string[] wzFilesToDump = (string[])((object[])param)[0]; string baseDir = (string)((object[])param)[1]; - WzMapleVersion version = GetWzMapleVersionByWzEncryptionBoxSelection( ((int[])param)[2]); + WzMapleVersion version = GetWzMapleVersionByWzEncryptionBoxSelection((int)(((object[])param)[2])); IWzFileSerializer serializer = (IWzFileSerializer)((object[])param)[3]; UpdateProgressBar(MainPanel.mainProgressBar, 0, false, true); UpdateProgressBar(MainPanel.mainProgressBar, wzFilesToDump.Length, true, true); @@ -1901,5 +1902,31 @@ private void WzImporterThread(object param) threadDone = true; } + + private void nXForamtToolStripMenuItem_Click(object sender, EventArgs e) + { + OpenFileDialog dialog = new OpenFileDialog() + { + Title = HaRepacker.Properties.Resources.SelectWz, + Filter = string.Format("{0}|*.wz", HaRepacker.Properties.Resources.WzFilter), + Multiselect = true + }; + + if (dialog.ShowDialog() != DialogResult.OK) + return; + + string outPath = GetOutputDirectory(); + if (outPath == string.Empty) + { + MessageBox.Show(Properties.Resources.MainWzExportError, Properties.Resources.Warning, MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + + WzToNxSerializer serializer = new WzToNxSerializer(); + threadDone = false; + runningThread = new Thread(new ParameterizedThreadStart(RunWzFilesExtraction)); + runningThread.Start((object)new object[] { dialog.FileNames, outPath, encryptionBox.SelectedIndex, serializer }); + new Thread(new ParameterizedThreadStart(ProgressBarThread)).Start(serializer); + } } } diff --git a/HaRepacker/GUI/MainForm.resx b/HaRepacker/GUI/MainForm.resx index 4859532b..7c10aaf2 100644 --- a/HaRepacker/GUI/MainForm.resx +++ b/HaRepacker/GUI/MainForm.resx @@ -121,14 +121,160 @@ 17, 17 + + 38, 21 + + + File + + + 41, 21 + + + Edit + + + 180, 22 + + + Private Server XML + + + 180, 22 + + + PNG\MP3 + + + 180, 22 + + + IMG + + + 180, 22 + + + NXForamt + + + 188, 30 + + + Export File(s) to + + + 188, 30 + + + Export Selection + + + 188, 30 + + + Import + + + 185, 6 + + + 188, 30 + + + Options... + + + 185, 6 + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAI6SURBVDhPY/j//z9FGKsgKRhDoLl/zqMlG/b8b504 + F8j9zzB5wTowOzQ29RayOhjGEKho7nu0bsdhkAYg9z9DRlHN/77ZK/4DDX6CrA6G4Yyk7JL/XdOX/K/t + nPq/bdL8/yaWdkDh/wwObj7/s0rq/hdUtYLFrOxdlysoqfIICosygQ1YsGYnR1Ftu0dT32ywUwur2/57 + +If9d/EK+J9T1vA/Ni3vf0RO0//aicv+l7RMActxc/NUsbGzM4INmDB3NcuUhesfLlq3639ueRMYV09c + 9X/K8l3/+5Zs/9U4fcP/2t75/6Nzm/+HJxeCXcjMwvKAgYGBGWwA0LmsIJunLd74P7u0/j/Izym55f+j + k3P+q2npgW0EuQQmHpdeANTF8A+IWcEGpBVUsvqFxvy0sHX67xUY8d/Ywva/tr7xf1kF5aciYuIGkjJy + W8UkpP4D/f1fVFzyPy8f/39GRsZ3QAMgYQAifIKiDoMCbtfhM/9XbTnwv3vGMlCArQDJqWrqrKhsmfB/ + 7Y5DYDlQjPDxCx4GycENcPMJ/pNf0Qw2AOii//EZhf/1jM2vguSANl8FxQDIgNT8iv/phdX/OTi5/qAY + 4Oju+x9mAEyRhrb+T0UVdUYJadl3oICDGQAKC1ZWNqA2JAOsHd3A8QxKQCAFoMDUNTL7D/Q/v5KqxhWQ + AaBYgskBwwDVAFACMTCxBAce0M//gTb/l5ZV+A8MRCmgf29zcnH/B8Y7KPqAOhjAGMUASjBWQeLxfwYA + njJojew6/+MAAAAASUVORK5CYII= + + + + 188, 30 + + + Search (Ctrl+F) + + + 50, 21 + + + Tools + + + 52, 21 + + + Extras + + + Segoe UI, 8.25pt + + + 268, 21 + + + 46, 21 + + + Help + + + 101, 21 + + + DEBUG MODE + + + + False + + + 0, 0 + + + 997, 25 + + + 1 + + + menuStrip1 + + + mainMenu + + + System.Windows.Forms.MenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + - 215, 22 + 222, 22 New (Ctl + T) - 215, 22 + 222, 22 Open WZ; ZLZ.dll (Ctl + O) @@ -151,28 +297,28 @@ - 215, 22 + 222, 22 Save... - 212, 6 + 219, 6 - 215, 22 + 222, 22 Copy (Ctrl+C) - 215, 22 + 222, 22 Paste (Ctrl+V) - 212, 6 + 219, 6 @@ -191,7 +337,7 @@ - 215, 22 + 222, 22 Reload All @@ -214,149 +360,142 @@ - 215, 22 + 222, 22 Unload All - - 37, 21 + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKFSURBVDhPpZP9S1NRHMb9W/SXAiEpMQsFNaUEC2Vl + s01UdJou52yKznY3l865zRcynRu+VNSGbqORbtM5Hb5gJk4tXaRehxJtFEFQG/76dM+GTk2C6IHnwP1+ + z+e595x7TgyA//IfBY2rLq7dWUu1OgR083hVUPKmItjwupQWmYspwQg37vT8Ew8al4ilnKwNvFrrxUpg + Ad7v61j7toxJnxUyZzUqDewA78Vt1nHmFCwMuXat2P+1i5kvDhjoATzf1sK6Z8Di11mo58UoGs4NcQZy + jkLCg3pKFMvA/okdE3Z/bmFoqwdPV9vR5WmF1qtBn1eNro0WTOxbQTn5yNfd8Of1ZsYeBTCwtH9JgU8/ + Npg39qF3Uw3VOxnTikixKoZkgQ/pUg3sexbcHc5CzpM0KdOKBLTYq2mHz8J8qhEdK3K0LUsgnhGEYaIq + CwcN08UQTXGh/6BBz2Izrnel0EwrEiAdqzxwf3ag/6OGgZvC0FkSThZAOlcJk3cIGZrkA6YUCWiy8g7G + faNQr1OQe+rDk88SCaDcFTB7B5HanhgNqLeU0DqPGtpNFZre8iGcKwXPfCcMERGQ+KGTg36PAp3uR7ii + SIguQThaKL1vZsHmM0E8V4Zad1F4zYcisMDORt0EF7YdI651JyPxcXx0E/nGgtjyl/l+ylmFMXrkaMMI + WGMnJjAH49sGPDDdI7A/QXY++huJS57lsQoHb4YabWWwMyE6jxLUdDkkU2XQrbTBxsB8ExuJ8vgQA588 + SIdm67NZLG1WIFefju55Csb3WhjXtVC5G5HRmUTgwHGY+EQA8a2e9Ljs7lQqs+MqnaZKCqYoLwYvt16g + L8njqQTZub9fpn83Yn4DQUbLHyk4qYsAAAAASUVORK5CYII= + - - File + + 188, 30 + + + Add - 180, 22 + 169, 22 Directory - 180, 22 + 169, 22 Image - 180, 22 + 169, 22 Sub - 180, 22 + 169, 22 Uol - 177, 6 + 166, 6 - 180, 22 + 169, 22 Canvas / Image - 177, 6 + 166, 6 - 180, 22 + 169, 22 String - 180, 22 + 169, 22 Byte or Float - 180, 22 + 169, 22 Long - 180, 22 + 169, 22 Double - 180, 22 + 169, 22 Int - 180, 22 + 169, 22 Short - 177, 6 + 166, 6 - 180, 22 + 169, 22 Convex - 180, 22 + 169, 22 Null - 180, 22 + 169, 22 Binary (mp3, bin) - 180, 22 + 169, 22 Vector (x, y) - 180, 22 + 169, 22 Lua Script - False - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m - dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKFSURBVDhPpZP9S1NRHMb9W/SXAiEpMQsFNaUEC2Vl - s01UdJou52yKznY3l865zRcynRu+VNSGbqORbtM5Hb5gJk4tXaRehxJtFEFQG/76dM+GTk2C6IHnwP1+ - z+e595x7TgyA//IfBY2rLq7dWUu1OgR083hVUPKmItjwupQWmYspwQg37vT8Ew8al4ilnKwNvFrrxUpg - Ad7v61j7toxJnxUyZzUqDewA78Vt1nHmFCwMuXat2P+1i5kvDhjoATzf1sK6Z8Di11mo58UoGs4NcQZy - jkLCg3pKFMvA/okdE3Z/bmFoqwdPV9vR5WmF1qtBn1eNro0WTOxbQTn5yNfd8Of1ZsYeBTCwtH9JgU8/ - Npg39qF3Uw3VOxnTikixKoZkgQ/pUg3sexbcHc5CzpM0KdOKBLTYq2mHz8J8qhEdK3K0LUsgnhGEYaIq - CwcN08UQTXGh/6BBz2Izrnel0EwrEiAdqzxwf3ag/6OGgZvC0FkSThZAOlcJk3cIGZrkA6YUCWiy8g7G - faNQr1OQe+rDk88SCaDcFTB7B5HanhgNqLeU0DqPGtpNFZre8iGcKwXPfCcMERGQ+KGTg36PAp3uR7ii - SIguQThaKL1vZsHmM0E8V4Zad1F4zYcisMDORt0EF7YdI651JyPxcXx0E/nGgtjyl/l+ylmFMXrkaMMI - WGMnJjAH49sGPDDdI7A/QXY++huJS57lsQoHb4YabWWwMyE6jxLUdDkkU2XQrbTBxsB8ExuJ8vgQA588 - SIdm67NZLG1WIFefju55Csb3WhjXtVC5G5HRmUTgwHGY+EQA8a2e9Ljs7lQqs+MqnaZKCqYoLwYvt16g - L8njqQTZub9fpn83Yn4DQUbLHyk4qYsAAAAASUVORK5CYII= - - - - 188, 30 - - - Add - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m @@ -416,156 +555,80 @@ Collapse All - - 39, 21 - - - Edit - - - 172, 22 - - - Private Server XML - - - 172, 22 - - - PNG\MP3 - - - 172, 22 - - - IMG - - - 188, 30 + + 180, 22 - - Export File(s) to + + XML - 144, 22 + 180, 22 Private server - 144, 22 + 180, 22 Classic - 144, 22 + 180, 22 New - - 127, 22 - - - XML - - 127, 22 + 180, 22 JSON - 127, 22 + 180, 22 BSON - 127, 22 + 180, 22 PNG\MP3 - 127, 22 + 180, 22 IMG - - 188, 30 - - - Export Selection - - 98, 22 + 100, 22 XML - 98, 22 + 100, 22 IMG - - 188, 30 - - - Import - - - 185, 6 - - - 188, 30 - - - Options... - - - 185, 6 - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m - dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAI6SURBVDhPY/j//z9FGKsgKRhDoLl/zqMlG/b8b504 - F8j9zzB5wTowOzQ29RayOhjGEKho7nu0bsdhkAYg9z9DRlHN/77ZK/4DDX6CrA6G4Yyk7JL/XdOX/K/t - nPq/bdL8/yaWdkDh/wwObj7/s0rq/hdUtYLFrOxdlysoqfIICosygQ1YsGYnR1Ftu0dT32ywUwur2/57 - +If9d/EK+J9T1vA/Ni3vf0RO0//aicv+l7RMActxc/NUsbGzM4INmDB3NcuUhesfLlq3639ueRMYV09c - 9X/K8l3/+5Zs/9U4fcP/2t75/6Nzm/+HJxeCXcjMwvKAgYGBGWwA0LmsIJunLd74P7u0/j/Izym55f+j - k3P+q2npgW0EuQQmHpdeANTF8A+IWcEGpBVUsvqFxvy0sHX67xUY8d/Ywva/tr7xf1kF5aciYuIGkjJy - W8UkpP4D/f1fVFzyPy8f/39GRsZ3QAMgYQAifIKiDoMCbtfhM/9XbTnwv3vGMlCArQDJqWrqrKhsmfB/ - 7Y5DYDlQjPDxCx4GycENcPMJ/pNf0Qw2AOii//EZhf/1jM2vguSANl8FxQDIgNT8iv/phdX/OTi5/qAY - 4Oju+x9mAEyRhrb+T0UVdUYJadl3oICDGQAKC1ZWNqA2JAOsHd3A8QxKQCAFoMDUNTL7D/Q/v5KqxhWQ - AaBYgskBwwDVAFACMTCxBAce0M//gTb/l5ZV+A8MRCmgf29zcnH/B8Y7KPqAOhjAGMUASjBWQeLxfwYA - njJojew6/+MAAAAASUVORK5CYII= - - - - 188, 30 - - - Search (Ctrl+F) - - - 46, 21 + + 173, 22 - - Tools + + FH Mapping - 185, 22 + 194, 22 Render Map (Ctl + R) - 185, 22 + 194, 22 Settings... @@ -579,81 +642,24 @@ 1 - - 180, 22 - - - FH Mapping - - 180, 22 + 173, 22 Search WZ strings - - 50, 21 - - - Extras - - - Segoe UI, 8.25pt - - - 268, 21 - - 173, 22 + 181, 22 View Help - 173, 22 + 181, 22 About HaRepacker - - 44, 21 - - - Help - - - 93, 21 - - - DEBUG MODE - - - False - - - 0, 0 - - - 997, 25 - - - 1 - - - menuStrip1 - - - mainMenu - - - System.Windows.Forms.MenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 3 - NoControl @@ -2849,6 +2855,12 @@ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + nXForamtToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + MainForm diff --git a/MapleLib/MapleLib.csproj b/MapleLib/MapleLib.csproj index 3ebfe8e5..5302ceb0 100644 --- a/MapleLib/MapleLib.csproj +++ b/MapleLib/MapleLib.csproj @@ -99,6 +99,9 @@ MinimumRecommendedRules.ruleset + + ..\packages\lz4net.1.0.15.93\lib\net4-client\LZ4.dll + ..\packages\Microsoft.Win32.Registry.5.0.0\lib\net461\Microsoft.Win32.Registry.dll @@ -204,6 +207,7 @@ + diff --git a/MapleLib/WzLib/Nx/WzToNxSerializer.cs b/MapleLib/WzLib/Nx/WzToNxSerializer.cs new file mode 100644 index 00000000..03fae6d3 --- /dev/null +++ b/MapleLib/WzLib/Nx/WzToNxSerializer.cs @@ -0,0 +1,420 @@ +using LZ4; +using MapleLib.WzLib.Serialization; +using MapleLib.WzLib.WzProperties; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace MapleLib.WzLib.Nx +{ + internal static class Extension + { + public static void EnsureMultiple(this Stream s, int multiple) + { + int skip = (int)(multiple - (s.Position % multiple)); + if (skip == multiple) + return; + s.Write(new byte[skip], 0, skip); + } + + + public static T[] SubArray(this T[] array, int offset, int length) + { + T[] result = new T[length]; + Array.Copy(array, offset, result, 0, length); + return result; + } + } + + public class WzToNxSerializer : ProgressingWzSerializer, IWzFileSerializer + { + private static readonly byte[] PKG4 = { 0x50, 0x4B, 0x47, 0x34 }; // PKG4 + private static readonly bool _is64bit = IntPtr.Size == 8; + + + public void SerializeFile(WzFile file, string path) + { + String filename = file.Name.Replace(".wz", ".nx"); + using (FileStream fs = new FileStream(Path.Combine(Path.GetDirectoryName(path), filename), FileMode.Create, FileAccess.ReadWrite, + FileShare.None)) + using (BinaryWriter bw = new BinaryWriter(fs)) + { + DumpState state = new DumpState(); + bw.Write(PKG4); + bw.Write(new byte[(4 + 8) * 4]); + fs.EnsureMultiple(4); + ulong nodeOffset = (ulong)bw.BaseStream.Position; + List nodeLevel = new List { file.WzDirectory }; + while (nodeLevel.Count > 0) + WriteNodeLevel(ref nodeLevel, state, bw); + + ulong stringOffset; + uint stringCount = (uint)state.Strings.Count; + { + Dictionary strings = state.Strings.ToDictionary(kvp => kvp.Value, + kvp => kvp.Key); + ulong[] offsets = new ulong[stringCount]; + for (uint idx = 0; idx < stringCount; ++idx) + { + fs.EnsureMultiple(2); + offsets[idx] = (ulong)bw.BaseStream.Position; + WriteString(strings[idx], bw); + } + + fs.EnsureMultiple(8); + stringOffset = (ulong)bw.BaseStream.Position; + for (uint idx = 0; idx < stringCount; ++idx) + bw.Write(offsets[idx]); + } + + ulong bitmapOffset = 0UL; + uint bitmapCount = 0U; + bool flag = true; + if (flag) + { + bitmapCount = (uint)state.Canvases.Count; + ulong[] offsets = new ulong[bitmapCount]; + long cId = 0; + foreach (WzCanvasProperty cNode in state.Canvases) + { + fs.EnsureMultiple(8); + offsets[cId++] = (ulong)bw.BaseStream.Position; + WriteBitmap(cNode, bw); + } + fs.EnsureMultiple(8); + bitmapOffset = (ulong)bw.BaseStream.Position; + for (uint idx3 = 0U; idx3 < bitmapCount; idx3 += 1U) + { + bw.Write(offsets[(int)idx3]); + } + } + ulong soundOffset = 0UL; + uint soundCount = 0U; + bool flag2 = true; + if (flag2) + { + soundCount = (uint)state.MP3s.Count; + ulong[] offsets = new ulong[soundCount]; + long cId = 0L; + foreach (WzBinaryProperty mNode in state.MP3s) + { + fs.EnsureMultiple(8); + offsets[cId++] = (ulong)bw.BaseStream.Position; + WriteMP3(mNode, bw); + } + fs.EnsureMultiple(8); + soundOffset = (ulong)bw.BaseStream.Position; + for (uint idx4 = 0U; idx4 < soundCount; idx4 += 1U) + { + bw.Write(offsets[(int)idx4]); + } + } + byte[] uolReplace = new byte[16]; + foreach (KeyValuePair> pair in state.UOLs) + { + WzObject result = pair.Key.LinkValue; + bool flag3 = result == null; + if (!flag3) + { + bw.BaseStream.Position = (long)(nodeOffset + (ulong)(state.GetNodeID(result) * 20U) + 4UL); + bw.BaseStream.Read(uolReplace, 0, 16); + pair.Value(bw, uolReplace); + } + } + 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); + + + } + + } + + + private byte[] GetCompressedBitmap(Bitmap b) + { + BitmapData bd = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); + int inLen = Math.Abs(bd.Stride) * bd.Height; + byte[] rgbValues = new byte[inLen]; + Marshal.Copy(bd.Scan0, rgbValues, 0, inLen); + + var compressed = LZ4Codec.WrapHC(rgbValues); + + return compressed.SubArray(8, compressed.Length - 8); + } + + private void WriteBitmap(WzCanvasProperty node, BinaryWriter bw) + { + Bitmap b = node.PngProperty.GetBitmap(); + byte[] compressed = GetCompressedBitmap(b); + bw.Write((uint)compressed.Length); + bw.Write(compressed); + } + + private void WriteMP3(WzBinaryProperty node, BinaryWriter bw) + { + byte[] i = node.GetBytes(); + bw.Write(i); + } + + private void WriteString(string s, BinaryWriter bw) + { + bool flag = s.Any(new Func(char.IsControl)); + if (flag) + { + Console.WriteLine("Warning; control character in string. Perhaps toggle /wzn?"); + } + byte[] toWrite = Encoding.UTF8.GetBytes(s); + bw.Write((ushort)toWrite.Length); + bw.Write(toWrite); + } + + private void WriteNodeLevel(ref List nodeLevel, DumpState ds, BinaryWriter bw) + { + uint nextChildId = (uint)((ulong)ds.GetNextNodeID() + (ulong)((long)nodeLevel.Count)); + foreach (WzObject levelNode in nodeLevel) + { + bool flag = levelNode is WzUOLProperty; + if (flag) + { + WriteUOL((WzUOLProperty)levelNode, ds, bw); + } + else + { + WriteNode(levelNode, ds, bw, nextChildId); + } + nextChildId += (uint)GetChildCount(levelNode); + } + List @out = new List(); + foreach (WzObject levelNode2 in nodeLevel) + { + List childs = GetChildObjects(levelNode2); + @out.AddRange(childs); + } + nodeLevel.Clear(); + nodeLevel = @out; + } + + private void WriteUOL(WzUOLProperty node, DumpState ds, BinaryWriter bw) + { + ds.AddNode(node); + bw.Write(ds.AddString(node.Name)); + ds.AddUOL(node, bw.BaseStream.Position); + bw.Write(0L); + bw.Write(0L); + } + + public List GetChildObjects(WzObject node) + { + List childs = new List(); + bool flag = node is WzDirectory; + if (flag) + { + childs.AddRange(((WzDirectory)node).WzImages); + childs.AddRange(((WzDirectory)node).WzDirectories); + } + else + { + bool flag2 = node is WzImage; + if (flag2) + { + childs.AddRange(((WzImage)node).WzProperties); + } + else + { + bool flag3 = node is WzImageProperty && !(node is WzUOLProperty); + if (flag3) + { + bool flag4 = ((WzImageProperty)node).WzProperties != null; + if (flag4) + { + childs.AddRange(((WzImageProperty)node).WzProperties); + } + } + } + } + return childs; + } + private int GetChildCount(WzObject node) + { + return GetChildObjects(node).Count(); + } + private void WriteNode(WzObject node, DumpState ds, BinaryWriter bw, uint nextChildID) + { + ds.AddNode(node); + bw.Write(ds.AddString(node.Name)); + bw.Write(nextChildID); + bw.Write((ushort)GetChildCount(node)); + + ushort type; + + if (node is WzDirectory || node is WzImage || node is WzSubProperty || node is WzConvexProperty || node is WzNullProperty) + type = 0; // no data; children only (8) + else if (node is WzIntProperty || node is WzShortProperty || node is WzLongProperty) + type = 1; // int32 (4) + else if (node is WzDoubleProperty || node is WzFloatProperty) + type = 2; // Double (0) + else if (node is WzStringProperty || node is WzLuaProperty) + type = 3; // String (4) + else if (node is WzVectorProperty) + type = 4; // (0) + else if (node is WzCanvasProperty) + type = 5; // (4) + else if (node is WzBinaryProperty) + type = 6; // (4) + else + throw new InvalidOperationException("Unhandled WZ node type [1]"); + + bw.Write(type); + if (node is WzIntProperty) + { + bw.Write((long)((WzIntProperty)node).Value); + } + else if (node is WzShortProperty) + { + bw.Write((long)((WzShortProperty)node).Value); + } + else if (node is WzLongProperty) + { + bw.Write(((WzLongProperty)node).Value); + } + else if (node is WzFloatProperty) + { + bw.Write((double)((WzFloatProperty)node).Value); + } + else if (node is WzDoubleProperty) + { + bw.Write(((WzDoubleProperty)node).Value); + } + else if (node is WzStringProperty) + { + bw.Write(ds.AddString(((WzStringProperty)node).Value)); + } + else if (node is WzVectorProperty) + { + Point pNode = ((WzVectorProperty)node).Pos; + bw.Write(pNode.X); + bw.Write(pNode.Y); + } + else if (node is WzCanvasProperty) + { + WzCanvasProperty wzcp = (WzCanvasProperty)node; + bw.Write(ds.AddCanvas(wzcp)); + bool flag16 = true; // export canvas + if (flag16) + { + bw.Write((ushort)wzcp.PngProperty.GetBitmap().Width); + bw.Write((ushort)wzcp.PngProperty.GetBitmap().Height); + } + else + { + bw.Write(0); + } + } + else if (node is WzBinaryProperty) + { + WzBinaryProperty wzmp = (WzBinaryProperty)node; + bw.Write(ds.AddMP3(wzmp)); + bool flag18 = true; + if (flag18) + { + bw.Write((uint)wzmp.GetBytes().Length); + } + else + { + bw.Write(0); + } + } + switch (type) + { + case 0: + bw.Write(0L); + break; + case 3: + bw.Write(0); + break; + } + } + + private sealed class DumpState + { + public DumpState() + { + Canvases = new List(); + Strings = new Dictionary(StringComparer.Ordinal) { { "", 0 } }; + MP3s = new List(); + UOLs = new Dictionary>(); + Nodes = new Dictionary(); + } + + public List Canvases { get; } + + public Dictionary Strings { get; } + + public List MP3s { get; } + + public Dictionary> UOLs { get; } + + public Dictionary Nodes { get; } + + public uint AddCanvas(WzCanvasProperty node) + { + uint ret = (uint)Canvases.Count; + Canvases.Add(node); + return ret; + } + + public uint AddMP3(WzBinaryProperty node) + { + uint ret = (uint)MP3s.Count; + MP3s.Add(node); + return ret; + } + + public uint AddString(string str) + { + if (Strings.ContainsKey(str)) + return Strings[str]; + uint ret = (uint)Strings.Count; + Strings.Add(str, ret); + return ret; + } + + public void AddNode(WzObject node) + { + uint ret = (uint)Nodes.Count; + Nodes.Add(node, ret); + } + + public uint GetNodeID(WzObject node) + { + return Nodes[node]; + } + + public uint GetNextNodeID() + { + return (uint)Nodes.Count; + } + + public void AddUOL(WzUOLProperty node, long currentPosition) + { + UOLs.Add(node, (bw, data) => { + bw.BaseStream.Position = currentPosition; + bw.Write(data); + }); + } + } + } +} diff --git a/MapleLib/packages.config b/MapleLib/packages.config index cd85e948..aea90295 100644 --- a/MapleLib/packages.config +++ b/MapleLib/packages.config @@ -1,5 +1,6 @@  + From 9c097099126fdb90705b13e1716a60868a4f9422 Mon Sep 17 00:00:00 2001 From: Weber Tsai Date: Wed, 22 Sep 2021 12:52:24 +0800 Subject: [PATCH 2/2] add wz2nx code references --- MapleLib/WzLib/Nx/WzToNxSerializer.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MapleLib/WzLib/Nx/WzToNxSerializer.cs b/MapleLib/WzLib/Nx/WzToNxSerializer.cs index 03fae6d3..07adec14 100644 --- a/MapleLib/WzLib/Nx/WzToNxSerializer.cs +++ b/MapleLib/WzLib/Nx/WzToNxSerializer.cs @@ -9,8 +9,10 @@ using System.Linq; using System.Runtime.InteropServices; using System.Text; -using System.Threading.Tasks; +/// +/// The code was modified from https://github.com/angelsl/wz2nx +/// namespace MapleLib.WzLib.Nx { internal static class Extension