From 7805d4a04247b08f4537abfe6ad5ef6eedf93171 Mon Sep 17 00:00:00 2001 From: pokecal Date: Mon, 10 Apr 2017 04:17:42 +0900 Subject: [PATCH] Poketch DotArtEdit drag&drop will import file, click will edit directly. --- .../Save Editors/Gen4/SAV_Misc4.Designer.cs | 26 ++- .../Subforms/Save Editors/Gen4/SAV_Misc4.cs | 177 +++++++++++++++++- PKHeX/Saves/SAV4.cs | 30 +++ 3 files changed, 225 insertions(+), 8 deletions(-) diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.Designer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.Designer.cs index 8df89c911..911a836b0 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.Designer.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.Designer.cs @@ -33,6 +33,7 @@ private void InitializeComponent() this.B_Save = new System.Windows.Forms.Button(); this.TC_Misc = new System.Windows.Forms.TabControl(); this.TAB_Poketch = new System.Windows.Forms.TabPage(); + this.PB_DotArtist = new System.Windows.Forms.PictureBox(); this.B_GiveAll = new System.Windows.Forms.Button(); this.CHK_App25 = new System.Windows.Forms.CheckBox(); this.CHK_App24 = new System.Windows.Forms.CheckBox(); @@ -61,6 +62,7 @@ private void InitializeComponent() this.CHK_App01 = new System.Windows.Forms.CheckBox(); this.TC_Misc.SuspendLayout(); this.TAB_Poketch.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PB_DotArtist)).BeginInit(); this.SuspendLayout(); // // B_Cancel @@ -96,6 +98,8 @@ private void InitializeComponent() // // TAB_Poketch // + this.TAB_Poketch.AllowDrop = true; + this.TAB_Poketch.Controls.Add(this.PB_DotArtist); this.TAB_Poketch.Controls.Add(this.B_GiveAll); this.TAB_Poketch.Controls.Add(this.CHK_App25); this.TAB_Poketch.Controls.Add(this.CHK_App24); @@ -129,6 +133,18 @@ private void InitializeComponent() this.TAB_Poketch.TabIndex = 0; this.TAB_Poketch.Text = "Poketch"; this.TAB_Poketch.UseVisualStyleBackColor = true; + this.TAB_Poketch.DragDrop += new System.Windows.Forms.DragEventHandler(this.TAB_Poketch_DragDrop); + this.TAB_Poketch.DragEnter += new System.Windows.Forms.DragEventHandler(this.TAB_Poketch_DragEnter); + // + // PB_DotArtist + // + this.PB_DotArtist.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.PB_DotArtist.Location = new System.Drawing.Point(277, 145); + this.PB_DotArtist.Name = "PB_DotArtist"; + this.PB_DotArtist.Size = new System.Drawing.Size(96, 80); + this.PB_DotArtist.TabIndex = 26; + this.PB_DotArtist.TabStop = false; + this.PB_DotArtist.MouseClick += new System.Windows.Forms.MouseEventHandler(this.PB_DotArtist_MouseClick); // // B_GiveAll // @@ -215,9 +231,9 @@ private void InitializeComponent() this.CHK_App18.AutoSize = true; this.CHK_App18.Location = new System.Drawing.Point(151, 160); this.CHK_App18.Name = "CHK_App18"; - this.CHK_App18.Size = new System.Drawing.Size(91, 16); + this.CHK_App18.Size = new System.Drawing.Size(117, 16); this.CHK_App18.TabIndex = 17; - this.CHK_App18.Text = "18 Dot Artist"; + this.CHK_App18.Text = "18 Dot Artist -->"; this.CHK_App18.UseVisualStyleBackColor = true; // // CHK_App17 @@ -401,10 +417,11 @@ private void InitializeComponent() this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Name = "SAV_Misc4"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "SAV_Misc4"; + this.Text = "Misc Editor"; this.TC_Misc.ResumeLayout(false); this.TAB_Poketch.ResumeLayout(false); this.TAB_Poketch.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PB_DotArtist)).EndInit(); this.ResumeLayout(false); } @@ -441,5 +458,6 @@ private void InitializeComponent() private System.Windows.Forms.CheckBox CHK_App07; private System.Windows.Forms.CheckBox CHK_App06; private System.Windows.Forms.Button B_GiveAll; + private System.Windows.Forms.PictureBox PB_DotArtist; } -} \ No newline at end of file +} diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.cs index c3beaf586..81f77ab6a 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.cs @@ -1,4 +1,8 @@ using System; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; using System.Windows.Forms; using PKHeX.Core; @@ -20,22 +24,165 @@ public SAV_Misc4() }; int ret = SAV.PoketchApps; - for(int i = 0; i < Apps.Length; i++) - { + for (int i = 0; i < Apps.Length; i++) Apps[i].Checked = (ret & 1 << i) != 0; - } + DotArtistByte = SAV.PoketchDotArtist; + ColorTable = new byte[4] { 248, 168, 88, 8 }; + setPictureBoxFromFlags(DotArtistByte); + string tip = "Guide about D&D ImageFile Format"; + tip += Environment.NewLine + " width = 24px"; + tip += Environment.NewLine + " height = 20px"; + tip += Environment.NewLine + " used color count <= 4"; + tip += Environment.NewLine + " file size < 2058byte"; + tip1.SetToolTip(PB_DotArtist, tip); } private readonly CheckBox[] Apps; + private byte[] DotArtistByte; + private readonly byte[] ColorTable; + private readonly ToolTip tip1 = new ToolTip(); + + private void setPictureBoxFromFlags(byte[] inp) + { + if (inp.Length != 120) return; + byte[] dupbyte = new byte[23040]; + byte ict; + for (int iy = 0, iz, ib; iy < 20; iy++) + for (int ix = 0; ix < 24; ix++) + { + ib = ix + 24 * iy; + ict = ColorTable[inp[ib >> 2] >> (ib % 4 << 1) & 3]; + iz = 12 * ix + 1152 * iy; + for (int izy = 0; izy < 4; izy++) + for (int izx = 0; izx < 4; izx++) + for (int ic = 0; ic < 3; ic++) + dupbyte[ic + 3 * izx + 288 * izy + iz] = ict; + } + Bitmap dabmp = new Bitmap(96, 80); + BitmapData dabdata = dabmp.LockBits(new Rectangle(0, 0, dabmp.Width, dabmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); + System.Runtime.InteropServices.Marshal.Copy(dupbyte, 0, dabdata.Scan0, dupbyte.Length); + dabmp.UnlockBits(dabdata); + PB_DotArtist.Image = dabmp; + } + private void setFlagsFromFileName(string inpFileName) + { + if (new FileInfo(inpFileName).Length > 2058) return; // 24*20*4(ARGB)=1920 + Bitmap bmp; + FileStream fs = new FileStream(inpFileName, FileMode.Open, FileAccess.Read); + try + { + bmp = (Bitmap)Image.FromStream(fs); + } + catch + { + bmp = null; + } + fs.Close(); + if (bmp == null || bmp.Width != 24 || bmp.Height != 20) return; + + byte[] BrightMap = new byte[480]; + byte[] BrightCount = new byte[0x100]; + byte[] iBrightCount = new byte[0x100]; + byte ig; + for (int iy = 0; iy < 20; iy++) + for (int ix = 0; ix < 24; ix++) + { + ig = (byte)(0xFF * bmp.GetPixel(ix, iy).GetBrightness()); + BrightMap[ix + 24 * iy] = ig; + BrightCount[ig]++; + } + + int ColorCount = BrightCount.Count(v => v > 0); + if (ColorCount > 4 || ColorCount == 0) return; + int errtot, errmin = int.MaxValue; + byte[] LCT = new byte[4]; + byte[] mLCT = new byte[4]; + for (int i = 0; i < 4; i++) + LCT[i] = (byte)(ColorCount < i + 1 ? 4 : ColorCount - i - 1); + int ee = 0; + while (++ee < 1000) + { + BrightCount.CopyTo(iBrightCount, 0); + for (int i = 0, j = 0; i < 0x100; i++) + if (iBrightCount[i] > 0) + iBrightCount[i] = LCT[j++]; + errtot = 0; + for (int i = 0; i < 480; i++) + errtot += Math.Abs(BrightMap[i] - ColorTable[iBrightCount[BrightMap[i]]]); + if (errmin > errtot) + { + errmin = errtot; + LCT.CopyTo(mLCT, 0); + } + LCT = getNextLCT(LCT); + if (LCT[0] >= 4) break; + } + for (int i = 0, j = 0; i < 0x100; i++) + if (BrightCount[i] > 0) + BrightCount[i] = mLCT[j++]; + for (int i = 0; i < 480; i++) + BrightMap[i] = BrightCount[BrightMap[i]]; + + byte[] ndab = new byte[120]; + for (int i = 0; i < 480; i++) + ndab[i >> 2] |= (byte)((BrightMap[i] & 3) << (i % 4 << 1)); + + ndab.CopyTo(DotArtistByte, 0); + } + + private byte[] getNextLCT(byte[] inp) + { + while (true) + { + if (++inp[0] >= 4) + { + inp[0] = 0; + if (++inp[1] >= 4) + { + inp[1] = 0; + if (++inp[2] >= 4) + { + inp[2] = 0; + if (++inp[3] >= 4) + { + inp[0] = 4; + return inp; + } + } + } + } + if (inp[1] < 4 && inp[1] >= inp[0]) continue; + if (inp[2] < 4 && inp[2] >= inp[1]) continue; + if (inp[3] < 4 && inp[3] >= inp[2]) continue; + } + return inp; + } + + private void setFlagsFromClickPoint(int inpX, int inpY) + { + if (inpX < 0) inpX = 0; + else if (inpX > 95) inpX = 95; + if (inpY < 0) inpY = 0; + else if (inpY > 79) inpY = 79; + int i = (inpX >> 2) + 24 * (inpY >> 2); + byte[] ndab = new byte[120]; + DotArtistByte.CopyTo(ndab, 0); + byte c = (byte)(ndab[i >> 2] >> (i % 4 << 1) & 3); + if (++c >= 4) c = 0; + ndab[i >> 2] &= (byte)~(3 << (i % 4 << 1)); + ndab[i >> 2] |= (byte)((c & 3) << (i % 4 << 1)); + ndab.CopyTo(DotArtistByte, 0); + } private void saveMisc() { int ret = 0; - for(int i = 0; i < Apps.Length; i++) + for (int i = 0; i < Apps.Length; i++) { if (Apps[i].Checked) ret |= 1 << i; } SAV.PoketchApps = ret; + SAV.PoketchDotArtist = DotArtistByte; } private void B_Save_Click(object sender, EventArgs e) @@ -55,5 +202,27 @@ private void B_GiveAll_Click(object sender, EventArgs e) { foreach (CheckBox c in Apps) c.Checked = true; } + + private void TAB_Poketch_DragEnter(object sender, DragEventArgs e) + { + if (e.Data.GetDataPresent(DataFormats.FileDrop)) + e.Effect = DragDropEffects.Copy; + else + e.Effect = DragDropEffects.None; + } + + private void TAB_Poketch_DragDrop(object sender, DragEventArgs e) + { + string[] t = (string[])e.Data.GetData(DataFormats.FileDrop, false); + if (t.Length != 1) return; + setFlagsFromFileName(t[0]); + setPictureBoxFromFlags(DotArtistByte); + } + + private void PB_DotArtist_MouseClick(object sender, MouseEventArgs e) + { + setFlagsFromClickPoint(e.X, e.Y); + setPictureBoxFromFlags(DotArtistByte); + } } } diff --git a/PKHeX/Saves/SAV4.cs b/PKHeX/Saves/SAV4.cs index 5cfed4b3a..89e649b32 100644 --- a/PKHeX/Saves/SAV4.cs +++ b/PKHeX/Saves/SAV4.cs @@ -1154,5 +1154,35 @@ public int PoketchApps Data[ofs - 1] = 0; // current used, force set for first App. } } + public byte[] PoketchDotArtist + { + get + { + byte[] ret = new byte[120]; // 2bit*24px*20px + int ofs = 0; + switch (Version) + { + case GameVersion.DP: ofs = 0x1176; break; + default: return ret; + } + ofs += GBO; + for (int i = 0; i < 120; i++) + ret[i] = Data[ofs + i]; + return ret; + } + set + { + int ofs = 0; + switch (Version) + { + case GameVersion.DP: ofs = 0x1176; break; + default: return; + } + ofs += GBO; + for(int i = 0; i < 120; i++) + Data[ofs + i] = value[i]; + Data[ofs - 0x2A] |= 0x04; // 0x114C "Touch!" + } + } } }