Add more s/m stuff

Inventory editing, mystery gift editing, trainer info (soon)
This commit is contained in:
Kaphotics 2016-10-26 22:06:03 -07:00
parent 9e2743ad82
commit 81547107a0
7 changed files with 132 additions and 106 deletions

View file

@ -955,8 +955,9 @@ namespace PKHeX
GB_nOT.Visible = GB_RelearnMoves.Visible = BTN_Medals.Visible = BTN_History.Visible = SAV.Generation >= 6;
PB_Legal.Visible = PB_WarnMove1.Visible = PB_WarnMove2.Visible = PB_WarnMove3.Visible = PB_WarnMove4.Visible = SAV.Generation >= 6;
PB_MarkPentagon.Visible = SAV.Generation == 6;
TB_GameSync.Visible = TB_Secure1.Visible = TB_Secure2.Visible = L_GameSync.Visible = L_Secure1.Visible = L_Secure2.Visible = SAV.Exportable && SAV.Generation == 6;
PB_MarkPentagon.Visible = SAV.Generation >= 6;
TB_Secure1.Visible = TB_Secure2.Visible = L_GameSync.Visible = L_Secure1.Visible = L_Secure2.Visible = SAV.Exportable && SAV.Generation >= 6;
TB_GameSync.Visible = SAV.Exportable && SAV.Generation == 6;
FLP_NSparkle.Visible = L_NSparkle.Visible = CHK_NSparkle.Visible = SAV.Generation == 5;
@ -1117,16 +1118,19 @@ namespace PKHeX
getFieldsfromPKM = populateFieldsPK6;
getPKMfromFields = preparePK6;
extraBytes = PK6.ExtraBytes;
SAV6 sav6 = (SAV6)SAV;
TB_GameSync.Enabled = sav6.GameSyncID != 0;
TB_GameSync.Text = sav6.GameSyncID.ToString("X16");
TB_Secure1.Text = sav6.Secure1.ToString("X16");
TB_Secure2.Text = sav6.Secure2.ToString("X16");
TB_GameSync.Enabled = (SAV.GameSyncID ?? 0) != 0;
TB_GameSync.Text = SAV.GameSyncID?.ToString("X16");
TB_Secure1.Text = SAV.Secure1?.ToString("X16");
TB_Secure2.Text = SAV.Secure2?.ToString("X16");
break;
case 7:
getFieldsfromPKM = populateFieldsPK7;
getPKMfromFields = preparePK7;
extraBytes = PK7.ExtraBytes;
TB_GameSync.Enabled = (SAV.GameSyncID ?? 0) != 0;
TB_GameSync.Text = SAV.GameSyncID?.ToString("X16");
TB_Secure1.Text = SAV.Secure1?.ToString("X16");
TB_Secure2.Text = SAV.Secure2?.ToString("X16");
break;
}
bool init = fieldsInitialized;
@ -3427,7 +3431,7 @@ namespace PKHeX
private void updateU64(object sender, EventArgs e)
{
TextBox tb = sender as TextBox;
if (tb.Text.Length == 0)
if (tb?.Text.Length == 0)
{
// Reset to 0
tb.Text = 0.ToString("X16");
@ -3435,16 +3439,15 @@ namespace PKHeX
}
// Currently saved Value
ulong oldval = 0;
ulong? oldval = 0;
if (SAV.Generation == 6)
{
SAV6 sav6 = (SAV6) SAV;
if (tb == TB_GameSync)
oldval = sav6.GameSyncID;
oldval = SAV.GameSyncID;
else if (tb == TB_Secure1)
oldval = sav6.Secure1;
oldval = SAV.Secure1;
else if (tb == TB_Secure2)
oldval = sav6.Secure2;
oldval = SAV.Secure2;
}
string filterText = Util.getOnlyHex(tb.Text);
@ -3453,23 +3456,22 @@ namespace PKHeX
{
Util.Alert("Expected HEX (0-9, A-F).", "Received: " + Environment.NewLine + tb.Text);
// Reset to Stored Value
tb.Text = oldval.ToString("X16");
tb.Text = (oldval ?? 0).ToString("X16");
return; // recursively triggers this method, no need to continue
}
// Write final value back to the save
ulong newval = Convert.ToUInt64(filterText, 16);
ulong? newval = Convert.ToUInt64(filterText, 16);
if (newval == oldval) return;
if (SAV.Generation == 6)
if (SAV.Generation >= 6)
{
SAV6 sav6 = (SAV6) SAV;
if (tb == TB_GameSync)
sav6.GameSyncID = newval;
SAV.GameSyncID = newval;
else if (tb == TB_Secure1)
sav6.Secure1 = newval;
SAV.Secure1 = newval;
else if (tb == TB_Secure2)
sav6.Secure2 = newval;
SAV.Secure2 = newval;
SAV.Edited = true;
}
}

