From 4f489a720fa0346d88cea60b3cbf6f266ba9019b Mon Sep 17 00:00:00 2001 From: Kurt Date: Tue, 9 Jan 2018 23:30:44 -0800 Subject: [PATCH] Refactoring move logic back to cgearbackground, initialize the bg regardless of psk/cgb input format cache background data to return psk (potentially unintended side effects if importing bw psk to b2w2, will have to fix cgb->psk first then undo this tempfix) #1699 --- .../Save Editors/Gen5/CGearBackground.cs | 40 +++++++++++-------- .../Save Editors/Gen5/SAV_CGearSkin.cs | 29 +++++--------- PKHeX.WinForms/Util/ImageUtil.cs | 12 ++++++ 3 files changed, 45 insertions(+), 36 deletions(-) diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen5/CGearBackground.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen5/CGearBackground.cs index 0e1f26aa8..4945d790e 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen5/CGearBackground.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen5/CGearBackground.cs @@ -3,9 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; -using System.IO; using System.Linq; -using System.Runtime.InteropServices; namespace PKHeX.WinForms { @@ -46,6 +44,12 @@ namespace PKHeX.WinForms if (data.Length != SIZE_CGB) return; + // decode for easy handling + if (!IsCGB(data)) + _psk = data = PSKtoCGB(data); + else + _cgb = data; + byte[] Region1 = data.Take(0x1FE0).ToArray(); byte[] ColorData = data.Skip(0x1FE0).Take(0x20).ToArray(); byte[] Region2 = data.Skip(0x2000).Take(0x600).ToArray(); @@ -67,6 +71,12 @@ namespace PKHeX.WinForms Map = new TileMap(Region2); } + private byte[] _cgb; + private byte[] _psk; + + public byte[] GetCGB() => _cgb ?? Write(); + public byte[] GetPSK(bool B2W2) => _psk ?? CGBtoPSK(Write(), B2W2); + public byte[] Write() { byte[] data = new byte[SIZE_CGB]; @@ -100,11 +110,12 @@ namespace PKHeX.WinForms { int index = BitConverter.ToUInt16(cgb, i); int val = IndexToVal(index, shiftVal); - BitConverter.GetBytes((ushort)val).CopyTo(psk, i); + psk[i] = (byte)val; + psk[i + 1] = (byte)(val >> 8); } return psk; } - public static byte[] PSKtoCGB(byte[] psk, bool B2W2) + public static byte[] PSKtoCGB(byte[] psk) { byte[] cgb = (byte[])psk.Clone(); for (int i = 0x2000; i < 0x2600; i += 2) @@ -144,11 +155,7 @@ namespace PKHeX.WinForms throw new ArgumentException($"Invalid image height. Expected {Height} pixels high."); // get raw bytes of image - BitmapData bData = img.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); - byte[] data = new byte[bData.Stride * bData.Height]; - Marshal.Copy(bData.Scan0, data, 0, data.Length); - img.UnlockBits(bData); - + byte[] data = ImageUtil.GetPixelData(img); const int bpp = 4; Debug.Assert(data.Length == Width * Height * bpp); @@ -207,6 +214,8 @@ namespace PKHeX.WinForms Map = tm; ColorPalette = Palette; Tiles = tilelist.ToArray(); + _psk = null; + _cgb = null; } private sealed class Tile : IDisposable @@ -310,16 +319,13 @@ namespace PKHeX.WinForms } internal byte[] Write() { - using (MemoryStream ms = new MemoryStream()) - using (BinaryWriter bw = new BinaryWriter(ms)) + byte[] data = new byte[TileChoices.Length * 2]; + for (int i = 0; i < data.Length; i += 2) { - for (int i = 0; i < TileChoices.Length; i++) - { - bw.Write((byte)TileChoices[i]); - bw.Write((byte)Rotations[i]); - } - return ms.ToArray(); + data[i] = (byte)TileChoices[i/2]; + data[i+1] = (byte)Rotations[i/2]; } + return data; } } diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_CGearSkin.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_CGearSkin.cs index f76c60cd4..1d34e8e39 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_CGearSkin.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_CGearSkin.cs @@ -17,16 +17,10 @@ namespace PKHeX.WinForms SAV = (SAV5)(Origin = sav).Clone(); InitializeComponent(); - SAV = (Origin = sav).Clone() as SAV5; - bool cgearPresent = SAV.Data[SAV.CGearInfoOffset + 0x26] == 1; byte[] data = new byte[CGearBackground.SIZE_CGB]; if (cgearPresent) - { Array.Copy(SAV.Data, SAV.CGearDataOffset, data, 0, CGearBackground.SIZE_CGB); - if (!CGearBackground.IsCGB(data)) - data = CGearBackground.PSKtoCGB(data, SAV.B2W2); - } bg = new CGearBackground(data); PB_Background.Image = bg.GetImage(); @@ -82,23 +76,24 @@ namespace PKHeX.WinForms if (ofd.ShowDialog() != DialogResult.OK) return; - var len = new FileInfo(ofd.FileName).Length; + var path = ofd.FileName; + var len = new FileInfo(path).Length; if (len != CGearBackground.SIZE_CGB) { WinFormsUtil.Error($"Incorrect size, got {len} bytes, expected {CGearBackground.SIZE_CGB} bytes."); return; } - byte[] data = File.ReadAllBytes(ofd.FileName); - if (!CGearBackground.IsCGB(data)) - { - bool B2W2 = data[0x2000] != 0x00; - data = CGearBackground.PSKtoCGB(data, B2W2); - } + byte[] data = File.ReadAllBytes(path); + LoadBackground(data); + } + private void LoadBackground(byte[] data) + { bg = new CGearBackground(data); PB_Background.Image = bg.GetImage(); } + private void B_ExportCGB_Click(object sender, EventArgs e) { SaveFileDialog sfd = new SaveFileDialog @@ -109,19 +104,15 @@ namespace PKHeX.WinForms if (sfd.ShowDialog() != DialogResult.OK) return; - byte[] data = bg.Write(); + byte[] data = bg.GetCGB(); File.WriteAllBytes(sfd.FileName, data); } private void B_Save_Click(object sender, EventArgs e) { - byte[] bgdata = bg.Write(); + byte[] bgdata = bg.GetPSK(SAV.B2W2); if (bgdata.SequenceEqual(new byte[CGearBackground.SIZE_CGB])) return; - // Data present - - bgdata = CGearBackground.CGBtoPSK(bgdata, SAV.B2W2); - byte[] dlcfooter = { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x27, 0x00, 0x00, 0x27, 0x35, 0x05, 0x31, 0x00, 0x00 }; bgdata.CopyTo(SAV.Data, SAV.CGearDataOffset); diff --git a/PKHeX.WinForms/Util/ImageUtil.cs b/PKHeX.WinForms/Util/ImageUtil.cs index 9229186ac..8a8605a75 100644 --- a/PKHeX.WinForms/Util/ImageUtil.cs +++ b/PKHeX.WinForms/Util/ImageUtil.cs @@ -78,6 +78,18 @@ namespace PKHeX.WinForms ptr = bmpData.Scan0; data = new byte[bmp.Width * bmp.Height * 4]; } + public static Bitmap GetBitmap(byte[] data, int width, int height, int stride = 4, PixelFormat format = PixelFormat.Format32bppArgb) + { + return new Bitmap(width, height, stride, format, Marshal.UnsafeAddrOfPinnedArrayElement(data, 0)); + } + public static byte[] GetPixelData(Bitmap bitmap) + { + var argbData = new byte[bitmap.Width * bitmap.Height * 4]; + var bd = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat); + Marshal.Copy(bd.Scan0, argbData, 0, bitmap.Width * bitmap.Height * 4); + bitmap.UnlockBits(bd); + return argbData; + } private static void SetAllTransparencyTo(byte[] data, double trans) { for (int i = 0; i < data.Length; i += 4)