diff --git a/pk3DS/Main.cs b/pk3DS/Main.cs index d29b6bc..d2ab0fb 100644 --- a/pk3DS/Main.cs +++ b/pk3DS/Main.cs @@ -421,8 +421,9 @@ private void B_Wild_Click(object sender, EventArgs e) { if (advanced) { - string[] files = { "encdata", "storytext" }; - fileGet(files, false); + string[] files = { "encdata", "storytext", "mapGR", "mapMatrix" }; + if (files.Sum(t => Directory.Exists(t) ? 0 : 1) != 0) + fileGet(files, false); Invoke((MethodInvoker)delegate { Enabled = false; }); { Invoke((Action)(() => new xytext(Directory.GetFiles("storytext")).Show())); diff --git a/pk3DS/Structs.cs b/pk3DS/Structs.cs index 1fcda1c..ca0dce5 100644 --- a/pk3DS/Structs.cs +++ b/pk3DS/Structs.cs @@ -556,7 +556,8 @@ public MapMatrix(byte[] data) for (int i = 0; i < Area; i++) EntryList[i] = br.ReadUInt16(); - uL = br.ReadUInt16(); + if (br.BaseStream.Position != br.BaseStream.Length) + uL = br.ReadUInt16(); } } public byte[] Write() @@ -573,30 +574,29 @@ public byte[] Write() } } - public Image Preview(int Scale, int Spacing, int ColorShift) + public Image Preview(int Scale, int ColorShift) { // Require the entries to be defined in order to continue. if (Entries.Any(entry => entry == null)) - return null; + { + // Do nothing; images are instead created with the standard dimensions and returned. + } // Fetch Singular Images first Image[] EntryImages = new Image[Area]; for (int i = 0; i < Area; i++) - EntryImages[i] = Entries[i].Preview(Scale, Spacing, ColorShift); + EntryImages[i] = (Entries[i] == null) + ? new Bitmap(40 * Scale, 40 * Scale) + : Entries[i].Preview(Scale, ColorShift); // Combine all images into one. - Bitmap img = new Bitmap(EntryImages[0].Width * Width, EntryImages[1].Height * Height); + Bitmap img = new Bitmap(EntryImages[0].Width * Width, EntryImages[0].Height * Height); + + using (Graphics g = Graphics.FromImage(img)) for (int i = 0; i < Area; i++) - { try { - for (int x = 0; x < EntryImages[i].Width; x++) - for (int y = 0; y < EntryImages[i].Height; y++) - { - img.SetPixel( - x + (i * EntryImages[0].Width) % (img.Width), // Shifted X - y + EntryImages[0].Height * ((i / Width)), // Shifted Y - img.GetPixel(x, y)); // Color at Pixel - } - } catch { } } + { + g.DrawImage(EntryImages[i], new Point((i * EntryImages[0].Width) % (img.Width), EntryImages[0].Height * ((i / Width)))); + } return img; } @@ -628,9 +628,9 @@ public byte[] Write() return ms.ToArray(); } } - public Image Preview(int s, int Spacing, int ColorShift) + public Image Preview(int s, int ColorShift) { - Bitmap img = new Bitmap(Width*s + 2*Spacing, Height*s + 2*Spacing); + Bitmap img = new Bitmap(Width*s, Height*s); for (int i = 0; i < Area; i++) { Color c = Tiles[i] == 0x01000021 @@ -642,8 +642,8 @@ public Image Preview(int s, int Spacing, int ColorShift) for (int y = 0; y < s; y++) { img.SetPixel( - x + (i*s)%(img.Width) + Spacing, - y + ((i/Width)*s) + Spacing, + x + (i * s) % (img.Width), + y + ((i/Width)*s), c); } } diff --git a/pk3DS/Subforms/OWSE.cs b/pk3DS/Subforms/OWSE.cs index 6d4f727..81c2849 100644 --- a/pk3DS/Subforms/OWSE.cs +++ b/pk3DS/Subforms/OWSE.cs @@ -43,7 +43,7 @@ private void openQuick(string[] encdata) zdLocations = new string[filepaths.Length]; rawLocations = new string[filepaths.Length]; - TB_File5.Visible = Main.oras; // 5th File is only present with OR/AS. + tb_File5.Visible = Main.oras; // 5th File is only present with OR/AS. // Analyze for (int f = 0; f < filepaths.Length; f++) @@ -180,12 +180,14 @@ private void getOWSData() byte[] zd = zonedata.Skip(56*entry).Take(56).ToArray(); ushort text = BitConverter.ToUInt16(zonedata, 56*entry + 6); - ushort map = BitConverter.ToUInt16(zonedata, 56*entry + 2); + ushort map = BitConverter.ToUInt16(zonedata, 56*entry + 4); RTB_zonedata.Lines = Scripts.getHexLines(zd, 0x10); L_ZDPreview.Text = "Text File: " + text + Environment.NewLine + "Map File: " + map; // Fetch Map Image + DrawMap = map; + PB_Map.Image = getMapImage(); byte[] owData = data.Skip(4).Take(len).ToArray(); // Process owData Header @@ -472,5 +474,54 @@ internal static void parseScriptInput(byte[] OWScriptData) } System.Media.SystemSounds.Asterisk.Play(); } + + private int DrawMap = -1; + private Image getMapImage() + { + // Load MM + byte[][] MM = CTR.mini.unpackMini(File.ReadAllBytes(MapMatrixes[DrawMap]), "MM"); + MapMatrix mm = new MapMatrix(MM[0]); + + // Load GR TileMaps + for (int i = 0; i < mm.EntryList.Length; i++) + { + if (mm.EntryList[i] == 0xFFFF) // Mystery Zone + continue; + byte[][] GR = CTR.mini.unpackMini(File.ReadAllBytes(MapGRs[mm.EntryList[i]]), "GR"); + mm.Entries[i] = new MapMatrix.Entry(GR[0]); + } + Image img = mm.Preview((int)NUD_Scale.Value, (int)NUD_Flavor.Value); + img = Util.TrimBitmap((Bitmap)img); + PB_Map.Size = new Size(img.Width + 2, img.Height + 2); + return img; + } + private void B_Redraw_Click(object sender, EventArgs e) + { + if (DrawMap != -1) + PB_Map.Image = getMapImage(); + + if (ModifierKeys != Keys.Control || + Util.Prompt(MessageBoxButtons.YesNoCancel, "Export all?") != DialogResult.Yes) + return; + + const string folder = "MapImages"; + if (!Directory.Exists(folder)) + Directory.CreateDirectory(folder); + + for (int i = 0; i < CB_LocationID.Items.Count; i++) + { + DrawMap = BitConverter.ToUInt16(zonedata, 56 * i + 4); + Image img = getMapImage(); + using (MemoryStream ms = new MemoryStream()) + { + //error will throw from here + img.Save(ms, System.Drawing.Imaging.ImageFormat.Png); + byte[] data = ms.ToArray(); + File.WriteAllBytes(Path.Combine(folder, String.Format("{0} ({1}).png", zdLocations[i].Replace('?', '-'), DrawMap)), data); + } + } + CB_LocationID.SelectedIndex = 0; + Util.Alert("All Dumped!"); + } } } \ No newline at end of file diff --git a/pk3DS/Subforms/OWSE.designer.cs b/pk3DS/Subforms/OWSE.designer.cs index 85627df..a36d4c7 100644 --- a/pk3DS/Subforms/OWSE.designer.cs +++ b/pk3DS/Subforms/OWSE.designer.cs @@ -80,9 +80,9 @@ private void InitializeComponent() this.RTB_MS = new System.Windows.Forms.RichTextBox(); this.tb_Encounters = new System.Windows.Forms.TabPage(); this.L_Encounters = new System.Windows.Forms.Label(); - this.TB_File5 = new System.Windows.Forms.TabPage(); + this.tb_File5 = new System.Windows.Forms.TabPage(); this.L_File5TabData = new System.Windows.Forms.Label(); - this.tabPage1 = new System.Windows.Forms.TabPage(); + this.tb_RAW = new System.Windows.Forms.TabPage(); this.L_File3 = new System.Windows.Forms.Label(); this.L_ZD = new System.Windows.Forms.Label(); this.L_File5 = new System.Windows.Forms.Label(); @@ -96,6 +96,13 @@ private void InitializeComponent() this.RTB_MapSC = new System.Windows.Forms.RichTextBox(); this.L_ZDPreview = new System.Windows.Forms.Label(); this.B_HLCMD = new System.Windows.Forms.Button(); + this.tb_Map = new System.Windows.Forms.TabPage(); + this.PB_Map = new System.Windows.Forms.PictureBox(); + this.NUD_Flavor = new System.Windows.Forms.NumericUpDown(); + this.L_Flavor = new System.Windows.Forms.Label(); + this.B_Redraw = new System.Windows.Forms.Button(); + this.L_Scale = new System.Windows.Forms.Label(); + this.NUD_Scale = new System.Windows.Forms.NumericUpDown(); this.tabControl1.SuspendLayout(); this.tb_MapInfo.SuspendLayout(); this.tb_OWSC.SuspendLayout(); @@ -118,8 +125,12 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)(this.NUD_NPCCount)).BeginInit(); this.tb_MSC.SuspendLayout(); this.tb_Encounters.SuspendLayout(); - this.TB_File5.SuspendLayout(); - this.tabPage1.SuspendLayout(); + this.tb_File5.SuspendLayout(); + this.tb_RAW.SuspendLayout(); + this.tb_Map.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PB_Map)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.NUD_Flavor)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.NUD_Scale)).BeginInit(); this.SuspendLayout(); // // CB_LocationID @@ -162,8 +173,9 @@ private void InitializeComponent() this.tabControl1.Controls.Add(this.tb_OWSC); this.tabControl1.Controls.Add(this.tb_MSC); this.tabControl1.Controls.Add(this.tb_Encounters); - this.tabControl1.Controls.Add(this.TB_File5); - this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tb_File5); + this.tabControl1.Controls.Add(this.tb_RAW); + this.tabControl1.Controls.Add(this.tb_Map); this.tabControl1.Location = new System.Drawing.Point(12, 32); this.tabControl1.Name = "tabControl1"; this.tabControl1.SelectedIndex = 0; @@ -722,15 +734,15 @@ private void InitializeComponent() this.L_Encounters.TabIndex = 0; this.L_Encounters.Text = "Encounters are handled in the regular Wild Editor."; // - // TB_File5 + // tb_File5 // - this.TB_File5.Controls.Add(this.L_File5TabData); - this.TB_File5.Location = new System.Drawing.Point(4, 22); - this.TB_File5.Name = "TB_File5"; - this.TB_File5.Size = new System.Drawing.Size(486, 471); - this.TB_File5.TabIndex = 4; - this.TB_File5.Text = "File 5"; - this.TB_File5.UseVisualStyleBackColor = true; + this.tb_File5.Controls.Add(this.L_File5TabData); + this.tb_File5.Location = new System.Drawing.Point(4, 22); + this.tb_File5.Name = "tb_File5"; + this.tb_File5.Size = new System.Drawing.Size(486, 471); + this.tb_File5.TabIndex = 4; + this.tb_File5.Text = "File 5"; + this.tb_File5.UseVisualStyleBackColor = true; // // L_File5TabData // @@ -741,26 +753,26 @@ private void InitializeComponent() this.L_File5TabData.TabIndex = 1; this.L_File5TabData.Text = "Functionality unknown. See RAW tab for data."; // - // tabPage1 + // tb_RAW // - this.tabPage1.Controls.Add(this.L_File3); - this.tabPage1.Controls.Add(this.L_ZD); - this.tabPage1.Controls.Add(this.L_File5); - this.tabPage1.Controls.Add(this.L_File4); - this.tabPage1.Controls.Add(this.L_File2); - this.tabPage1.Controls.Add(this.L_File1); - this.tabPage1.Controls.Add(this.RTB_zonedata); - this.tabPage1.Controls.Add(this.RTB_MapInfo); - this.tabPage1.Controls.Add(this.RTB_File5); - this.tabPage1.Controls.Add(this.RTB_OWSC); - this.tabPage1.Controls.Add(this.RTB_Encounter); - this.tabPage1.Controls.Add(this.RTB_MapSC); - this.tabPage1.Location = new System.Drawing.Point(4, 22); - this.tabPage1.Name = "tabPage1"; - this.tabPage1.Size = new System.Drawing.Size(486, 471); - this.tabPage1.TabIndex = 5; - this.tabPage1.Text = "RAW"; - this.tabPage1.UseVisualStyleBackColor = true; + this.tb_RAW.Controls.Add(this.L_File3); + this.tb_RAW.Controls.Add(this.L_ZD); + this.tb_RAW.Controls.Add(this.L_File5); + this.tb_RAW.Controls.Add(this.L_File4); + this.tb_RAW.Controls.Add(this.L_File2); + this.tb_RAW.Controls.Add(this.L_File1); + this.tb_RAW.Controls.Add(this.RTB_zonedata); + this.tb_RAW.Controls.Add(this.RTB_MapInfo); + this.tb_RAW.Controls.Add(this.RTB_File5); + this.tb_RAW.Controls.Add(this.RTB_OWSC); + this.tb_RAW.Controls.Add(this.RTB_Encounter); + this.tb_RAW.Controls.Add(this.RTB_MapSC); + this.tb_RAW.Location = new System.Drawing.Point(4, 22); + this.tb_RAW.Name = "tb_RAW"; + this.tb_RAW.Size = new System.Drawing.Size(486, 471); + this.tb_RAW.TabIndex = 5; + this.tb_RAW.Text = "RAW"; + this.tb_RAW.UseVisualStyleBackColor = true; // // L_File3 // @@ -887,6 +899,94 @@ private void InitializeComponent() this.B_HLCMD.UseVisualStyleBackColor = true; this.B_HLCMD.Click += new System.EventHandler(this.B_HLCMD_Click); // + // tb_Map + // + this.tb_Map.Controls.Add(this.B_Redraw); + this.tb_Map.Controls.Add(this.L_Scale); + this.tb_Map.Controls.Add(this.NUD_Scale); + this.tb_Map.Controls.Add(this.L_Flavor); + this.tb_Map.Controls.Add(this.NUD_Flavor); + this.tb_Map.Controls.Add(this.PB_Map); + this.tb_Map.Location = new System.Drawing.Point(4, 22); + this.tb_Map.Name = "tb_Map"; + this.tb_Map.Padding = new System.Windows.Forms.Padding(3); + this.tb_Map.Size = new System.Drawing.Size(486, 471); + this.tb_Map.TabIndex = 6; + this.tb_Map.Text = "Map Preview"; + this.tb_Map.UseVisualStyleBackColor = true; + // + // PB_Map + // + this.PB_Map.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None; + this.PB_Map.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.PB_Map.Location = new System.Drawing.Point(6, 32); + this.PB_Map.Name = "PB_Map"; + this.PB_Map.Size = new System.Drawing.Size(300, 124); + this.PB_Map.TabIndex = 2; + this.PB_Map.TabStop = false; + // + // NUD_Flavor + // + this.NUD_Flavor.Location = new System.Drawing.Point(51, 6); + this.NUD_Flavor.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.NUD_Flavor.Name = "NUD_Flavor"; + this.NUD_Flavor.Size = new System.Drawing.Size(37, 20); + this.NUD_Flavor.TabIndex = 3; + this.NUD_Flavor.Value = new decimal(new int[] { + 2, + 0, + 0, + 0}); + // + // L_Flavor + // + this.L_Flavor.AutoSize = true; + this.L_Flavor.Location = new System.Drawing.Point(6, 8); + this.L_Flavor.Name = "L_Flavor"; + this.L_Flavor.Size = new System.Drawing.Size(39, 13); + this.L_Flavor.TabIndex = 4; + this.L_Flavor.Text = "Flavor:"; + // + // B_Redraw + // + this.B_Redraw.Location = new System.Drawing.Point(180, 4); + this.B_Redraw.Name = "B_Redraw"; + this.B_Redraw.Size = new System.Drawing.Size(75, 23); + this.B_Redraw.TabIndex = 9; + this.B_Redraw.Text = "Redraw"; + this.B_Redraw.UseVisualStyleBackColor = true; + this.B_Redraw.Click += new System.EventHandler(this.B_Redraw_Click); + // + // L_Scale + // + this.L_Scale.AutoSize = true; + this.L_Scale.Location = new System.Drawing.Point(94, 8); + this.L_Scale.Name = "L_Scale"; + this.L_Scale.Size = new System.Drawing.Size(37, 13); + this.L_Scale.TabIndex = 6; + this.L_Scale.Text = "Scale:"; + // + // NUD_Scale + // + this.NUD_Scale.Location = new System.Drawing.Point(137, 6); + this.NUD_Scale.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.NUD_Scale.Name = "NUD_Scale"; + this.NUD_Scale.Size = new System.Drawing.Size(37, 20); + this.NUD_Scale.TabIndex = 5; + this.NUD_Scale.Value = new decimal(new int[] { + 3, + 0, + 0, + 0}); + // // OWSE // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -929,9 +1029,14 @@ private void InitializeComponent() this.tb_MSC.PerformLayout(); this.tb_Encounters.ResumeLayout(false); this.tb_Encounters.PerformLayout(); - this.TB_File5.ResumeLayout(false); - this.TB_File5.PerformLayout(); - this.tabPage1.ResumeLayout(false); + this.tb_File5.ResumeLayout(false); + this.tb_File5.PerformLayout(); + this.tb_RAW.ResumeLayout(false); + this.tb_Map.ResumeLayout(false); + this.tb_Map.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PB_Map)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.NUD_Flavor)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.NUD_Scale)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -947,7 +1052,7 @@ private void InitializeComponent() private System.Windows.Forms.TabPage tb_OWSC; private System.Windows.Forms.TabPage tb_MSC; private System.Windows.Forms.TabPage tb_Encounters; - private System.Windows.Forms.TabPage TB_File5; + private System.Windows.Forms.TabPage tb_File5; private System.Windows.Forms.TabControl tc_OWSC; private System.Windows.Forms.TabPage tb_Furniture; private System.Windows.Forms.TabPage tb_Overworld; @@ -985,7 +1090,7 @@ private void InitializeComponent() private System.Windows.Forms.Label L_DestWarpTile; private System.Windows.Forms.Label L_DestMap; private System.Windows.Forms.Label L_OWSCDesc; - private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tb_RAW; private System.Windows.Forms.Label L_MSSCDesc; private System.Windows.Forms.RichTextBox RTB_MS; private System.Windows.Forms.Label L_WarpDest; @@ -1007,6 +1112,13 @@ private void InitializeComponent() private System.Windows.Forms.RichTextBox RTB_OSP; private System.Windows.Forms.RichTextBox RTB_MSP; private System.Windows.Forms.Button B_HLCMD; + private System.Windows.Forms.TabPage tb_Map; + private System.Windows.Forms.Label L_Flavor; + private System.Windows.Forms.NumericUpDown NUD_Flavor; + private System.Windows.Forms.PictureBox PB_Map; + private System.Windows.Forms.Button B_Redraw; + private System.Windows.Forms.Label L_Scale; + private System.Windows.Forms.NumericUpDown NUD_Scale; } } diff --git a/pk3DS/Util.cs b/pk3DS/Util.cs index 98ef711..adc9d74 100644 --- a/pk3DS/Util.cs +++ b/pk3DS/Util.cs @@ -5,6 +5,7 @@ using System.Globalization; using System.IO; using System.Linq; +using System.Runtime.InteropServices; using System.Text.RegularExpressions; using System.Windows.Forms; @@ -639,5 +640,116 @@ internal static int highlightText(RichTextBox RTB, string word, Color hlColor) RTB.SelectionColor = Color.Black; return ctr; } + // http://stackoverflow.com/questions/4820212/automatically-trim-a-bitmap-to-minimum-size + internal static Bitmap TrimBitmap(Bitmap source) + { + Rectangle srcRect = default(Rectangle); + BitmapData data = null; + try + { + data = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); + byte[] buffer = new byte[data.Height * data.Stride]; + Marshal.Copy(data.Scan0, buffer, 0, buffer.Length); + + int xMin = int.MaxValue, + xMax = int.MinValue, + yMin = int.MaxValue, + yMax = int.MinValue; + + bool foundPixel = false; + + // Find xMin + for (int x = 0; x < data.Width; x++) + { + bool stop = false; + for (int y = 0; y < data.Height; y++) + { + byte alpha = buffer[y * data.Stride + 4 * x + 3]; + if (alpha != 0) + { + xMin = x; + stop = true; + foundPixel = true; + break; + } + } + if (stop) + break; + } + + // Image is empty... + if (!foundPixel) + return null; + + // Find yMin + for (int y = 0; y < data.Height; y++) + { + bool stop = false; + for (int x = xMin; x < data.Width; x++) + { + byte alpha = buffer[y * data.Stride + 4 * x + 3]; + if (alpha != 0) + { + yMin = y; + stop = true; + break; + } + } + if (stop) + break; + } + + // Find xMax + for (int x = data.Width - 1; x >= xMin; x--) + { + bool stop = false; + for (int y = yMin; y < data.Height; y++) + { + byte alpha = buffer[y * data.Stride + 4 * x + 3]; + if (alpha != 0) + { + xMax = x; + stop = true; + break; + } + } + if (stop) + break; + } + + // Find yMax + for (int y = data.Height - 1; y >= yMin; y--) + { + bool stop = false; + for (int x = xMin; x <= xMax; x++) + { + byte alpha = buffer[y * data.Stride + 4 * x + 3]; + if (alpha != 0) + { + yMax = y; + stop = true; + break; + } + } + if (stop) + break; + } + + srcRect = Rectangle.FromLTRB(xMin, yMin, xMax, yMax); + } + finally + { + if (data != null) + source.UnlockBits(data); + } + + Bitmap dest = new Bitmap(srcRect.Width, srcRect.Height); + Rectangle destRect = new Rectangle(0, 0, srcRect.Width, srcRect.Height); + using (Graphics graphics = Graphics.FromImage(dest)) + { + graphics.DrawImage(source, destRect, srcRect, GraphicsUnit.Pixel); + } + return dest; + } } }