Wondercard Window refactor

No functional change; more OOP.
This commit is contained in:
Kaphotics
2016-04-21 19:16:55 -07:00
parent 2c233be43f
commit 13ec0e9e89
3 changed files with 175 additions and 137 deletions

View File

@@ -518,9 +518,7 @@ public bool DaycareOccupied2
public byte[] Puffs { get { return Data.Skip(Puff).Take(100).ToArray(); } set { value.CopyTo(Data, Puff); } }
public int PuffCount { get { return BitConverter.ToInt32(Data, Puff + 100); } set { BitConverter.GetBytes(value).CopyTo(Data, Puff + 100); } }
public byte[] getWondercard(int i) { return Data.Skip(WondercardData + i*WC6.Size).Take(WC6.Size).ToArray(); }
public void setWondercard(int i, byte[] data) { data.CopyTo(data, WondercardData + i * WC6.Size); }
public string JPEGTitle => JPEG > -1 ? null : Util.TrimFromZero(Encoding.Unicode.GetString(Data, JPEG, 0x1A));
public byte[] JPEGData => JPEG > -1 || Data[JPEG + 0x54] != 0xFF ? null : Data.Skip(JPEG + 0x54).Take(0xE004).ToArray();
@@ -827,6 +825,60 @@ public PK6[] BattleBoxData
}
}
public bool[] WC6Flags
{
get
{
if (WondercardData < 0 || WondercardFlags < 0)
return null;
bool[] r = new bool[(WondercardData-WondercardFlags)*8];
for (int i = 0; i < r.Length; i++)
r[i] = (Data[WondercardFlags + (i>>3)] >> (i&7) & 0x1) == 1;
return r;
}
set
{
if (WondercardData < 0 || WondercardFlags < 0)
return;
if ((WondercardData - WondercardFlags)*8 != value?.Length)
return;
byte[] data = new byte[value.Length/8];
for (int i = 0; i < value.Length; i++)
if (value[i])
data[i>>3] |= (byte)(1 << (i&7));
data.CopyTo(Data, WondercardFlags);
Edited = true;
}
}
public WC6 getWC6(int index)
{
if (WondercardData < 0)
return null;
if (index < 0 || index > 24)
return null;
return new WC6(Data.Skip(WondercardData + index * WC6.Size).Take(WC6.Size).ToArray());
}
public void setWC6(WC6 wc6, int index)
{
if (WondercardData < 0)
return;
if (index < 0 || index > 24)
return;
wc6.Data.CopyTo(Data, WondercardData + index * WC6.Size);
for (int i = 0; i < 24; i++)
if (BitConverter.ToUInt16(Data, WondercardData + i * WC6.Size) == 0)
for (int j = i + 1; j < 24 - i; j++) // Shift everything down
Array.Copy(Data, WondercardData + j * WC6.Size, Data, WondercardData + (j - 1) * WC6.Size, WC6.Size);
Edited = true;
}
// Writeback Validity
public string checkChunkFF()
{
@@ -854,7 +906,7 @@ public string checkChunkFF()
public string getBlockInfoString()
{
return Blocks.Aggregate("", (current, b) => current +
$"{b.ID.ToString("00")}: {b.Offset.ToString("X5")}-{(b.Offset + b.Length).ToString("X5")}, {b.Length.ToString("X5")}{Environment.NewLine}");
$"{b.ID.ToString("00")}: {b.Offset.ToString("X5")}-{(b.Offset + b.Length).ToString("X5")}, {b.Length.ToString("X5")}{Environment.NewLine}");
}
}
}

View File