View file

@ -138,15 +138,15 @@ namespace PKHeX
return rv;
}
}
public ulong Secure1
public override ulong? Secure1
{
get { return BitConverter.ToUInt64(Data, BlockInfoOffset - 0x14); }
set { BitConverter.GetBytes(value).CopyTo(Data, BlockInfoOffset - 0x14); }
set { BitConverter.GetBytes(value ?? 0).CopyTo(Data, BlockInfoOffset - 0x14); }
}
public ulong Secure2
public override ulong? Secure2
{
get { return BitConverter.ToUInt64(Data, BlockInfoOffset - 0xC); }
set { BitConverter.GetBytes(value).CopyTo(Data, BlockInfoOffset - 0xC); }
set { BitConverter.GetBytes(value ?? 0).CopyTo(Data, BlockInfoOffset - 0xC); }
}
private void getSAVOffsets()
@ -346,10 +346,10 @@ namespace PKHeX
get { return Data[TrainerCard + 7]; }
set { Data[TrainerCard + 7] = (byte)value; }
}
public ulong GameSyncID
public override ulong? GameSyncID
{
get { return BitConverter.ToUInt64(Data, TrainerCard + 8); }
set { BitConverter.GetBytes(value).CopyTo(Data, TrainerCard + 8); }
set { BitConverter.GetBytes(value ?? 0).CopyTo(Data, TrainerCard + 8); }
}
public override int SubRegion
{
@ -819,8 +819,8 @@ namespace PKHeX
{
if (value == null)
return;
if (value.Length > 24)
Array.Resize(ref value, 24);
if (value.Length > GiftCountMax)
Array.Resize(ref value, GiftCountMax);
for (int i = 0; i < value.Length; i++)
setWC6(value[i], i);

View file

@ -27,7 +27,7 @@ namespace PKHeX
}
// Configuration
public override SaveFile Clone() { return new SAV6(Data); }
public override SaveFile Clone() { return new SAV7(Data); }
public override int SIZE_STORED => PKX.SIZE_6STORED;
public override int SIZE_PARTY => PKX.SIZE_6PARTY;
@ -37,8 +37,8 @@ namespace PKHeX
public override int BoxCount => 32;
public override int MaxEV => 252;
public override int Generation => 7;
protected override int GiftCountMax => -1;
protected override int GiftFlagMax => -1;
protected override int GiftCountMax => 48;
protected override int GiftFlagMax => 0x100 * 8;
protected override int EventFlagMax => -1;
protected override int EventConstMax => (EventFlag - EventConst) / 2;
public override int OTLength => 12;
@ -151,9 +151,19 @@ namespace PKHeX
// Return Outputs
rv += $"SAV: {Blocks.Length - invalid}/{Blocks.Length + Environment.NewLine}";
return rv;
}
}
}
public override ulong? Secure1
{
get { return BitConverter.ToUInt64(Data, BlockInfoOffset - 0x14); }
set { BitConverter.GetBytes(value ?? 0).CopyTo(Data, BlockInfoOffset - 0x14); }
}
public override ulong? Secure2
{
get { return BitConverter.ToUInt64(Data, BlockInfoOffset - 0xC); }
set { BitConverter.GetBytes(value ?? 0).CopyTo(Data, BlockInfoOffset - 0xC); }
}
private void getSAVOffsets()
{
if (SMDEMO)
@ -175,7 +185,7 @@ namespace PKHeX
/* 14 */ Box = 0x04E00; // [36600] BoxPokemon
/* 15 */ Resort = 0x3B400; // [572C] ResortSave
/* 16 */ PlayTime = 0x40C00; // [008] PlayTime
/* 17 */ // = 0x40E00; // [1080] FieldMoveModelSave
/* 17 */ //Overworld// = 0x40E00; // [1080] FieldMoveModelSave
/* 18 */ // = 0x42000; // [1A08] Fashion
/* 19 */ // = 0x43C00; // [6408] JoinFestaPersonalSave
/* 20 */ // = 0x4A200; // [6408] JoinFestaPersonalSave
@ -196,12 +206,12 @@ namespace PKHeX
/* 35 */ // = 0x6B800; // [1C8] QRReaderSaveData
/* 36 */ // = 0x6BA00; // [200] TurtleSalmonSave
OFS_PouchHeldItem = Item + 0; // 430
OFS_PouchKeyItem = Item + 0x35C; // 184
OFS_PouchTMHM = Item + 0x4CC; // 108
OFS_PouchMedicine = Item + 0x5A4; // 64
OFS_PouchBerry = Item + 0x624; // 72
OFS_PouchZCrystals = Item + 0x6B4; // 30
OFS_PouchHeldItem = Item + 0; // 430 (Case 0)
OFS_PouchKeyItem = Item + 0x6B8; // 184 (Case 4)
OFS_PouchTMHM = Item + 0x998; // 108 (Case 2)
OFS_PouchMedicine = Item + 0xB48; // 64 (Case 1)
OFS_PouchBerry = Item + 0xC48; // 72 (Case 3)
OFS_PouchZCrystals = Item + 0xD68; // 30 (Case 5)
PokeDexLanguageFlags = PokeDex + 0x550;
WondercardData = WondercardFlags + 0x100;
@ -295,30 +305,30 @@ namespace PKHeX
get { return Data[TrainerCard + 5]; }
set { Data[TrainerCard + 5] = (byte)value; }
}
public ulong GameSyncID
public override ulong? GameSyncID
{
get { return BitConverter.ToUInt64(Data, TrainerCard + 0x18); }
set { BitConverter.GetBytes(value).CopyTo(Data, TrainerCard + 0x18); }
set { BitConverter.GetBytes(value ?? 0).CopyTo(Data, TrainerCard + 0x18); }
}
public override int SubRegion
{
get { return Data[TrainerCard + 0x26]; }
set { Data[TrainerCard + 0x26] = (byte)value; }
get { return Data[TrainerCard + 0x2E]; }
set { Data[TrainerCard + 0x2E] = (byte)value; }
}
public override int Country
{
get { return Data[TrainerCard + 0x27]; }
set { Data[TrainerCard + 0x27] = (byte)value; }
get { return Data[TrainerCard + 0x2F]; }
set { Data[TrainerCard + 0x2F] = (byte)value; }
}
public override int ConsoleRegion
{
get { return Data[TrainerCard + 0x2C]; }
set { Data[TrainerCard + 0x2C] = (byte)value; }
get { return Data[TrainerCard + 0x34]; }
set { Data[TrainerCard + 0x34] = (byte)value; }
}
public override int Language
{
get { return Data[TrainerCard + 0x2D]; }
set { Data[TrainerCard + 0x2D] = (byte)value; }
get { return Data[TrainerCard + 0x35]; }
set { Data[TrainerCard + 0x35] = (byte)value; }
}
public override string OT
{
@ -363,46 +373,6 @@ namespace PKHeX
public override int SecondsToStart { get { return BitConverter.ToInt32(Data, AdventureInfo + 0x28); } set { BitConverter.GetBytes(value).CopyTo(Data, AdventureInfo + 0x28); } }
public override int SecondsToFame { get { return BitConverter.ToInt32(Data, AdventureInfo + 0x30); } set { BitConverter.GetBytes(value).CopyTo(Data, AdventureInfo + 0x30); } }
public int[] SelectItems
{
// UP,RIGHT,DOWN,LEFT
get
{
int[] list = new int[4];
for (int i = 0; i < list.Length; i++)
list[i] = BitConverter.ToUInt16(Data, ItemInfo + 10 + 2 * i);
return list;
}
set
{
if (value == null || value.Length > 4)
return;
for (int i = 0; i < value.Length; i++)
BitConverter.GetBytes((ushort)value[i]).CopyTo(Data, ItemInfo + 10 + 2 * i);
}
}
public int[] RecentItems
{
// Items recently interacted with (Give, Use)
get
{
int[] list = new int[12];
for (int i = 0; i < list.Length; i++)
list[i] = BitConverter.ToUInt16(Data, ItemInfo + 20 + 2 * i);
return list;
}
set
{
if (value == null || value.Length > 12)
return;
for (int i = 0; i < value.Length; i++)
BitConverter.GetBytes((ushort)value[i]).CopyTo(Data, ItemInfo + 20 + 2 * i);
}
}
public override string JPEGTitle => JPEG < 0 ? null : Util.TrimFromZero(Encoding.Unicode.GetString(Data, JPEG, 0x1A));
public override byte[] JPEGData => JPEG < 0 || Data[JPEG + 0x54] != 0xFF ? null : Data.Skip(JPEG + 0x54).Take(0xE004).ToArray();
// Inventory
public override InventoryPouch[] Inventory
{
@ -418,13 +388,13 @@ namespace PKHeX
new InventoryPouch(InventoryType.ZCrystals, Legal.Pouch_ZCrystal_SM, 995, OFS_PouchZCrystals),
};
foreach (var p in pouch)
p.getPouch(ref Data);
p.getPouch7(ref Data);
return pouch;
}
set
{
foreach (var p in value)
p.setPouch(ref Data);
p.setPouch7(ref Data);
}
}
@ -711,8 +681,8 @@ namespace PKHeX
{
if (value == null)
return;
if (value.Length > 24)
Array.Resize(ref value, 24);
if (value.Length > GiftCountMax)
Array.Resize(ref value, GiftCountMax);
for (int i = 0; i < value.Length; i++)
setWC6(value[i], i);

View file

@ -329,6 +329,9 @@ namespace PKHeX
public abstract int getBoxWallpaper(int box);
public abstract string getBoxName(int box);
public abstract void setBoxName(int box, string val);
public virtual ulong? GameSyncID { get { return null; } set { } }
public virtual ulong? Secure1 { get { return null; } set { } }
public virtual ulong? Secure2 { get { return null; } set { } }
// Daycare
public int DaycareIndex = 0;

View file

@ -471,6 +471,10 @@ namespace PKHeX
case GameVersion.AS:
return GameVersion.ORAS;
case GameVersion.SN:
case GameVersion.MN:
return GameVersion.SM;
default:
return GameVersion.Invalid;
}
@ -580,6 +584,8 @@ namespace PKHeX
case SIZE_G6XY:
case SIZE_G6ORASDEMO:
case SIZE_G6ORAS:
case SIZE_G7SMDEMO:
return true;
default:
return false;
@ -653,7 +659,7 @@ namespace PKHeX
/// <returns>Checksum</returns>
internal static ushort check16(byte[] data, int blockID, ushort initial = 0)
{
if (blockID == 0x24)
if (blockID == 36)
new byte[0x80].CopyTo(data, 0x100);
int len = data.Length;
@ -661,22 +667,20 @@ namespace PKHeX
if (len > 1)
{
int ofs = -1;
if (len % 2 == 0)
if (len % 2 == 0) // always true, always even length
{
ofs = 0;
chk = (ushort)(crc16[(data[0] ^ chk) & 0xFF] ^ (chk >> 8));
chk = (ushort)(crc16[(data[0] ^ chk) & 0xFF] ^ chk >> 8);
}
for (int i = (len - 1) / 2; i != 0; i--, ofs += 2)
{
ushort temp1 = data[ofs + 1];
ushort temp2 = data[ofs + 2];
ushort temp3 = crc16[(temp1 ^ chk) & 0xFF];
chk = (ushort)(crc16[(temp2 ^ temp3 ^ (chk >> 8)) & 0xFF] ^ ((temp3 ^ (chk >> 8)) >> 8));
ushort temp = crc16[(data[ofs + 1] ^ chk) & 0xFF];
chk = (ushort)(crc16[(data[ofs + 2] ^ temp ^ chk >> 8) & 0xFF] ^ (temp ^ chk >> 8) >> 8);
}
}
if (len >= 1)
chk = (ushort)(crc16[(data[len - 1] ^ chk) & 0xFF] ^ (chk >> 8));
if (len > 0)
chk = (ushort)(crc16[(data[len - 1] ^ chk) & 0xFF] ^ chk >> 8);
return (ushort)~chk;
}

