DS-Pokemon-Rom-Editor/DS_Map/Editors/PokemonSpriteEditor.cs
2025-07-29 11:23:52 +02:00

1018 lines
42 KiB
C#

using DSPRE.Editors.Utils;
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using static DSPRE.RomInfo;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ScrollBar;
namespace DSPRE.Editors
{
public struct FileEntry
{
public int Ofs;
public int Size;
}
public partial class PokemonSpriteEditor : Form
{
private readonly string[] pokenames;
private readonly int[] formPalettes = new int[]
{
158, 158, 158, 158,
160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
162, 162, 162, 162,
164, 164, 164,
166, 166, 166,
168, 168, 168, 168,
170, 170, 170, 170,
172, 172, 172, 172,
174, 174, 174, 174, 174, 174, 174, 174,
174, 174, 174, 174, 174, 174, 174, 174,
174, 174, 174, 174, 174, 174, 174, 174,
174, 174, 174, 174, 174, 174, 174, 174,
174, 174, 174, 174, 174, 174, 174, 174,
176, 176,
178, 178, 178, 178,
180, 180, 180, 180, 180, 180, 180, 180,
180, 180, 180, 180, 180, 180, 180, 180,
182, 182, 182, 182,
184, 184, 184,
186, 186
};
private readonly int[] shinyPalettes = new int[]
{
159, 159, 159, 159,
161, 161, 161, 161, 161, 161, 161, 161, 161, 161,
161, 161, 161, 161, 161, 161, 161, 161, 161, 161,
161, 161, 161, 161, 161, 161, 161, 161, 161, 161,
163, 163, 163, 163,
165, 165, 165,
167, 167, 167,
169, 169, 169, 169,
171, 171, 171, 171,
173, 173, 173, 173,
175, 175, 175, 175, 175, 175, 175, 175,
175, 175, 175, 175, 175, 175, 175, 175,
175, 175, 175, 175, 175, 175, 175, 175,
175, 175, 175, 175, 175, 175, 175, 175,
175, 175, 175, 175, 175, 175, 175, 175,
177, 177,
179, 179, 179, 179,
181, 181, 181, 181, 181, 181, 181, 181,
181, 181, 181, 181, 181, 181, 181, 181,
183, 183, 183, 183,
185, 185, 185,
187, 187
};
private readonly int[] validPalettesHGSS = new int[]
{
158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
178, 179, 180, 181, 182, 183, 184, 185, 186, 187,
188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
208, 209, 210, 211, 212, 213, 214, 215, 216, 217,
218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
238, 239, 240, 241, 242, 243, 244, 245, 246, 247,
248, 249, 250, 251, 252, 253, 254, 255, 258, 260
};
private readonly int[] validPalettesPt = new int[]
{
154, 155, 156, 157, 158, 159, 160, 161, 162, 163,
164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
204, 205, 206, 207, 208, 209, 210, 211, 212, 213,
214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
224, 225, 226, 227, 228, 229, 230, 231, 232, 233,
234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
244, 245, 246, 247, 250, 252
};
private readonly int[] validPalettesDP = new int[]
{
134, 135, 136, 137, 138, 139, 140, 141, 142, 145,
146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
156, 157, 158, 159, 160, 161, 162, 163, 164, 165,
166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
176, 177, 178, 179, 180, 181, 182, 183, 184, 185,
186, 187, 188, 189, 190, 191, 192, 193, 194, 195,
196, 197, 198, 199, 200, 201, 202, 203, 204, 205,
206, 207, 210, 212
};
private readonly string[] otherPokenames = new string[]
{
"Deoxys - Base", "Deoxys - Attack", "Deoxys - Defence", "Deoxys - Speed",
"Unown - A", "Unown - B", "Unown - C", "Unown - D", "Unown - E", "Unown - F",
"Unown - G", "Unown - H", "Unown - I", "Unown - J", "Unown - K", "Unown - L",
"Unown - M", "Unown - N", "Unown - O", "Unown - P", "Unown - Q", "Unown - R",
"Unown - S", "Unown - T", "Unown - U", "Unown - V", "Unown - W", "Unown - X",
"Unown - Y", "Unown - Z", "Unown - !", "Unown - ?",
"Castform - Base", "Castform - Sunny", "Castform - Rainy", "Castform - Snow",
"Burmy - Plant", "Burmy - Sandy", "Burmy - Trash",
"Wormadam - Plant", "Wormadam - Sandy", "Wormadam - Trash",
"Shellos", "Shellos",
"Gastrodon", "Gastrodon",
"Cherrim", "Cherrim",
"Arceus - Type 1", "Arceus - Type 2", "Arceus - Type 3", "Arceus - Type 4",
"Arceus - Type 5", "Arceus - Type 6", "Arceus - Type 7", "Arceus - Type 8",
"Arceus - Type 9", "Arceus - Type 10", "Arceus - Type 11", "Arceus - Type 12",
"Arceus - Type 13", "Arceus - Type 14", "Arceus - Type 15", "Arceus - Type 16",
"Egg", "Egg",
"Shaymin", "Shaymin", "Shaymin", "Shaymin",
"Rotom", "Rotom", "Rotom", "Rotom", "Rotom", "Rotom", "Rotom", "Rotom",
"Rotom", "Rotom", "Rotom", "Rotom", "Rotom", "Rotom", "Rotom", "Rotom",
"Giratina", "Giratina", "Giratina", "Giratina",
"Deoxys", "Deoxys",
"Unown", "Unown",
"Castform", "Castform", "Castform", "Castform", "Castform", "Castform", "Castform", "Castform",
"Burmy", "Burmy", "Burmy", "Burmy", "Burmy", "Burmy",
"Wormadam", "Wormadam", "Wormadam", "Wormadam", "Wormadam", "Wormadam",
"Shellos", "Shellos", "Shellos", "Shellos",
"Gastrodon", "Gastrodon", "Gastrodon", "Gastrodon",
"Cherrim", "Cherrim", "Cherrim", "Cherrim",
"Arceus", "Arceus", "Arceus", "Arceus", "Arceus", "Arceus", "Arceus", "Arceus",
"Arceus", "Arceus", "Arceus", "Arceus", "Arceus", "Arceus", "Arceus", "Arceus",
"Arceus", "Arceus", "Arceus", "Arceus", "Arceus", "Arceus", "Arceus", "Arceus",
"Arceus", "Arceus", "Arceus", "Arceus", "Arceus", "Arceus", "Arceus", "Arceus",
"Arceus", "Arceus", "Arceus", "Arceus", "Arceus", "Arceus", "Arceus", "Arceus",
"Egg", "Egg",
"Shaymin", "Shaymin", "Shaymin", "Shaymin",
"Rotom", "Rotom", "Rotom", "Rotom", "Rotom", "Rotom", "Rotom", "Rotom",
"Rotom", "Rotom", "Rotom", "Rotom", "Rotom", "Rotom", "Rotom", "Rotom",
"Giratina", "Giratina", "Giratina", "Giratina",
"Substitute", "Substitute", "Substitute",
"Shadows", "Shadows"
};
private static string[] names = { "Female backsprite", "Male backsprite", "Female frontsprite", "Male frontsprite", "Shiny" };
private bool loadingOther = false;
private PokemonEditor _parent;
private static bool dirty = false;
private static readonly string formName = "Sprite Editor";
private NarcReader nr;
private PictureBox[,] Display;
private bool[] used;
private Rectangle rect;
private IndexedBitmapHandler Handler;
private SpriteSet CurrentSprites;
public PokemonSpriteEditor(Control parent, PokemonEditor pokeEditor)
{
this._parent = pokeEditor;
InitializeComponent();
SetupPictureBoxes();
int[] source = RomInfo.gameFamily == GameFamilies.Plat ? validPalettesPt : RomInfo.gameFamily == GameFamilies.DP ? validPalettesDP : validPalettesHGSS;
foreach (var item in source)
{
BasePalette.Items.Add(item);
ShinyPalette.Items.Add(item);
}
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.Size = parent.Size;
this.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom;
this.pokenames = RomInfo.GetPokemonNames();
Helpers.DisableHandlers();
LoadSprites();
Helpers.EnableHandlers();
}
void IndexBox_SelectedIndexChanged(object sender, EventArgs e)
{
CurrentSprites = new SpriteSet();
if (!this.loadingOther)
{
int num = (IndexBox.Items.IndexOf(IndexBox.Text) * 6);
for (int i = 0; i < 4; i++)
{
if (nr.fe[num + i].Size == 6448)
{
nr.OpenEntry(num + i);
CurrentSprites.Sprites[i] = MakeImage(nr.fs);
nr.Close();
}
}
if (nr.fe[num + 4].Size == 72)
{
nr.OpenEntry(num + 4);
CurrentSprites.Normal = SetPal(nr.fs);
nr.Close();
}
if (nr.fe[num + 5].Size == 72)
{
nr.OpenEntry(num + 5);
CurrentSprites.Shiny = SetPal(nr.fs);
nr.Close();
}
}
else
{
int num = (IndexBox.Items.IndexOf(IndexBox.Text) * 2);
for (int i = 0; i < 2; i++)
{
if (nr.fe[num + i].Size == 6448)
{
nr.OpenEntry(num + i);
CurrentSprites.Sprites[i * 2 + 1] = MakeImage(nr.fs);
nr.Close();
}
}
if (nr.fe[(int)BasePalette.SelectedItem].Size == 72)
{
nr.OpenEntry((int)BasePalette.SelectedItem);
CurrentSprites.Normal = SetPal(nr.fs);
nr.Close();
}
if (nr.fe[(int)ShinyPalette.SelectedItem].Size == 72)
{
nr.OpenEntry((int)ShinyPalette.SelectedItem);
CurrentSprites.Shiny = SetPal(nr.fs);
nr.Close();
}
}
LoadImages();
OpenPngs.Enabled = true;
}
void BasePalette_SelectedIndexChanged(object sender, EventArgs e)
{
if (Helpers.HandlersDisabled) return;
if (nr.fe[(int)BasePalette.SelectedItem].Size == 72)
{
nr.OpenEntry((int)BasePalette.SelectedItem);
CurrentSprites.Normal = SetPal(nr.fs);
nr.Close();
}
LoadImages();
}
void ShinyPalette_SelectedIndexChanged(object sender, EventArgs e)
{
if (Helpers.HandlersDisabled) return;
if (nr.fe[(int)ShinyPalette.SelectedItem].Size == 72)
{
nr.OpenEntry((int)ShinyPalette.SelectedItem);
CurrentSprites.Shiny = SetPal(nr.fs);
nr.Close();
}
LoadImages();
}
void SetupPictureBoxes()
{
Display = new PictureBox[2, 4];
femaleBackNormalPic.Name = "0";
Display[0, 0] = femaleBackNormalPic;
maleBackNormalPic.Name = "1";
Display[1, 0] = maleBackNormalPic;
femaleFrontNormalPic.Name = "2";
Display[0, 1] = femaleFrontNormalPic;
maleFrontNormalPic.Name = "3";
Display[1, 1] = maleFrontNormalPic;
femaleBackShinyPic.Name = "4";
Display[0, 2] = femaleBackShinyPic;
maleBackShinyPic.Name = "5";
Display[1, 2] = maleBackShinyPic;
femaleFrontShinyPic.Name = "6";
Display[0, 3] = femaleFrontShinyPic;
maleFrontShinyPic.Name = "7";
Display[1, 3] = maleFrontShinyPic;
}
void LoadImages()
{
for (int i = 0; i < Display.GetLength(0); i++)
{
for (int j = 0; j < Display.GetLength(1); j++)
{
Display[i, j].Image = null;
}
}
if (CurrentSprites.Normal == null)
return;
if (CurrentSprites.Shiny == null)
CurrentSprites.Shiny = CurrentSprites.Normal;
Bitmap image = new Bitmap(160, 80, PixelFormat.Format8bppIndexed);
for (int i = 0; i < 4; i++)
{
if (CurrentSprites.Sprites[i] != null)
{
CurrentSprites.Sprites[i].Palette = CurrentSprites.Shiny;
Display[(i % 2), ((i / 2) + 2)].Image = new Bitmap(CurrentSprites.Sprites[i], 320, 160);
CurrentSprites.Sprites[i].Palette = CurrentSprites.Normal;
Display[(i % 2), (i / 2)].Image = new Bitmap(CurrentSprites.Sprites[i], 320, 160);
}
}
}
Bitmap CheckSize(Bitmap image, string filename, string name, int spritenumber = 2)
{
DialogResult yesno;
IndexedBitmapHandler Handler = new IndexedBitmapHandler();
if (image.PixelFormat != PixelFormat.Format8bppIndexed)
{
yesno = MessageBox.Show(filename + " is not 8bpp Indexed! Attempt conversion?", "Incompatible image format", MessageBoxButtons.YesNo);
if (yesno != DialogResult.Yes)
return null;
image = Handler.Convert(image, PixelFormat.Format8bppIndexed);
if (image == null)
return null;
if ((image.PixelFormat != PixelFormat.Format8bppIndexed) || (image.Palette == null))
{
MessageBox.Show("Conversion failed.", "Failed");
return null;
}
}
if (((image.Height != 64) && (image.Height != 80)) || ((image.Width != 64) && (image.Width != 80) && (image.Width != 160)))
{
int imagescale = 0;
if ((image.Width / 64 == image.Height / 64) && (image.Width % 64 == 0) && (image.Height % 64 == 0))
imagescale = image.Width / 64;
if ((image.Width / 80 == image.Height / 80) && (image.Width % 80 == 0) && (image.Height % 80 == 0))
imagescale = image.Width / 80;
if ((image.Width / 160 == image.Height / 80) && (image.Width % 160 == 0) && (image.Height % 80 == 0))
imagescale = image.Width / 160;
if (imagescale > 1)
{
yesno = MessageBox.Show(filename + " is too large. Attempt to shrink?", "Too large", MessageBoxButtons.YesNo);
if (yesno == DialogResult.Yes)
image = Handler.ShrinkImage(image, imagescale, imagescale);
else
imagescale = 0;
}
if (imagescale == 0)
{
yesno = MessageBox.Show(filename + " size not recognized. Use Canvas Splitter?", "Unrecognized size", MessageBoxButtons.YesNo);
if (yesno != DialogResult.Yes)
return null;
SizeChooser Chooser = new SizeChooser();
DialogResult success = Chooser.ShowDialog();
int sizeChoice = Chooser.choice;
Chooser.Dispose();
if (success == DialogResult.Cancel)
return null;
int a = 80;
int b = 80;
if (sizeChoice == 0)
{
a = 64;
b = 64;
}
if (sizeChoice == 2)
a = 160;
if ((image.Width < a) || (image.Height < b))
{
MessageBox.Show("Image is too small");
return null;
}
Bitmap[] tiles = Handler.Split(image, a, b);
SpriteCropper Cropper = new SpriteCropper(tiles, name);
success = Cropper.ShowDialog();
if (success == DialogResult.Cancel)
return null;
image = Cropper.Chosen;
Cropper.Dispose();
}
}
byte check = Handler.PaletteSize(image);
if (check > 16)
{
yesno = MessageBox.Show("Image's palette contains more than sixteen colors. Attempt to shrink?", "Improper palette size", MessageBoxButtons.YesNo);
if (yesno == DialogResult.Yes)
{
image = Handler.ShrinkPalette(image);
check = Handler.PaletteSize(image);
if (check > 16)
MessageBox.Show("Palette still too large. Image will not save correctly.", "Failed");
}
}
if (image.Height == 64 && image.Width == 64)
image = Handler.Resize(image, 8, 8, 8, 8);
if (image.Height == 80 && image.Width == 80)
{
if ((spritenumber < 2) && (RomInfo.gameFamily == RomInfo.GameFamilies.DP))
image = Handler.Resize(image, 0, 0, 0, 80);
else
image = Handler.Concat(image, image);
}
if (image.Height == 80 && image.Width == 160)
return image;
return null;
}
Bitmap MakeImage(FileStream fs)
{
fs.Seek(48L, SeekOrigin.Current);
BinaryReader binaryReader = new BinaryReader(fs);
ushort[] array = new ushort[3200];
for (int i = 0; i < 3200; i++)
{
array[i] = binaryReader.ReadUInt16();
}
uint num = array[0];
if (RomInfo.gameFamily != RomInfo.GameFamilies.DP)
{
for (int j = 0; j < 3200; j++)
{
unchecked
{
ushort[] array2;
IntPtr value;
(array2 = array)[(int)(value = (IntPtr)j)] = (ushort)(array2[(int)value] ^ (ushort)(num & 0xFFFF));
num *= 1103515245;
num += 24691;
}
}
}
else
{
num = array[3199];
for (int num2 = 3199; num2 >= 0; num2--)
{
unchecked
{
ushort[] array2;
IntPtr value;
(array2 = array)[(int)(value = (IntPtr)num2)] = (ushort)(array2[(int)value] ^ (ushort)(num & 0xFFFF));
num *= 1103515245;
num += 24691;
}
}
}
Bitmap r_bitmap = new Bitmap(160, 80, PixelFormat.Format8bppIndexed);
rect = new Rectangle(0, 0, 160, 80);
byte[] array3 = new byte[12800];
for (int k = 0; k < 3200; k++)
{
array3[k * 4] = (byte)(array[k] & 0xF);
array3[k * 4 + 1] = (byte)((array[k] >> 4) & 0xF);
array3[k * 4 + 2] = (byte)((array[k] >> 8) & 0xF);
array3[k * 4 + 3] = (byte)((array[k] >> 12) & 0xF);
}
BitmapData bitmapData = r_bitmap.LockBits(rect, ImageLockMode.WriteOnly, r_bitmap.PixelFormat);
IntPtr scan = bitmapData.Scan0;
Marshal.Copy(array3, 0, scan, 12800);
r_bitmap.UnlockBits(bitmapData);
Bitmap bitmap = new Bitmap(1, 1, PixelFormat.Format4bppIndexed);
ColorPalette palette = bitmap.Palette;
for (int l = 0; l < 16; l++)
{
palette.Entries[l] = Color.FromArgb(l << 4, l << 4, l << 4);
}
r_bitmap.Palette = palette;
if (r_bitmap == null)
{
MessageBox.Show("MakeImage Failed");
return null;
}
return r_bitmap;
}
ColorPalette SetPal(FileStream fs)
{
fs.Seek(40L, SeekOrigin.Current);
ushort[] array = new ushort[16];
BinaryReader binaryReader = new BinaryReader(fs);
for (int i = 0; i < 16; i++)
{
array[i] = binaryReader.ReadUInt16();
}
Bitmap bitmap = new Bitmap(1, 1, PixelFormat.Format4bppIndexed);
ColorPalette palette = bitmap.Palette;
for (int j = 0; j < 16; j++)
{
palette.Entries[j] = Color.FromArgb((array[j] & 0x1F) << 3, ((array[j] >> 5) & 0x1F) << 3, ((array[j] >> 10) & 0x1F) << 3);
}
return palette;
}
void LoadSprites()
{
OpenPngs.Enabled = false;
IndexBox.Items.Clear();
if (!this.loadingOther)
{
nr = new NarcReader(RomInfo.gameDirs[DirNames.pokemonBattleSprites].packedDir);
for (int i = 0; i < nr.Entrys; i += 6)
{
IndexBox.Items.Add(this.pokenames[i / 6] + " (" + nr.fe[i].Size + ")");
}
IndexBox.SelectedIndex = 1;
}
else
{
nr = new NarcReader(RomInfo.gameDirs[DirNames.otherPokemonBattleSprites].packedDir);
for (int i = 0; i < nr.Entrys; i += 2)
{
IndexBox.Items.Add(this.otherPokenames[i / 2] + " (" + nr.fe[i].Size + ")");
}
IndexBox.SelectedIndex = 0;
}
}
void Picturebox_Click(object sender, EventArgs e)
{
if (OpenPngs.Enabled == false)
return;
OpenPngs.Enabled = false;
PictureBox source = sender as PictureBox;
int index = Convert.ToInt32(source.Name);
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Title = "Choose an image";
openFileDialog.CheckPathExists = true;
openFileDialog.Filter = "Supported fomats: *.bmp, *.gif, *.png | *.bmp; *.gif; *.png";
openFileDialog.ShowHelp = true;
Bitmap image;
if (openFileDialog.ShowDialog() != DialogResult.OK)
{
OpenPngs.Enabled = true;
return;
}
image = new Bitmap(openFileDialog.FileName);
IndexedBitmapHandler Handler = new IndexedBitmapHandler();
if (index > 3)
{
image = CheckSize(image, openFileDialog.FileName, "Shiny");
if (image == null)
{
OpenPngs.Enabled = true;
return;
}
ColorPalette temp = Handler.AlternatePalette(CurrentSprites.Sprites[index % 4], image);
if (temp != null)
CurrentSprites.Shiny = temp;
else
CurrentSprites.Shiny = image.Palette;
}
else
{
image = CheckSize(image, openFileDialog.FileName, names[index], index);
if (image == null)
{
OpenPngs.Enabled = true;
return;
}
bool match = Handler.PaletteEquals(CurrentSprites.Normal, image);
if (!match)
{
DialogResult yesno = MessageBox.Show("Image's palette does not match the current palette. Use PaletteMatch?", "Palette mismatch", MessageBoxButtons.YesNo);
if (yesno == DialogResult.Yes)
{
image = Handler.PaletteMatch(CurrentSprites.Normal, image, used);
used = Handler.IsUsed(image, used);
}
else
used = Handler.IsUsed(image);
CurrentSprites.Normal = image.Palette;
}
CurrentSprites.Sprites[index] = image;
}
OpenPngs.Enabled = true;
LoadImages();
}
void OpenPng_Click(object sender, EventArgs e)
{
if (OpenPngs.Enabled == false)
return;
OpenPngs.Enabled = false;
LoadingForm Open = new LoadingForm();
var result = Open.ShowDialog();
if (result == DialogResult.Cancel)
{
OpenPngs.Enabled = true;
return;
}
string[] filenames = Open.files;
bool Autofill = Open.result;
int shinymatch = Open.shinymatch;
bool paletteMatch = Open.paletteMatch;
Open.Dispose();
SpriteSet temp = new SpriteSet();
Bitmap image;
for (int i = 0; i < 4; i++)
{
if (filenames[i] == "")
continue;
image = new Bitmap(filenames[i]);
temp.Sprites[i] = CheckSize(image, filenames[i], names[i], i);
}
bool[] tempUsed = null;
if (paletteMatch)
{
temp.Normal = CurrentSprites.Normal;
tempUsed = used;
}
for (int i = 0; i < 4; i++)
{
if (temp.Sprites[i] == null)
continue;
if (temp.Normal == null)
{
temp.Normal = temp.Sprites[i].Palette;
tempUsed = Handler.IsUsed(temp.Sprites[i]);
}
else
{
bool match = Handler.PaletteEquals(temp.Normal, temp.Sprites[i]);
if (!match)
{
temp.Sprites[i] = Handler.PaletteMatch(temp.Normal, temp.Sprites[i], tempUsed);
temp.Normal = temp.Sprites[i].Palette;
}
tempUsed = Handler.IsUsed(temp.Sprites[i], tempUsed);
}
}
used = tempUsed;
if (filenames[4] != "")
{
image = new Bitmap(filenames[4]);
image = CheckSize(image, filenames[4], names[4], 4);
if ((shinymatch < 4) && (temp.Sprites[shinymatch] != null))
temp.Shiny = Handler.AlternatePalette(temp.Sprites[shinymatch], image);
else
temp.Shiny = image.Palette;
}
if (Autofill)
{
if (temp.Sprites[0] == null)
temp.Sprites[0] = temp.Sprites[1];
if (temp.Sprites[1] == null)
temp.Sprites[1] = temp.Sprites[0];
if (temp.Sprites[2] == null)
temp.Sprites[2] = temp.Sprites[3];
if (temp.Sprites[3] == null)
temp.Sprites[3] = temp.Sprites[2];
if (filenames[4] == "")
temp.Shiny = temp.Normal;
}
for (int i = 0; i < 4; i++)
{
if (temp.Sprites[i] != null)
CurrentSprites.Sprites[i] = temp.Sprites[i];
}
if (temp.Normal != null)
CurrentSprites.Normal = temp.Normal;
if (temp.Shiny != null)
CurrentSprites.Shiny = temp.Shiny;
LoadImages();
OpenPngs.Enabled = true;
}
void SaveChanges_Click(object sender, EventArgs e)
{
if (OpenPngs.Enabled == false)
return;
int num = (IndexBox.Items.IndexOf(IndexBox.Text) * 6);
for (int i = 0; i < 4; i++)
{
if (nr.fe[num + i].Size == 6448)
{
nr.OpenEntry(num + i);
SaveBin(nr.fs, CurrentSprites.Sprites[i]);
nr.Close();
}
}
if (nr.fe[num + 4].Size == 72)
{
nr.OpenEntry(num + 4);
SavePal(nr.fs, CurrentSprites.Normal);
nr.Close();
}
if (nr.fe[num + 5].Size == 72)
{
nr.OpenEntry(num + 5);
SavePal(nr.fs, CurrentSprites.Shiny);
nr.Close();
}
}
// Credit to loadingNOW and SCV for the original PokeDsPic and PokeDsPicPlatinum, without which this would never have happened.
// In addition to G4SpriteEditor
protected void btnSaveAs_Click(object sender, EventArgs e)
{
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Title = "Save Image Set";
saveFileDialog.CheckPathExists = true;
saveFileDialog.Filter = "*.png|*.png";
saveFileDialog.ShowHelp = true;
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
string fileName = saveFileDialog.FileName;
fileName = fileName.Replace(".png", "");
bool ShinySaved = false;
if (CurrentSprites.Sprites[2] != null)
{
if (CurrentSprites.Shiny != null)
{
CurrentSprites.Sprites[2].Palette = CurrentSprites.Shiny;
SavePNG(CurrentSprites.Sprites[2], (fileName + "Shiny.png"));
ShinySaved = true;
}
CurrentSprites.Sprites[2].Palette = CurrentSprites.Normal;
SavePNG(CurrentSprites.Sprites[2], (fileName + "FFront.png"));
}
if (CurrentSprites.Sprites[3] != null)
{
if ((CurrentSprites.Shiny != null) && (!ShinySaved))
{
CurrentSprites.Sprites[3].Palette = CurrentSprites.Shiny;
SavePNG(CurrentSprites.Sprites[3], (fileName + "Shiny.png"));
ShinySaved = true;
}
CurrentSprites.Sprites[3].Palette = CurrentSprites.Normal;
SavePNG(CurrentSprites.Sprites[3], (fileName + "MFront.png"));
}
if (CurrentSprites.Sprites[0] != null)
{
if ((CurrentSprites.Shiny != null) && (!ShinySaved))
{
CurrentSprites.Sprites[0].Palette = CurrentSprites.Shiny;
SavePNG(CurrentSprites.Sprites[0], (fileName + "Shiny.png"));
ShinySaved = true;
}
CurrentSprites.Sprites[0].Palette = CurrentSprites.Normal;
SavePNG(CurrentSprites.Sprites[0], (fileName + "FBack.png"));
}
if (CurrentSprites.Sprites[1] != null)
{
if ((CurrentSprites.Shiny != null) && (!ShinySaved))
{
CurrentSprites.Sprites[1].Palette = CurrentSprites.Shiny;
SavePNG(CurrentSprites.Sprites[1], (fileName + "Shiny.png"));
}
CurrentSprites.Sprites[1].Palette = CurrentSprites.Normal;
SavePNG(CurrentSprites.Sprites[1], (fileName + "MBack.png"));
}
}
}
void SaveSingle_Click(object sender, EventArgs e)
{
int index = SaveBox.SelectedIndex;
if (CurrentSprites.Sprites[index % 4] == null)
{
MessageBox.Show("Image is empty.");
return;
}
string selected = SaveBox.Text;
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Title = "Save As PNG";
saveFileDialog.OverwritePrompt = true;
saveFileDialog.CheckPathExists = true;
saveFileDialog.Filter = "*.png|*.png";
saveFileDialog.ShowHelp = true;
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
string fileName = saveFileDialog.FileName;
Bitmap image = CurrentSprites.Sprites[index % 4];
if (index > 3)
image.Palette = CurrentSprites.Shiny;
else
image.Palette = CurrentSprites.Normal;
SavePNG(image, fileName);
}
}
void btnOpenOther_Click(object sender, EventArgs e)
{
Helpers.DisableHandlers();
this.loadingOther = true;
BasePalette.Enabled = true;
ShinyPalette.Enabled = true;
BasePalette.Visible = true;
ShinyPalette.Visible = true;
BasePalette.SelectedIndex = 0;
ShinyPalette.SelectedIndex = 0;
LoadSprites();
Helpers.EnableHandlers();
}
void btnLoadSheet_Click(object sender, EventArgs e)
{
if (OpenPngs.Enabled == false)
return;
OpenPngs.Enabled = false;
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Title = "Select a sprite sheet";
openFileDialog.CheckPathExists = true;
openFileDialog.Filter = "Supported fomats: *.bmp, *.gif, *.png | *.bmp; *.gif; *.png";
openFileDialog.ShowHelp = true;
if (openFileDialog.ShowDialog() != DialogResult.OK)
{
OpenPngs.Enabled = true;
return;
}
Bitmap image = new Bitmap(openFileDialog.FileName);
if ((image.Width != 256) || (image.Height != 64))
{
MessageBox.Show("The sprite sheet should be 256x64.");
return;
}
IndexedBitmapHandler Handler = new IndexedBitmapHandler();
image = Handler.Convert(image, PixelFormat.Format8bppIndexed);
image.Palette = StandardizeColors(image);
Bitmap[] tiles = Handler.Split(image, 64, 64);
SpriteSet sprites = new SpriteSet();
bool[] used = Handler.IsUsed(tiles[0]);
used = Handler.IsUsed(tiles[2], used);
Bitmap temp = Handler.ShrinkPalette(tiles[0], used);
sprites.Normal = temp.Palette;
temp = Handler.Resize(temp, 8, 8, 8, 8);
temp = Handler.Concat(temp, temp);
sprites.Sprites[2] = temp;
sprites.Sprites[3] = temp;
temp = Handler.ShrinkPalette(tiles[2], used);
temp = Handler.Resize(temp, 8, 8, 8, 8);
if (RomInfo.gameFamily == RomInfo.GameFamilies.DP)
temp = Handler.Resize(temp, 0, 0, 0, 80);
else
temp = Handler.Concat(temp, temp);
sprites.Sprites[0] = temp;
sprites.Sprites[1] = temp;
temp = Handler.ShrinkPalette(tiles[1], used);
temp = Handler.Resize(temp, 8, 8, 8, 8);
temp = Handler.Concat(temp, temp);
sprites.Shiny = Handler.AlternatePalette(sprites.Sprites[2], temp);
CurrentSprites = sprites;
OpenPngs.Enabled = true;
LoadImages();
}
void MakeShiny_Click(object sender, EventArgs e)
{
if (OpenPngs.Enabled == false)
return;
OpenPngs.Enabled = false;
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Title = "Choose the base image";
openFileDialog.CheckPathExists = true;
openFileDialog.Filter = "Supported fomats: *.bmp, *.gif, *.png | *.bmp; *.gif; *.png";
openFileDialog.ShowHelp = true;
if (openFileDialog.ShowDialog() != DialogResult.OK)
{
OpenPngs.Enabled = true;
return;
}
string filename = openFileDialog.FileName;
openFileDialog.Title = "Choose the shiny image";
openFileDialog.CheckPathExists = true;
openFileDialog.Filter = "Supported fomats: *.bmp, *.gif, *.png | *.bmp; *.gif; *.png";
openFileDialog.ShowHelp = true;
if (openFileDialog.ShowDialog() != DialogResult.OK)
{
OpenPngs.Enabled = true;
return;
}
Bitmap parent = new Bitmap(filename);
Bitmap child = new Bitmap(openFileDialog.FileName);
IndexedBitmapHandler Handler = new IndexedBitmapHandler();
ColorPalette temp = Handler.AlternatePalette(parent, child);
if (temp != null)
CurrentSprites.Shiny = temp;
else
MessageBox.Show("Failed!", "Failed");
OpenPngs.Enabled = true;
LoadImages();
}
ColorPalette StandardizeColors(Bitmap image)
{
ColorPalette pal = image.Palette;
bool OffColor = false;
for (int i = 0; i < pal.Entries.Length; i++)
{
if ((pal.Entries[i].R % 8 != 0) || (pal.Entries[i].G % 8 != 0) || (pal.Entries[i].B % 8 != 0))
OffColor = true;
}
if (OffColor)
{
for (int i = 0; i < pal.Entries.Length; i++)
{
byte r = (byte)(pal.Entries[i].R - (pal.Entries[i].R % 8));
byte g = (byte)(pal.Entries[i].G - (pal.Entries[i].G % 8));
byte b = (byte)(pal.Entries[i].B - (pal.Entries[i].B % 8));
pal.Entries[i] = Color.FromArgb(r, g, b);
}
}
return pal;
}
void SavePNG(Bitmap image, string filename)
{
IndexedBitmapHandler Handler = new IndexedBitmapHandler();
byte[] array = Handler.GetArray(image);
Bitmap temp = Handler.MakeImage(image.Width, image.Height, array, image.PixelFormat);
ColorPalette cleaned = Handler.CleanPalette(image);
temp.Palette = cleaned;
temp.Save(filename, ImageFormat.Png);
}
void SaveBin(FileStream fs, Bitmap source)
{
BinaryWriter binaryWriter = new BinaryWriter(fs);
rect = new Rectangle(0, 0, 160, 80);
BitmapData bitmapData = source.LockBits(rect, ImageLockMode.ReadOnly, source.PixelFormat);
IntPtr scan = bitmapData.Scan0;
byte[] array = new byte[12800];
Marshal.Copy(scan, array, 0, 12800);
source.UnlockBits(bitmapData);
ushort[] array2 = new ushort[3200];
for (int i = 0; i < 3200; i++)
{
array2[i] = (ushort)((array[i * 4] & 0xF) | ((array[i * 4 + 1] & 0xF) << 4) | ((array[i * 4 + 2] & 0xF) << 8) | ((array[i * 4 + 3] & 0xF) << 12));
}
uint num = 0u;
if (RomInfo.gameFamily != RomInfo.GameFamilies.DP)
{
for (int j = 0; j < 3200; j++)
{
unchecked
{
ushort[] array3;
IntPtr value;
(array3 = array2)[(int)(value = (IntPtr)j)] = (ushort)(array3[(int)value] ^ (ushort)(num & 0xFFFF));
num *= 1103515245;
num += 24691;
}
}
}
else
{
num = 31315u;
for (int num2 = 3199; num2 >= 0; num2--)
{
num += array2[num2];
}
for (int num3 = 3199; num3 >= 0; num3--)
{
unchecked
{
ushort[] array3;
IntPtr value;
(array3 = array2)[(int)(value = (IntPtr)num3)] = (ushort)(array3[(int)value] ^ (ushort)(num & 0xFFFF));
num *= 1103515245;
num += 24691;
}
}
}
byte[] array4 = new byte[48]
{
82, 71, 67, 78, 255, 254, 0, 1, 48, 25, 0, 0, 16, 0, 1, 0,
82, 65, 72, 67, 32, 25, 0, 0, 10, 0, 20, 0, 3, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 25, 0, 0, 24, 0, 0, 0
};
for (int k = 0; k < 48; k++)
{
binaryWriter.Write(array4[k]);
}
for (int l = 0; l < 3200; l++)
{
binaryWriter.Write(array2[l]);
}
}
void SavePal(FileStream fs, ColorPalette palette)
{
byte[] buffer = new byte[40]
{
82, 76, 67, 78, 255, 254, 0, 1, 72, 0, 0, 0, 16, 0, 1, 0,
84, 84, 76, 80, 56, 0, 0, 0, 4, 0, 10, 0, 0, 0, 0, 0,
32, 0, 0, 0, 16, 0, 0, 0
};
BinaryWriter binaryWriter = new BinaryWriter(fs);
binaryWriter.Write(buffer, 0, 40);
ushort[] array = new ushort[16];
for (int i = 0; i < 16; i++)
{
array[i] = (ushort)(((palette.Entries[i].R >> 3) & 0x1F) | (((palette.Entries[i].G >> 3) & 0x1F) << 5) | (((palette.Entries[i].B >> 3) & 0x1F) << 10));
}
for (int j = 0; j < 16; j++)
{
binaryWriter.Write(array[j]);
}
}
}
}