PKHeX/SAV/SAV_Wondercard.cs
Kurt b56edf1fec Continued Refactoring
Should be good now, a lot of silly stuff removed.
2015-03-11 21:44:12 -07:00

400 lines
No EOL
17 KiB
C#

using System;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace PKHeX
{
public partial class SAV_Wondercard : Form
{
public SAV_Wondercard(Form1 frm1)
{
InitializeComponent();
Util.TranslateInterface(this, Form1.curlanguage);
m_parent = frm1;
Array.Copy(m_parent.savefile, sav, 0x100000);
savindex = m_parent.savindex;
if (m_parent.savegame_oras) wcoffset = 0x22100;
populateWClist();
populateReceived();
LB_WCs.SelectedIndex = 0;
if (LB_Received.Items.Count > 0)
LB_Received.SelectedIndex = 0;
DragEnter += tabMain_DragEnter;
DragDrop += tabMain_DragDrop;
}
Form1 m_parent;
public byte[] sav = new byte[0x100000];
public byte[] wondercard_data = new byte[0x108];
public int savindex;
private int wcoffset = 0x21100;
private const uint herpesval = 0x225D73C2;
// Repopulation Functions
private void populateWClist()
{
LB_WCs.Items.Clear();
for (int i = 0; i < 24; i++)
{
int offset = wcoffset + savindex * 0x7F000 + i * 0x108;
int cardID = BitConverter.ToUInt16(sav, offset);
if (cardID == 0)
LB_WCs.Items.Add((i + 1).ToString("00") + " - Empty");
else
LB_WCs.Items.Add((i + 1).ToString("00") + " - " + cardID.ToString("0000"));
}
}
private void loadwcdata()
{
try
{
RTB.Text = getWCDescriptionString(wondercard_data);
PB_Preview.Image = getWCPreviewImage(wondercard_data);
}
catch (Exception e)
{
Util.Error("Loading of data failed... is this really a Wondercard?", e.ToString());
Array.Copy(new byte[0x108], wondercard_data, 0x108);
RTB.Clear();
}
}
private void populateReceived()
{
int offset = wcoffset - 0x100 + savindex * 0x7F000;
LB_Received.Items.Clear();
for (int i = 1; i < 2048; i++)
if ((((sav[offset + i / 8]) >> (i % 8)) & 0x1) == 1)
LB_Received.Items.Add(i.ToString("0000"));
}
// Wondercard IO (.wc6<->window)
private void B_Import_Click(object sender, EventArgs e)
{
OpenFileDialog importwc6 = new OpenFileDialog {Filter = "Wondercard|*.wc6"};
if (importwc6.ShowDialog() != DialogResult.OK) return;
string path = importwc6.FileName;
if (new FileInfo(path).Length > 0x108)
{
Util.Error("File is not a Wondercard:", path);
return;
}
byte[] newwc6 = File.ReadAllBytes(path);
Array.Copy(newwc6, wondercard_data, newwc6.Length);
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);
outputwc6.FileName = cardID + " - " + cardname + ".wc6";
outputwc6.Filter = "Wondercard|*.wc6";
if (outputwc6.ShowDialog() != DialogResult.OK) return;
string path = outputwc6.FileName;
if (File.Exists(path))
{
// File already exists, save a .bak
byte[] backupfile = File.ReadAllBytes(path);
File.WriteAllBytes(path + ".bak", backupfile);
}
File.WriteAllBytes(path, wondercard_data);
}
// Wondercard RW (window<->sav)
private void B_SAV2WC(object sender, EventArgs e)
{
// Load Wondercard from Save File
int index = LB_WCs.SelectedIndex;
int offset = wcoffset + savindex * 0x7F000 + index * 0x108;
Array.Copy(sav, offset, wondercard_data, 0, 0x108);
loadwcdata();
}
private void B_WC2SAV(object sender, EventArgs e)
{
// Write Wondercard to Save File
int index = LB_WCs.SelectedIndex;
int offset = wcoffset + savindex * 0x7F000 + index * 0x108;
if (m_parent.savegame_oras) // ORAS Only
if (BitConverter.ToUInt16(wondercard_data, 0) == 0x800) // Eon Ticket #
if (BitConverter.ToUInt16(wondercard_data, 0x68) == 0x2D6) // Eon Ticket
Array.Copy(BitConverter.GetBytes(herpesval), 0, sav, 0x319B8 + 0x5400 + savindex * 0x7F000, 4);
Array.Copy(wondercard_data, 0, sav, offset, 0x108);
populateWClist();
int cardID = BitConverter.ToUInt16(wondercard_data, 0);
if (cardID <= 0 || cardID >= 0x100*8) return;
if (!LB_Received.Items.Contains(cardID.ToString("0000")))
LB_Received.Items.Add(cardID.ToString("0000"));
}
private void B_DeleteWC_Click(object sender, EventArgs e)
{
int index = LB_WCs.SelectedIndex;
int offset = wcoffset + savindex * 0x7F000 + index * 0x108;
byte[] zeros = new byte[0x108];
Array.Copy(zeros, 0, sav, offset, 0x108);
populateWClist();
}
// Close Window
private void B_Cancel_Click(object sender, EventArgs e)
{
Close();
}
private void B_Save_Click(object sender, EventArgs e)
{
int offset = wcoffset - 0x100 + savindex * 0x7F000;
// 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)));
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 * 0x108) == 0)
for (int j = i + 1; j < 24 - i; j++) // Shift everything down
Array.Copy(sav, offset + j * 0x108, sav, offset + (j - 1) * 0x108, 0x108);
}
Array.Copy(sav, m_parent.savefile, 0x100000);
m_parent.savedited = true;
Close();
}
// Delete WC Flag
private void B_DeleteReceived_Click(object sender, EventArgs e)
{
if (LB_Received.SelectedIndex <= -1) return;
if (LB_Received.Items.Count > 0)
LB_Received.Items.Remove(LB_Received.Items[LB_Received.SelectedIndex]);
}
// Drag & Drop Wondercards
private void tabMain_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
}
private void tabMain_DragDrop(object sender, DragEventArgs e)
{
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
// Check for multiple wondercards
if (LB_WCs.SelectedIndex < 0) LB_WCs.SelectedIndex = 0;
int ctr = LB_WCs.SelectedIndex;
if (files.Length == 1)
{
string path = files[0]; // open first D&D
if (new FileInfo(path).Length > 0x108)
{
Util.Error("File is not a Wondercard:", path);
return;
}
byte[] newwc6 = File.ReadAllBytes(path);
Array.Copy(newwc6, wondercard_data, newwc6.Length);
loadwcdata();
}
else if (DialogResult.Yes == Util.Prompt(MessageBoxButtons.YesNo, String.Format("Try to load {0} Wondercards starting at Card {1}?", files.Length, ctr + 1)))
{
int i = 0;
while (i < files.Length && ctr < 24)
{
string path = files[i++]; // open first D&D
if (new FileInfo(path).Length != 0x108)
{ Util.Error("File is not a Wondercard:", path); continue; }
ctr++; // Load in WC
byte[] newwc6 = File.ReadAllBytes(path);
Array.Copy(newwc6, wondercard_data, newwc6.Length);
loadwcdata();
// Set in WC
B_DisplaytoWCSlot.PerformClick();
// Advance to next WC
if (ctr != 24) LB_WCs.SelectedIndex = ctr;
}
}
}
// String Creation
private string getWCDescriptionString(byte[] data)
{
// Load up the data according to the wiki!
int cardID = BitConverter.ToUInt16(data, 0);
if (cardID == 0) return "Empty Slot. No data!";
string cardname = Util.TrimFromZero(Encoding.Unicode.GetString(data, 0x2, 0x48));
int cardtype = data[0x51];
string s = "";
s += "Card #: " + cardID.ToString("0000") + " - " + cardname + Environment.NewLine;
if (cardtype == 1) // Item
{
int item = BitConverter.ToUInt16(data, 0x68);
int qty = BitConverter.ToUInt16(data, 0x70);
s += "Item: " + Form1.itemlist[item] + Environment.NewLine + "Quantity: " + qty;
}
else if (cardtype == 0) // PKM
{
int species = BitConverter.ToUInt16(data, 0x82);
int helditem = BitConverter.ToUInt16(data, 0x78);
int move1 = BitConverter.ToUInt16(data, 0x7A);
int move2 = BitConverter.ToUInt16(data, 0x7C);
int move3 = BitConverter.ToUInt16(data, 0x7E);
int move4 = BitConverter.ToUInt16(data, 0x80);
int TID = BitConverter.ToUInt16(data, 0x68);
int SID = BitConverter.ToUInt16(data, 0x6A);
string OTname = Util.TrimFromZero(Encoding.Unicode.GetString(data, 0xB6, 22));
s += String.Format(
"{1} @ {2} --- {7} - {8}/{9}{0}" +
"{3} / {4} / {5} / {6}{0}",
Environment.NewLine,
Form1.specieslist[species],
Form1.itemlist[helditem],
Form1.movelist[move1],
Form1.movelist[move2],
Form1.movelist[move3],
Form1.movelist[move4],
OTname, TID.ToString("00000"), SID.ToString("00000"));
}
else
s += "Unknown Wondercard Type!";
return s;
}
private Image getWCPreviewImage(byte[] data)
{
Image img;
switch (data[0x51])
{
case 0:
ushort species = BitConverter.ToUInt16(data, 0x82);
byte altforms = data[0x84];
byte gender = data[0xA1];
string file = "_" + species;
if (altforms > 0) // Alt Form Handling
file = file + "_" + altforms;
else if (gender == 1 && (species == 592 || species == 593)) // Frillish & Jellicent
file = file + "_" + gender;
else if (gender == 1 && (species == 521 || species == 668)) // Unfezant & Pyroar
file = "_" + species + "f";
img = (Image) Properties.Resources.ResourceManager.GetObject(file);
// Improve the Preview
ushort item = BitConverter.ToUInt16(data, 0x78);
if (data[0xD1] > 0) img = Util.LayerImage(img, Properties.Resources.egg, 0, 0, 1);
if (data[0xA3] == 2) img = Util.LayerImage(img, Properties.Resources.rare_icon, 0, 0, 0.7);
if (item > 0)
{
Image itemimg = (Image)Properties.Resources.ResourceManager.GetObject("item_" + item) ?? Properties.Resources.helditem;
img = Util.LayerImage(img, itemimg, 22 + (15 - itemimg.Width) / 2, 15 + (15 - itemimg.Height), 1);
}
break;
case 1:
img = (Image)Properties.Resources.ResourceManager.GetObject("item_" + BitConverter.ToUInt16(data, 0x68));
break;
default:
img = Properties.Resources.unknown;
break;
}
return img;
}
private void L_QR_Click(object sender, EventArgs e)
{
if (ModifierKeys == Keys.Alt)
{
// Fetch data from QR code...
string address;
try { address = Clipboard.GetText(); }
catch { Util.Alert("No text (url) in clipboard."); return; }
try { if (address.Length < 4 || address.Substring(0, 3) != "htt") { Util.Alert("Clipboard text is not a valid URL:", address); return; } }
catch { Util.Alert("Clipboard text is not a valid URL:", address); return; }
string webURL = "http://api.qrserver.com/v1/read-qr-code/?fileurl=" + System.Web.HttpUtility.UrlEncode(address);
try
{
System.Net.HttpWebRequest httpWebRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(webURL);
System.Net.HttpWebResponse httpWebReponse = (System.Net.HttpWebResponse)httpWebRequest.GetResponse();
var reader = new StreamReader(httpWebReponse.GetResponseStream());
string data = reader.ReadToEnd();
if (data.Contains("could not find")) { Util.Alert("Reader could not find QR data in the image."); return; }
// Quickly convert the json response to a data string
string pkstr = data.Substring(data.IndexOf("#", StringComparison.Ordinal) + 1); // Trim intro
pkstr = pkstr.Substring(0, pkstr.IndexOf("\",\"error\":null}]}]", StringComparison.Ordinal)); // Trim outro
if (pkstr.Contains("nQR-Code:")) pkstr = pkstr.Substring(0, pkstr.IndexOf("nQR-Code:", StringComparison.Ordinal)); // Remove multiple QR codes in same image
pkstr = pkstr.Replace("\\", ""); // Rectify response
byte[] wc;
try { wc = Convert.FromBase64String(pkstr); }
catch { Util.Alert("QR string to Data failed.", pkstr); return; }
if (wc.Length != 0x108) { Util.Alert("Decoded data not 0x108 bytes.", String.Format("QR Data Size: 0x{0}", wc.Length.ToString("X"))); }
else try
{
Array.Copy(wc, wondercard_data, wc.Length);
loadwcdata();
}
catch { Util.Alert("Error loading wondercard data."); }
}
catch { Util.Alert("Unable to connect to the internet to decode QR code."); }
}
else
{
if (wondercard_data.SequenceEqual((new byte[wondercard_data.Length])))
{ Util.Alert("No wondercard data found"); return; }
// Prep data
byte[] wcdata = wondercard_data;
// Ensure size
Array.Resize(ref wcdata, 0x108);
// Setup QR
const string server = "http://lunarcookies.github.io/wc.html#";
string qrdata = Convert.ToBase64String(wcdata);
string message = server + qrdata;
string webURL = "http://chart.apis.google.com/chart?chs=365x365&cht=qr&chl=" + System.Web.HttpUtility.UrlEncode(message);
Image qr = null;
try
{
System.Net.HttpWebRequest httpWebRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(webURL);
System.Net.HttpWebResponse httpWebReponse = (System.Net.HttpWebResponse)httpWebRequest.GetResponse();
Stream stream = httpWebReponse.GetResponseStream();
if (stream != null) qr = Image.FromStream(stream);
}
catch
{
if (DialogResult.Yes == Util.Prompt(MessageBoxButtons.YesNo, "Unable to connect to the internet to receive QR code.", "Copy QR URL to Clipboard?"))
{
try { Clipboard.SetText(webURL); }
catch { Util.Alert("Failed to set text to Clipboard"); }
return;
}
}
string desc = getWCDescriptionString(wondercard_data);
Image img = PB_Preview.Image;
new QR(qr, img, desc, "", "", "PKHeX Wondercard @ ProjectPokemon.org").ShowDialog();
}
}
}
}