View file

@ -18,7 +18,12 @@ namespace PKHeX
}
public class InventoryItem
{
public bool New;
public int Index, Count;
public InventoryItem Clone()
{
return new InventoryItem {Count = Count, Index = Index, New = New};
}
}
public class InventoryPouch
@ -27,10 +32,12 @@ namespace PKHeX
public readonly ushort[] LegalItems;
public readonly int MaxCount;
public int Count => Items.Count(it => it.Count > 0);
public readonly int Offset;
private readonly int PouchDataSize;
public uint SecurityKey { private get; set; } // = 0 // Gen3 Only
public InventoryItem[] Items;
private readonly int Offset;
private readonly int PouchDataSize;
private InventoryItem[] OriginalItems;
public InventoryPouch(InventoryType type, ushort[] legal, int maxcount, int offset, int size = -1)
{
@ -65,6 +72,44 @@ namespace PKHeX
BitConverter.GetBytes((ushort)((ushort)Items[i].Count ^ (ushort)SecurityKey)).CopyTo(Data, Offset + i*4 + 2);
}
}
public void getPouch7(ref byte[] Data)
{
InventoryItem[] items = new InventoryItem[PouchDataSize];
for (int i = 0; i < items.Length; i++)
{
// 10bit itemID
// 10bit count
// 12bit flags/reserved
uint val = BitConverter.ToUInt32(Data, Offset + i*4);
items[i] = new InventoryItem
{
Index = (int)(val & 0x3FF),
Count = (int)(val >> 10 & 0x3FF),
New = (val & 0x40000000) == 1, // 30th bit is "NEW"
};
}
Items = items;
OriginalItems = Items.Select(i => i.Clone()).ToArray();
}
public void setPouch7(ref byte[] Data)
{
if (Items.Length != PouchDataSize)
throw new ArgumentException("Item array length does not match original pouch size.");
for (int i = 0; i < Items.Length; i++)
{
// Build Item Value
uint val = 0;
val |= (uint)(Items[i].Index & 0x3FF);
val |= (uint)(Items[i].Index & 0x3FF) << 10;
Items[i].New |= OriginalItems.All(z => z.Index != Items[i].Index);
if (Items[i].New)
val |= 0x40000000;
BitConverter.GetBytes((ushort)val).CopyTo(Data, Offset + i * 4);
}
}
public void getPouchBigEndian(ref byte[] Data)
{
InventoryItem[] items = new InventoryItem[PouchDataSize];
@ -89,6 +134,7 @@ namespace PKHeX
BigEndian.GetBytes((ushort)((ushort)Items[i].Count ^ (ushort)SecurityKey)).CopyTo(Data, Offset + i * 4 + 2);
}
}
public void getPouchG1(ref byte[] Data)
{
InventoryItem[] items = new InventoryItem[PouchDataSize];
@ -146,7 +192,6 @@ namespace PKHeX
Items = items;
}
public void setPouchG1(ref byte[] Data)
{
if (Items.Length != PouchDataSize)

View file

@ -329,6 +329,8 @@ namespace PKHeX
Util.Alert("Decoded data not valid for loaded save file.", $"QR Data Size: 0x{data.Length.ToString("X")}");
else if (types.All(type => type != giftType))
Util.Alert("Gift type is not compatible with the save file.", $"QR Gift Type: {gift.Type}" + Environment.NewLine + $"Expected Types: {string.Join(", ", types)}");
else if (gift.Species > SAV.MaxSpeciesID || gift.Moves.Any(move => move > SAV.MaxMoveID) || gift.HeldItem > SAV.MaxItemID)
Util.Alert("Gift Details are not compatible with the save file.");
else
try { viewGiftData(gift); }
catch { Util.Alert("Error loading Mystery Gift data."); }