2016-11-16 08:11:41 +00:00
|
|
|
|
using System;
|
2019-02-10 04:07:15 +00:00
|
|
|
|
using System.Collections.Generic;
|
2016-11-16 08:11:41 +00:00
|
|
|
|
|
2017-01-08 07:54:09 +00:00
|
|
|
|
namespace PKHeX.Core
|
2016-11-16 08:11:41 +00:00
|
|
|
|
{
|
2016-11-16 10:08:23 +00:00
|
|
|
|
// anatomy of a QR7:
|
|
|
|
|
// u32 magic; // POKE
|
|
|
|
|
// u32 _0xFF;
|
|
|
|
|
// u32 box;
|
|
|
|
|
// u32 slot;
|
|
|
|
|
// u32 num_copies;
|
|
|
|
|
// u8 reserved[0x1C];
|
|
|
|
|
// u8 ek7[0x104];
|
|
|
|
|
// u8 dex_data[0x60];
|
|
|
|
|
// u16 crc16
|
|
|
|
|
// sizeof(QR7) == 0x1A2
|
2018-05-12 15:13:39 +00:00
|
|
|
|
|
2019-02-10 04:07:15 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Generation 7 QR format (readable by the in-game QR Scanner feature)
|
|
|
|
|
/// </summary>
|
2017-01-08 08:14:34 +00:00
|
|
|
|
public static class QR7
|
2016-11-16 08:11:41 +00:00
|
|
|
|
{
|
2020-12-22 01:17:56 +00:00
|
|
|
|
private static readonly HashSet<int> GenderDifferences = new()
|
2016-11-16 08:11:41 +00:00
|
|
|
|
{
|
2019-02-10 04:07:15 +00:00
|
|
|
|
003, 012, 019, 020, 025, 026, 041, 042, 044, 045,
|
|
|
|
|
064, 065, 084, 085, 097, 111, 112, 118, 119, 123,
|
|
|
|
|
129, 130, 154, 165, 166, 178, 185, 186, 190, 194,
|
|
|
|
|
195, 198, 202, 203, 207, 208, 212, 214, 215, 217,
|
|
|
|
|
221, 224, 229, 232, 255, 256, 257, 267, 269, 272,
|
|
|
|
|
274, 275, 307, 308, 315, 316, 317, 322, 323, 332,
|
|
|
|
|
350, 369, 396, 397, 398, 399, 400, 401, 402, 403,
|
|
|
|
|
404, 405, 407, 415, 417, 418, 419, 424, 443, 444,
|
|
|
|
|
445, 449, 450, 453, 454, 456, 457, 459, 460, 461,
|
|
|
|
|
464, 465, 473, 521, 592, 593, 668, 678
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
private static readonly byte[] BaseQR =
|
|
|
|
|
{
|
|
|
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD2, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
2019-04-15 22:43:48 +00:00
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
2019-02-10 04:07:15 +00:00
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
};
|
2018-07-29 20:27:48 +00:00
|
|
|
|
|
2020-12-23 04:50:33 +00:00
|
|
|
|
private static byte[] GetRawQR(int species, int form, bool shiny, int gender)
|
2016-11-16 08:11:41 +00:00
|
|
|
|
{
|
2019-02-10 04:07:15 +00:00
|
|
|
|
var basedata = (byte[])BaseQR.Clone();
|
2016-11-16 08:11:41 +00:00
|
|
|
|
BitConverter.GetBytes((ushort)species).CopyTo(basedata, 0x28);
|
2019-04-15 22:43:48 +00:00
|
|
|
|
|
2020-12-23 04:50:33 +00:00
|
|
|
|
var pi = PersonalTable.USUM.GetFormEntry(species, form);
|
2019-04-15 22:43:48 +00:00
|
|
|
|
bool biGender = false;
|
|
|
|
|
if (pi.OnlyMale)
|
|
|
|
|
gender = 0;
|
|
|
|
|
else if (pi.OnlyFemale)
|
|
|
|
|
gender = 1;
|
|
|
|
|
else if (pi.Genderless)
|
|
|
|
|
gender = 2;
|
|
|
|
|
else
|
|
|
|
|
biGender = !GenderDifferences.Contains(species);
|
|
|
|
|
|
2020-12-23 04:50:33 +00:00
|
|
|
|
basedata[0x2A] = (byte)form;
|
2019-04-15 22:43:48 +00:00
|
|
|
|
basedata[0x2B] = (byte)gender;
|
2020-12-22 00:53:28 +00:00
|
|
|
|
basedata[0x2C] = shiny ? 1 : 0;
|
|
|
|
|
basedata[0x2D] = biGender ? 1 : 0;
|
2016-11-16 08:11:41 +00:00
|
|
|
|
return basedata;
|
|
|
|
|
}
|
2018-07-29 20:27:48 +00:00
|
|
|
|
|
2017-01-12 01:55:42 +00:00
|
|
|
|
public static byte[] GenerateQRData(PK7 pk7, int box = 0, int slot = 0, int num_copies = 1)
|
2016-11-16 08:11:41 +00:00
|
|
|
|
{
|
|
|
|
|
if (box > 31)
|
|
|
|
|
box = 31;
|
|
|
|
|
if (slot > 29)
|
|
|
|
|
slot = 29;
|
|
|
|
|
if (box < 0)
|
|
|
|
|
box = 0;
|
|
|
|
|
if (slot < 0)
|
|
|
|
|
slot = 0;
|
2016-11-16 10:08:23 +00:00
|
|
|
|
if (num_copies < 0)
|
|
|
|
|
num_copies = 1;
|
2016-11-16 08:11:41 +00:00
|
|
|
|
|
|
|
|
|
byte[] data = new byte[0x1A2];
|
|
|
|
|
BitConverter.GetBytes(0x454B4F50).CopyTo(data, 0); // POKE magic
|
2016-11-17 02:27:09 +00:00
|
|
|
|
data[0x4] = 0xFF; // QR Type
|
2016-11-16 08:11:41 +00:00
|
|
|
|
BitConverter.GetBytes(box).CopyTo(data, 0x8);
|
|
|
|
|
BitConverter.GetBytes(slot).CopyTo(data, 0xC);
|
2016-11-16 10:08:23 +00:00
|
|
|
|
BitConverter.GetBytes(num_copies).CopyTo(data, 0x10); // No need to check max num_copies, payload parser handles it on-console.
|
2016-11-16 08:11:41 +00:00
|
|
|
|
|
|
|
|
|
pk7.EncryptedPartyData.CopyTo(data, 0x30); // Copy in pokemon data
|
2020-12-11 04:42:30 +00:00
|
|
|
|
GetRawQR(pk7.Species, pk7.Form, pk7.IsShiny, pk7.Gender).CopyTo(data, 0x140);
|
2019-03-16 19:01:21 +00:00
|
|
|
|
BitConverter.GetBytes(Checksums.CRC16(data, 0, 0x1A0)).CopyTo(data, 0x1A0);
|
2016-11-16 08:11:41 +00:00
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|