@@ -4,15 +4,24 @@
namespace PKHeX
{
public class WC6
public partial class WC6
{
internal const int Size = 0x108;
internal const int SizeFull = 0x310;
internal const uint EonTicketConst = 0x225D73C2;
public byte[] Data;
public readonly byte[] Data;
public WC6(byte[] data = null)
{
Data = data ?? new byte[Size];
if (Data.Length == SizeFull)
{
Data = Data.Skip(SizeFull - Size).ToArray();
DateTime now = DateTime.Now;
Year = (uint)(now.Year - 2000);
Month = (uint)now.Month;
Day = (uint)now.Day;
}
}
// General Card Properties

View File

@@ -2,7 +2,6 @@
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace PKHeX
@@ -38,12 +37,11 @@ public SAV_Wondercard(byte[] wcdata = null)
if (wcdata == null || wcdata.Length != WC6.Size)
return;
Array.Copy(wcdata, wondercard_data, wcdata.Length);
Array.Copy(wcdata, wc6.Data, wcdata.Length);
loadwcdata();
}
private readonly byte[] sav = (byte[])Main.SAV.Data.Clone();
private byte[] wondercard_data = new byte[WC6.Size];
private const uint EonTicketConst = 0x225D73C2;
private readonly SAV6 SAV = new SAV6((byte[])Main.SAV.Data.Clone());
private WC6 wc6 = new WC6();
private readonly PictureBox[] pba;
// Repopulation Functions
@@ -54,54 +52,44 @@ private void setBackground(int index, Image bg)
pba[i].BackgroundImage = index == i ? bg : null;
currentSlot = index;
}
private void removeEmptyWC6s()
{
byte[][] ca = new byte[24][];
for (int i = 0; i < ca.Length; i++)
ca[i] = sav.Skip(Main.SAV.WondercardData + WC6.Size*i).Take(WC6.Size).ToArray();
ca = ca.Where(c => BitConverter.ToUInt16(c, 0) > 0).ToArray();
for (int i = 0; i < ca.Length; i++)
ca[i].CopyTo(sav, Main.SAV.WondercardData + WC6.Size * i);
for (int i = ca.Length; i < 24; i++)
new byte[WC6.Size].CopyTo(sav, Main.SAV.WondercardData + WC6.Size * i);
}
private void populateWClist()
{
removeEmptyWC6s();
for (int i = 0; i < 24; i++)
{
int offset = Main.SAV.WondercardData + i * WC6.Size;
int cardID = BitConverter.ToUInt16(sav, offset);
pba[i].Image = cardID == 0 ? null : getWCPreviewImage(sav.Skip(Main.SAV.WondercardData + WC6.Size * i).Take(WC6.Size).ToArray());
WC6 wc = SAV.getWC6(i);
pba[i].Image = wc.CardID == 0 ? null : wc.Preview;
}
}
private void loadwcdata()
{
if (wc6 == null)
return;
try
{
if ((wondercard_data[0x52] & 2) != 0 && DialogResult.Yes ==
if (wc6.GiftUsed && DialogResult.Yes ==
Util.Prompt(MessageBoxButtons.YesNo,
"Wonder Card is marked as USED and will not be able to be picked up in-game.",
"Do you want to remove the USED flag so that it is UNUSED?"))
wondercard_data[0x52] &= 0xFD; // keep all bits but bit1 (11111101)
wc6.GiftUsed = false;
RTB.Text = getWCDescriptionString(wondercard_data);
PB_Preview.Image = getWCPreviewImage(wondercard_data);
RTB.Text = wc6.Description;
PB_Preview.Image = wc6.Preview;
}
catch (Exception e)
{
Util.Error("Loading of data failed... is this really a Wonder Card?", e.ToString());
wondercard_data = new byte[WC6.Size];
wc6 = new WC6();
RTB.Clear();
}
}
private void populateReceived()
{
LB_Received.Items.Clear();
for (int i = 1; i < 2048; i++)
if ((sav[Main.SAV.WondercardFlags + i / 8]>>i%8 & 0x1) == 1)
bool[] flags = SAV.WC6Flags;
for (int i = 1; i < flags.Length; i++)
if (flags[i])
LB_Received.Items.Add(i.ToString("0000"));
if (LB_Received.Items.Count > 0)
LB_Received.SelectedIndex = 0;
}
@@ -128,17 +116,14 @@ private void B_Import_Click(object sender, EventArgs e)
Util.Error("File is not a Wonder Card:", path);
return;
}
byte[] newwc6 = File.ReadAllBytes(path);
if (newwc6.Length == WC6.SizeFull)
newwc6 = newwc6.Skip(WC6.SizeFull - WC6.Size).ToArray();
Array.Copy(newwc6, wondercard_data, newwc6.Length);
wc6 = new WC6(File.ReadAllBytes(path));
loadwcdata();
}
private void B_Output_Click(object sender, EventArgs e)
{
SaveFileDialog outputwc6 = new SaveFileDialog();
int cardID = BitConverter.ToUInt16(wondercard_data, 0);
string cardname = Encoding.Unicode.GetString(wondercard_data, 0x2, 0x48);
int cardID = wc6.CardID;
string cardname = wc6.CardTitle;
outputwc6.FileName = Util.CleanFileName($"{cardID} - {cardname}.wc6");
outputwc6.Filter = "Wonder Card|*.wc6";
if (outputwc6.ShowDialog() != DialogResult.OK) return;
@@ -148,7 +133,7 @@ private void B_Output_Click(object sender, EventArgs e)
if (File.Exists(path)) // File already exists, save a .bak
File.WriteAllBytes(path + ".bak", File.ReadAllBytes(path));
File.WriteAllBytes(path, wondercard_data);
File.WriteAllBytes(path, wc6.Data);
}
// Wonder Card RW (window<->sav)
@@ -158,13 +143,14 @@ private void clickView(object sender, EventArgs e)
int index = Array.IndexOf(pba, sender);
setBackground(index, Properties.Resources.slotView);
int offset = Main.SAV.WondercardData + index * WC6.Size;
Array.Copy(sav, offset, wondercard_data, 0, WC6.Size);
wc6 = SAV.getWC6(index);
loadwcdata();
}
private void clickSet(object sender, EventArgs e)
{
if (!checkSpecialWonderCard(wondercard_data))
if (wc6 == null)
return;
if (!checkSpecialWonderCard(wc6))
return;
sender = ((sender as ToolStripItem)?.Owner as ContextMenuStrip)?.SourceControl ?? sender as PictureBox;
@@ -176,10 +162,9 @@ private void clickSet(object sender, EventArgs e)
index = lastUnfilled;
setBackground(index, Properties.Resources.slotSet);
int offset = Main.SAV.WondercardData + index * WC6.Size;
Array.Copy(wondercard_data, 0, sav, offset, WC6.Size);
SAV.setWC6(wc6, index);
populateWClist();
setCardID(BitConverter.ToUInt16(wondercard_data, 0));
setCardID(wc6.CardID);
}
private void clickDelete(object sender, EventArgs e)
{
@@ -187,8 +172,7 @@ private void clickDelete(object sender, EventArgs e)
int index = Array.IndexOf(pba, sender);
setBackground(index, Properties.Resources.slotDel);
int offset = Main.SAV.WondercardData + index * WC6.Size;
new byte[WC6.Size].CopyTo(sav, offset);
SAV.setWC6(new WC6(), index);
populateWClist();
}
@@ -202,24 +186,12 @@ private void B_Save_Click(object sender, EventArgs e)
int offset = Main.SAV.WondercardFlags;
// Make sure all of the Received Flags are flipped!
byte[] wcflags = new byte[0x100];
foreach (uint cardnum in from object card in LB_Received.Items
select card.ToString() into cardID
select Util.ToUInt32(cardID))
wcflags[(cardnum / 8) & 0xFF] |= (byte)(1 << (byte)(cardnum & 0x7));
bool[] flags = new bool[(SAV.WondercardData - SAV.WondercardFlags)*8];
foreach (var o in LB_Received.Items)
flags[Util.ToUInt32(o.ToString())] = true;
Array.Copy(wcflags, 0, sav, offset, 0x100);
offset += 0x100;
// Make sure there's no space between wondercards
{
for (int i = 0; i < 24; i++)
if (BitConverter.ToUInt16(sav, offset + i * WC6.Size) == 0)
for (int j = i + 1; j < 24 - i; j++) // Shift everything down
Array.Copy(sav, offset + j * WC6.Size, sav, offset + (j - 1) * WC6.Size, WC6.Size);
}
Array.Copy(sav, Main.SAV.Data, sav.Length);
SAV.WC6Flags = flags;
Main.SAV.Data = SAV.Data;
Main.SAV.Edited = true;
Close();
}
@@ -260,7 +232,7 @@ private void tabMain_DragDrop(object sender, DragEventArgs e)
byte[] newwc6 = File.ReadAllBytes(path);
if (newwc6.Length == WC6.SizeFull)
newwc6 = newwc6.Skip(WC6.SizeFull - WC6.Size).ToArray();
Array.Copy(newwc6, wondercard_data, newwc6.Length);
Array.Copy(newwc6, wc6.Data, newwc6.Length);
loadwcdata();
return;
}
@@ -279,10 +251,11 @@ private void tabMain_DragDrop(object sender, DragEventArgs e)
if (newwc6.Length == WC6.SizeFull)
newwc6 = newwc6.Skip(WC6.SizeFull - WC6.Size).ToArray();
if (checkSpecialWonderCard(newwc6))
if (checkSpecialWonderCard(new WC6(newwc6)))
{
newwc6.CopyTo(sav, Main.SAV.WondercardData + WC6.Size * ctr++);
setCardID(BitConverter.ToUInt16(newwc6, 0));
WC6 wc = new WC6(newwc6);
SAV.setWC6(wc, ctr++);
setCardID(wc.CardID);
}
if (ctr >= 24)
break;
@@ -290,85 +263,43 @@ private void tabMain_DragDrop(object sender, DragEventArgs e)
populateWClist();
}
private bool checkSpecialWonderCard(byte[] data)
private bool checkSpecialWonderCard(WC6 wc)
{
ushort cardID = BitConverter.ToUInt16(data, 0);
ushort item = BitConverter.ToUInt16(data, 0x68);
if (cardID == 2048 && item == 726) // Eon Ticket (OR/AS)
if (wc6.CardID == 2048 && wc.Item == 726) // Eon Ticket (OR/AS)
{
if (!Main.SAV.ORAS || Main.SAV.EonTicket < 0)
goto reject;
BitConverter.GetBytes(EonTicketConst).CopyTo(sav, Main.SAV.EonTicket);
BitConverter.GetBytes(WC6.EonTicketConst).CopyTo(SAV.Data, Main.SAV.EonTicket);
}
return true;
reject: Util.Alert("Unable to insert the Wonder Card.", "Does this Wonder Card really belong to this game?");
return false;
}
// String Creation
private string getWCDescriptionString(byte[] data)
{
WC6 wc = new WC6(data);
if (wc.CardID == 0)
return "Empty Slot. No data!";
string s = $"Card #: {wc.CardID.ToString("0000")} - {wc.CardTitle.Trim()}" + Environment.NewLine;
switch (wc.CardType)
{
case 1:
s += "Item: " + Main.itemlist[wc.Item] + Environment.NewLine + "Quantity: " + wc.Quantity;
return s;
case 0:
s +=
$"{Main.specieslist[wc.Species]} @ {Main.itemlist[wc.HeldItem]} --- {wc.OT} - {wc.TID.ToString("00000")}/{wc.SID.ToString("00000")}" + Environment.NewLine +
$"{Main.movelist[wc.Move1]} / {Main.movelist[wc.Move2]} / {Main.movelist[wc.Move3]} / {Main.movelist[wc.Move4]}" + Environment.NewLine;
return s;
default:
s += "Unknown Wonder Card Type!";
return s;
}
}
private Image getWCPreviewImage(byte[] data)
{
Image img;
WC6 wc = new WC6(data);
if (wc.IsPokémon)
img = PKX.getSprite(wc.Species, wc.Form, wc.Gender, wc.HeldItem, wc.IsEgg, wc.PIDType == 2);
else if (wc.IsItem)
img = (Image)(Properties.Resources.ResourceManager.GetObject("item_" + BitConverter.ToUInt16(data, 0x68)) ?? Properties.Resources.unknown);
else
img = Properties.Resources.unknown;
if (wc.GiftUsed)
img = Util.LayerImage(new Bitmap(img.Width, img.Height), img, 0, 0, 0.3);
return img;
}
private void L_QR_Click(object sender, EventArgs e)
{
if (ModifierKeys == Keys.Alt)
{
byte[] wc = Util.getQRData();
if (wc == null) return;
if (wc.Length != WC6.Size) { Util.Alert("Decoded data not 0x108 bytes.",
$"QR Data Size: 0x{wc.Length.ToString("X")}"); }
byte[] data = Util.getQRData();
if (data == null) return;
if (data.Length != WC6.Size) { Util.Alert("Decoded data not 0x108 bytes.",
$"QR Data Size: 0x{data.Length.ToString("X")}"); }
else try
{
wc.CopyTo(wondercard_data, 0);
wc6 = new WC6(data);
loadwcdata();
}
catch { Util.Alert("Error loading wondercard data."); }
}
else
{
if (wondercard_data.SequenceEqual(new byte[wondercard_data.Length]))
if (wc6.Data.SequenceEqual(new byte[wc6.Data.Length]))
{ Util.Alert("No wondercard data found in loaded slot!"); return; }
if (BitConverter.ToUInt16(wondercard_data, 0x68) == 726 && wondercard_data[0x51] == 1)
if (wc6.Item == 726 && wc6.IsItem)
{ Util.Alert("Eon Ticket Wonder Cards will not function properly", "Inject to the save file instead."); return; }
// Prep data
byte[] wcdata = wondercard_data;
byte[] wcdata = wc6.Data;
// Ensure size
Array.Resize(ref wcdata, WC6.Size);
// Setup QR
@@ -376,7 +307,7 @@ private void L_QR_Click(object sender, EventArgs e)
Image qr = Util.getQRImage(wcdata, server);
if (qr == null) return;
string desc = getWCDescriptionString(wondercard_data);
string desc = wc6.Description;
new QR(qr, PB_Preview.Image, desc, "", "", "PKHeX Wonder Card @ ProjectPokemon.org").ShowDialog();
}
@@ -407,15 +338,14 @@ private void pbBoxSlot_MouseDown(object sender, MouseEventArgs e)
Cursor.Current = Cursors.Hand;
// Prepare Data
byte[] dragdata = sav.Skip(Main.SAV.WondercardData + WC6.Size * index).Take(WC6.Size).ToArray();
WC6 card = new WC6(dragdata);
WC6 card = SAV.getWC6(index);
string filename = Util.CleanFileName($"{card.CardID.ToString("0000")} - {card.CardTitle}.wc6");
// Make File
string newfile = Path.Combine(Path.GetTempPath(), Util.CleanFileName(filename));
try
{
File.WriteAllBytes(newfile, dragdata);
File.WriteAllBytes(newfile, card.Data);
DoDragDrop(new DataObject(DataFormats.FileDrop, new[] { newfile }), DragDropEffects.Move);
}
catch (ArgumentException x)
@@ -440,22 +370,22 @@ private void pbBoxSlot_DragDrop(object sender, DragEventArgs e)
if (files.Length < 1 || new FileInfo(files[0]).Length != WC6.Size)
return;
byte[] wcdata = File.ReadAllBytes(files[0]);
wcdata.CopyTo(sav, Main.SAV.WondercardData + WC6.Size * index);
wcdata.CopyTo(wondercard_data, 0);
WC6 wc = new WC6(File.ReadAllBytes(files[0]));
SAV.setWC6(wc, index);
setCardID(wc.CardID);
wc6 = wc;
loadwcdata();
setCardID(BitConverter.ToUInt16(wcdata, 0));
}
else // Swap Data
{
// Check to see if they copied beyond blank slots.
if (index > Math.Max(wc_slot, lastUnfilled - 1))
index = Math.Max(wc_slot, lastUnfilled - 1);
byte[] s1 = sav.Skip(Main.SAV.WondercardData + WC6.Size * index).Take(WC6.Size).ToArray();
byte[] s2 = sav.Skip(Main.SAV.WondercardData + WC6.Size * wc_slot).Take(WC6.Size).ToArray();
s1.CopyTo(sav, Main.SAV.WondercardData + WC6.Size * wc_slot);
s2.CopyTo(sav, Main.SAV.WondercardData + WC6.Size * index);
WC6 s1 = SAV.getWC6(index);
WC6 s2 = SAV.getWC6(wc_slot);
SAV.setWC6(s1, wc_slot);
SAV.setWC6(s2, index);
}
setBackground(index, Properties.Resources.slotView);
populateWClist();
@@ -469,4 +399,51 @@ private void pbBoxSlot_DragEnter(object sender, DragEventArgs e)
}
private int wc_slot = -1;
}
// Extension Properties
public partial class WC6
{
public Image Preview
{
get
{
Image img;
if (IsPokémon)
img = PKX.getSprite(Species, Form, Gender, HeldItem, IsEgg, PIDType == 2);
else if (IsItem)
img = (Image)(Properties.Resources.ResourceManager.GetObject("item_" + Item) ?? Properties.Resources.unknown);
else
img = Properties.Resources.unknown;
if (GiftUsed)
img = Util.LayerImage(new Bitmap(img.Width, img.Height), img, 0, 0, 0.3);
return img;
}
}
public string Description
{
get
{
if (CardID == 0)
return "Empty Slot. No data!";
string s = $"Card #: {CardID.ToString("0000")} - {CardTitle.Trim()}" + Environment.NewLine;
switch (CardType)
{
case 1:
s += "Item: " + Main.itemlist[Item] + Environment.NewLine + "Quantity: " + Quantity;
return s;
case 0:
s +=
$"{Main.specieslist[Species]} @ {Main.itemlist[HeldItem]} --- {OT} - {TID.ToString("00000")}/{SID.ToString("00000")}" + Environment.NewLine +
$"{Main.movelist[Move1]} / {Main.movelist[Move2]} / {Main.movelist[Move3]} / {Main.movelist[Move4]}" + Environment.NewLine;
return s;
default:
s += "Unknown Wonder Card Type!";
return s;
}
}
}
}
}