mirror of
https://github.com/kwsch/PKHeX
synced 2025-02-17 05:48:44 +00:00
Sync current Colo/XD implementation
Not working yet, need to pull in PBR support
This commit is contained in:
parent
3114c658d9
commit
05000b7697
12 changed files with 1591 additions and 2 deletions
|
@ -43,5 +43,37 @@ namespace PKHeX
|
|||
20, 15, 10, 10, 15, 10, 05, 05, 10, 15, 10, 05, 20, 25, 05, 40, 10, 05, 40, 15, 20, 20, 05, 15, 20, 30, 15, 15, 05, 10, 30, 20, 30, 15, 05, 40, 15, 05, 20, 05, 15, 25, 40, 15, 20, 15, 20, 15, 20, 10,
|
||||
20, 20, 05, 05,
|
||||
};
|
||||
|
||||
internal static readonly ushort[] Pouch_Cologne_CXD = {543, 544, 545};
|
||||
internal static readonly ushort[] Pouch_Items_COLO = Pouch_Items_RS.Concat(new ushort[] {537}).ToArray(); // Time Flute
|
||||
internal static readonly ushort[] HeldItems_COLO = new ushort[1].Concat(Pouch_Items_COLO).Concat(Pouch_Ball_RS).Concat(Pouch_Berries_RS).Concat(Pouch_TM_RS).ToArray();
|
||||
internal static readonly ushort[] Pouch_Key_COLO =
|
||||
{
|
||||
500, 501, 502, 503, 504, 505, 506, 507, 508, 509,
|
||||
510, 511, 512, 513, 514, 515, 516, 517, 518, 519,
|
||||
520, 521, 522, 523, 524, 525, 526, 527, 528, 529,
|
||||
530, 531, 532, 533, 534, 535, 536, 538, 539,
|
||||
540, 541, 542, 546, 547,
|
||||
};
|
||||
|
||||
internal static readonly ushort[] Pouch_Items_XD = Pouch_Items_RS.Concat(new ushort[] {511}).ToArray(); // Poké Snack
|
||||
internal static readonly ushort[] HeldItems_XD = new ushort[1].Concat(Pouch_Items_XD).Concat(Pouch_Ball_RS).Concat(Pouch_Berries_RS).Concat(Pouch_TM_RS).ToArray();
|
||||
internal static readonly ushort[] Pouch_Key_XD =
|
||||
{
|
||||
500, 501, 502, 503, 504, 505, 506, 507, 508, 509,
|
||||
510, 512, 516, 517, 518, 519,
|
||||
523, 524, 525, 526, 527, 528, 529,
|
||||
530, 531, 532, 533
|
||||
};
|
||||
internal static readonly ushort[] Pouch_Disc_XD =
|
||||
{
|
||||
534, 535, 536, 537, 538, 539,
|
||||
540, 541, 542, 543, 544, 545, 546, 547, 548, 549,
|
||||
550, 551, 552, 553, 554, 555, 556, 557, 558, 559,
|
||||
560, 561, 562, 563, 564, 565, 566, 567, 568, 569,
|
||||
570, 571, 572, 573, 574, 575, 576, 577, 578, 579,
|
||||
580, 581, 582, 583, 584, 585, 586, 587, 588, 589,
|
||||
590, 591, 592, 593
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1031,6 +1031,20 @@ namespace PKHeX
|
|||
extraBytes = new byte[] { };
|
||||
break;
|
||||
case 3:
|
||||
if (SAV.Version == GameVersion.COLO)
|
||||
{
|
||||
getFieldsfromPKM = populateFieldsCK3;
|
||||
getPKMfromFields = prepareCK3;
|
||||
extraBytes = CK3.ExtraBytes;
|
||||
break;
|
||||
}
|
||||
if (SAV.Version == GameVersion.XD)
|
||||
{
|
||||
getFieldsfromPKM = populateFieldsXK3;
|
||||
getPKMfromFields = prepareXK3;
|
||||
extraBytes = XK3.ExtraBytes;
|
||||
break;
|
||||
}
|
||||
getFieldsfromPKM = populateFieldsPK3;
|
||||
getPKMfromFields = preparePK3;
|
||||
extraBytes = PK3.ExtraBytes;
|
||||
|
|
197
PKHeX/MainWindow/MainCK3.cs
Normal file
197
PKHeX/MainWindow/MainCK3.cs
Normal file
|
@ -0,0 +1,197 @@
|
|||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace PKHeX
|
||||
{
|
||||
public partial class Main
|
||||
{
|
||||
private void populateFieldsCK3()
|
||||
{
|
||||
CK3 ck3 = pkm as CK3;
|
||||
if (ck3 == null)
|
||||
return;
|
||||
|
||||
// Do first
|
||||
ck3.Stat_Level = PKX.getLevel(ck3.Species, ck3.EXP);
|
||||
if (ck3.Stat_Level == 100)
|
||||
ck3.EXP = PKX.getEXP(ck3.Stat_Level, ck3.Species);
|
||||
|
||||
CB_Species.SelectedValue = ck3.Species;
|
||||
TB_Level.Text = ck3.Stat_Level.ToString();
|
||||
TB_EXP.Text = ck3.EXP.ToString();
|
||||
|
||||
// Load rest
|
||||
CHK_Fateful.Checked = ck3.FatefulEncounter;
|
||||
CHK_IsEgg.Checked = ck3.IsEgg;
|
||||
CHK_Nicknamed.Checked = ck3.IsNicknamed;
|
||||
Label_OTGender.Text = gendersymbols[ck3.OT_Gender];
|
||||
Label_OTGender.ForeColor = ck3.OT_Gender == 1 ? Color.Red : Color.Blue;
|
||||
TB_PID.Text = ck3.PID.ToString("X8");
|
||||
CB_HeldItem.SelectedValue = ck3.G3Item;
|
||||
setAbilityList();
|
||||
CB_Ability.SelectedIndex = ck3.AbilityNumber > CB_Ability.Items.Count ? 0 : ck3.AbilityNumber;
|
||||
CB_Nature.SelectedValue = ck3.Nature;
|
||||
TB_TID.Text = ck3.TID.ToString("00000");
|
||||
TB_SID.Text = ck3.SID.ToString("00000");
|
||||
TB_Nickname.Text = ck3.Nickname;
|
||||
TB_OT.Text = ck3.OT_Name;
|
||||
TB_Friendship.Text = ck3.CurrentFriendship.ToString();
|
||||
GB_OT.BackgroundImage = null;
|
||||
CB_Language.SelectedValue = ck3.Language;
|
||||
CB_GameOrigin.SelectedValue = ck3.Version;
|
||||
CB_EncounterType.SelectedValue = ck3.Gen4 ? ck3.EncounterType : 0;
|
||||
CB_Ball.SelectedValue = ck3.Ball;
|
||||
|
||||
int cr = ck3.CurrentRegion;
|
||||
int or = ck3.OriginalRegion;
|
||||
int ver = ck3.Version;
|
||||
CB_MetLocation.SelectedValue = ck3.Met_Location;
|
||||
|
||||
TB_MetLevel.Text = ck3.Met_Level.ToString();
|
||||
|
||||
// Reset Label and ComboBox visibility, as well as non-data checked status.
|
||||
Label_PKRS.Visible = CB_PKRSStrain.Visible = CHK_Infected.Checked = ck3.PKRS_Strain != 0;
|
||||
Label_PKRSdays.Visible = CB_PKRSDays.Visible = ck3.PKRS_Days != 0;
|
||||
|
||||
// Set SelectedIndexes for PKRS
|
||||
CB_PKRSStrain.SelectedIndex = ck3.PKRS_Strain;
|
||||
CHK_Cured.Checked = ck3.PKRS_Strain > 0 && ck3.PKRS_Days == 0;
|
||||
CB_PKRSDays.SelectedIndex = Math.Min(CB_PKRSDays.Items.Count - 1, ck3.PKRS_Days); // to strip out bad hacked 'rus
|
||||
|
||||
TB_Cool.Text = ck3.CNT_Cool.ToString();
|
||||
TB_Beauty.Text = ck3.CNT_Beauty.ToString();
|
||||
TB_Cute.Text = ck3.CNT_Cute.ToString();
|
||||
TB_Smart.Text = ck3.CNT_Smart.ToString();
|
||||
TB_Tough.Text = ck3.CNT_Tough.ToString();
|
||||
TB_Sheen.Text = ck3.CNT_Sheen.ToString();
|
||||
|
||||
TB_HPIV.Text = ck3.IV_HP.ToString();
|
||||
TB_ATKIV.Text = ck3.IV_ATK.ToString();
|
||||
TB_DEFIV.Text = ck3.IV_DEF.ToString();
|
||||
TB_SPEIV.Text = ck3.IV_SPE.ToString();
|
||||
TB_SPAIV.Text = ck3.IV_SPA.ToString();
|
||||
TB_SPDIV.Text = ck3.IV_SPD.ToString();
|
||||
CB_HPType.SelectedValue = ck3.HPType;
|
||||
|
||||
TB_HPEV.Text = ck3.EV_HP.ToString();
|
||||
TB_ATKEV.Text = ck3.EV_ATK.ToString();
|
||||
TB_DEFEV.Text = ck3.EV_DEF.ToString();
|
||||
TB_SPEEV.Text = ck3.EV_SPE.ToString();
|
||||
TB_SPAEV.Text = ck3.EV_SPA.ToString();
|
||||
TB_SPDEV.Text = ck3.EV_SPD.ToString();
|
||||
|
||||
CB_Move1.SelectedValue = ck3.Move1;
|
||||
CB_Move2.SelectedValue = ck3.Move2;
|
||||
CB_Move3.SelectedValue = ck3.Move3;
|
||||
CB_Move4.SelectedValue = ck3.Move4;
|
||||
CB_PPu1.SelectedIndex = ck3.Move1_PPUps;
|
||||
CB_PPu2.SelectedIndex = ck3.Move2_PPUps;
|
||||
CB_PPu3.SelectedIndex = ck3.Move3_PPUps;
|
||||
CB_PPu4.SelectedIndex = ck3.Move4_PPUps;
|
||||
TB_PP1.Text = ck3.Move1_PP.ToString();
|
||||
TB_PP2.Text = ck3.Move2_PP.ToString();
|
||||
TB_PP3.Text = ck3.Move3_PP.ToString();
|
||||
TB_PP4.Text = ck3.Move4_PP.ToString();
|
||||
|
||||
// Set Form if count is enough, else cap.
|
||||
CB_Form.SelectedIndex = CB_Form.Items.Count > ck3.AltForm ? ck3.AltForm : CB_Form.Items.Count - 1;
|
||||
|
||||
// Load Extrabyte Value
|
||||
TB_ExtraByte.Text = ck3.Data[Convert.ToInt32(CB_ExtraBytes.Text, 16)].ToString();
|
||||
|
||||
updateStats();
|
||||
|
||||
TB_EXP.Text = ck3.EXP.ToString();
|
||||
Label_Gender.Text = gendersymbols[ck3.Gender];
|
||||
Label_Gender.ForeColor = ck3.Gender == 2 ? Label_Species.ForeColor : (ck3.Gender == 1 ? Color.Red : Color.Blue);
|
||||
}
|
||||
private PKM prepareCK3()
|
||||
{
|
||||
CK3 ck3 = pkm as CK3;
|
||||
if (ck3 == null)
|
||||
return null;
|
||||
|
||||
ck3.Species = Util.getIndex(CB_Species);
|
||||
ck3.G3Item = Util.getIndex(CB_HeldItem);
|
||||
ck3.TID = Util.ToInt32(TB_TID.Text);
|
||||
ck3.SID = Util.ToInt32(TB_SID.Text);
|
||||
ck3.EXP = Util.ToUInt32(TB_EXP.Text);
|
||||
ck3.PID = Util.getHEXval(TB_PID.Text);
|
||||
ck3.AbilityNumber = CB_Ability.SelectedIndex;
|
||||
|
||||
ck3.FatefulEncounter = CHK_Fateful.Checked;
|
||||
ck3.Gender = PKX.getGender(Label_Gender.Text);
|
||||
ck3.EV_HP = Util.ToInt32(TB_HPEV.Text);
|
||||
ck3.EV_ATK = Util.ToInt32(TB_ATKEV.Text);
|
||||
ck3.EV_DEF = Util.ToInt32(TB_DEFEV.Text);
|
||||
ck3.EV_SPE = Util.ToInt32(TB_SPEEV.Text);
|
||||
ck3.EV_SPA = Util.ToInt32(TB_SPAEV.Text);
|
||||
ck3.EV_SPD = Util.ToInt32(TB_SPDEV.Text);
|
||||
|
||||
ck3.CNT_Cool = Util.ToInt32(TB_Cool.Text);
|
||||
ck3.CNT_Beauty = Util.ToInt32(TB_Beauty.Text);
|
||||
ck3.CNT_Cute = Util.ToInt32(TB_Cute.Text);
|
||||
ck3.CNT_Smart = Util.ToInt32(TB_Smart.Text);
|
||||
ck3.CNT_Tough = Util.ToInt32(TB_Tough.Text);
|
||||
ck3.CNT_Sheen = Util.ToInt32(TB_Sheen.Text);
|
||||
|
||||
ck3.PKRS_Days = CB_PKRSDays.SelectedIndex;
|
||||
ck3.PKRS_Strain = CB_PKRSStrain.SelectedIndex;
|
||||
ck3.Nickname = TB_Nickname.Text;
|
||||
ck3.Move1 = Util.getIndex(CB_Move1);
|
||||
ck3.Move2 = Util.getIndex(CB_Move2);
|
||||
ck3.Move3 = Util.getIndex(CB_Move3);
|
||||
ck3.Move4 = Util.getIndex(CB_Move4);
|
||||
ck3.Move1_PP = Util.getIndex(CB_Move1) > 0 ? Util.ToInt32(TB_PP1.Text) : 0;
|
||||
ck3.Move2_PP = Util.getIndex(CB_Move2) > 0 ? Util.ToInt32(TB_PP2.Text) : 0;
|
||||
ck3.Move3_PP = Util.getIndex(CB_Move3) > 0 ? Util.ToInt32(TB_PP3.Text) : 0;
|
||||
ck3.Move4_PP = Util.getIndex(CB_Move4) > 0 ? Util.ToInt32(TB_PP4.Text) : 0;
|
||||
ck3.Move1_PPUps = Util.getIndex(CB_Move1) > 0 ? CB_PPu1.SelectedIndex : 0;
|
||||
ck3.Move2_PPUps = Util.getIndex(CB_Move2) > 0 ? CB_PPu2.SelectedIndex : 0;
|
||||
ck3.Move3_PPUps = Util.getIndex(CB_Move3) > 0 ? CB_PPu3.SelectedIndex : 0;
|
||||
ck3.Move4_PPUps = Util.getIndex(CB_Move4) > 0 ? CB_PPu4.SelectedIndex : 0;
|
||||
|
||||
ck3.IV_HP = Util.ToInt32(TB_HPIV.Text);
|
||||
ck3.IV_ATK = Util.ToInt32(TB_ATKIV.Text);
|
||||
ck3.IV_DEF = Util.ToInt32(TB_DEFIV.Text);
|
||||
ck3.IV_SPE = Util.ToInt32(TB_SPEIV.Text);
|
||||
ck3.IV_SPA = Util.ToInt32(TB_SPAIV.Text);
|
||||
ck3.IV_SPD = Util.ToInt32(TB_SPDIV.Text);
|
||||
ck3.IsEgg = CHK_IsEgg.Checked;
|
||||
ck3.IsNicknamed = CHK_Nicknamed.Checked;
|
||||
|
||||
ck3.OT_Name = TB_OT.Text;
|
||||
ck3.CurrentFriendship = Util.ToInt32(TB_Friendship.Text);
|
||||
|
||||
ck3.Ball = Util.getIndex(CB_Ball);
|
||||
ck3.Met_Level = Util.ToInt32(TB_MetLevel.Text);
|
||||
ck3.OT_Gender = PKX.getGender(Label_OTGender.Text);
|
||||
ck3.Version = Util.getIndex(CB_GameOrigin);
|
||||
ck3.Language = Util.getIndex(CB_Language);
|
||||
|
||||
ck3.Met_Location = Util.getIndex(CB_MetLocation);
|
||||
|
||||
// Toss in Party Stats
|
||||
Array.Resize(ref ck3.Data, ck3.SIZE_PARTY);
|
||||
ck3.Stat_Level = Util.ToInt32(TB_Level.Text);
|
||||
ck3.Stat_HPCurrent = Util.ToInt32(Stat_HP.Text);
|
||||
ck3.Stat_HPMax = Util.ToInt32(Stat_HP.Text);
|
||||
ck3.Stat_ATK = Util.ToInt32(Stat_ATK.Text);
|
||||
ck3.Stat_DEF = Util.ToInt32(Stat_DEF.Text);
|
||||
ck3.Stat_SPE = Util.ToInt32(Stat_SPE.Text);
|
||||
ck3.Stat_SPA = Util.ToInt32(Stat_SPA.Text);
|
||||
ck3.Stat_SPD = Util.ToInt32(Stat_SPD.Text);
|
||||
|
||||
if (HaX)
|
||||
{
|
||||
ck3.Stat_Level = (byte)Math.Min(Convert.ToInt32(MT_Level.Text), byte.MaxValue);
|
||||
}
|
||||
|
||||
// Fix Moves if a slot is empty
|
||||
ck3.FixMoves();
|
||||
|
||||
ck3.RefreshChecksum();
|
||||
return ck3;
|
||||
}
|
||||
}
|
||||
}
|
194
PKHeX/MainWindow/MainXK3.cs
Normal file
194
PKHeX/MainWindow/MainXK3.cs
Normal file
|
@ -0,0 +1,194 @@
|
|||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace PKHeX
|
||||
{
|
||||
public partial class Main
|
||||
{
|
||||
private void populateFieldsXK3()
|
||||
{
|
||||
XK3 xk3 = pkm as XK3;
|
||||
if (xk3 == null)
|
||||
return;
|
||||
|
||||
// Do first
|
||||
xk3.Stat_Level = PKX.getLevel(xk3.Species, xk3.EXP);
|
||||
if (xk3.Stat_Level == 100)
|
||||
xk3.EXP = PKX.getEXP(xk3.Stat_Level, xk3.Species);
|
||||
|
||||
CB_Species.SelectedValue = xk3.Species;
|
||||
TB_Level.Text = xk3.Stat_Level.ToString();
|
||||
TB_EXP.Text = xk3.EXP.ToString();
|
||||
|
||||
// Load rest
|
||||
CHK_Fateful.Checked = xk3.FatefulEncounter;
|
||||
CHK_IsEgg.Checked = xk3.IsEgg;
|
||||
CHK_Nicknamed.Checked = xk3.IsNicknamed;
|
||||
Label_OTGender.Text = gendersymbols[xk3.OT_Gender];
|
||||
Label_OTGender.ForeColor = xk3.OT_Gender == 1 ? Color.Red : Color.Blue;
|
||||
TB_PID.Text = xk3.PID.ToString("X8");
|
||||
CB_HeldItem.SelectedValue = xk3.G3Item;
|
||||
setAbilityList();
|
||||
CB_Ability.SelectedIndex = xk3.AbilityNumber > CB_Ability.Items.Count ? 0 : xk3.AbilityNumber;
|
||||
CB_Nature.SelectedValue = xk3.Nature;
|
||||
TB_TID.Text = xk3.TID.ToString("00000");
|
||||
TB_SID.Text = xk3.SID.ToString("00000");
|
||||
TB_Nickname.Text = xk3.Nickname;
|
||||
TB_OT.Text = xk3.OT_Name;
|
||||
TB_Friendship.Text = xk3.CurrentFriendship.ToString();
|
||||
GB_OT.BackgroundImage = null;
|
||||
CB_Language.SelectedValue = xk3.Language;
|
||||
CB_GameOrigin.SelectedValue = xk3.Version;
|
||||
CB_EncounterType.SelectedValue = xk3.Gen4 ? xk3.EncounterType : 0;
|
||||
CB_Ball.SelectedValue = xk3.Ball;
|
||||
|
||||
CB_MetLocation.SelectedValue = xk3.Met_Location;
|
||||
|
||||
TB_MetLevel.Text = xk3.Met_Level.ToString();
|
||||
|
||||
// Reset Label and ComboBox visibility, as well as non-data checked status.
|
||||
Label_PKRS.Visible = CB_PKRSStrain.Visible = CHK_Infected.Checked = xk3.PKRS_Strain != 0;
|
||||
Label_PKRSdays.Visible = CB_PKRSDays.Visible = xk3.PKRS_Days != 0;
|
||||
|
||||
// Set SelectedIndexes for PKRS
|
||||
CB_PKRSStrain.SelectedIndex = xk3.PKRS_Strain;
|
||||
CHK_Cured.Checked = xk3.PKRS_Strain > 0 && xk3.PKRS_Days == 0;
|
||||
CB_PKRSDays.SelectedIndex = Math.Min(CB_PKRSDays.Items.Count - 1, xk3.PKRS_Days); // to strip out bad hacked 'rus
|
||||
|
||||
TB_Cool.Text = xk3.CNT_Cool.ToString();
|
||||
TB_Beauty.Text = xk3.CNT_Beauty.ToString();
|
||||
TB_Cute.Text = xk3.CNT_Cute.ToString();
|
||||
TB_Smart.Text = xk3.CNT_Smart.ToString();
|
||||
TB_Tough.Text = xk3.CNT_Tough.ToString();
|
||||
TB_Sheen.Text = xk3.CNT_Sheen.ToString();
|
||||
|
||||
TB_HPIV.Text = xk3.IV_HP.ToString();
|
||||
TB_ATKIV.Text = xk3.IV_ATK.ToString();
|
||||
TB_DEFIV.Text = xk3.IV_DEF.ToString();
|
||||
TB_SPEIV.Text = xk3.IV_SPE.ToString();
|
||||
TB_SPAIV.Text = xk3.IV_SPA.ToString();
|
||||
TB_SPDIV.Text = xk3.IV_SPD.ToString();
|
||||
CB_HPType.SelectedValue = xk3.HPType;
|
||||
|
||||
TB_HPEV.Text = xk3.EV_HP.ToString();
|
||||
TB_ATKEV.Text = xk3.EV_ATK.ToString();
|
||||
TB_DEFEV.Text = xk3.EV_DEF.ToString();
|
||||
TB_SPEEV.Text = xk3.EV_SPE.ToString();
|
||||
TB_SPAEV.Text = xk3.EV_SPA.ToString();
|
||||
TB_SPDEV.Text = xk3.EV_SPD.ToString();
|
||||
|
||||
CB_Move1.SelectedValue = xk3.Move1;
|
||||
CB_Move2.SelectedValue = xk3.Move2;
|
||||
CB_Move3.SelectedValue = xk3.Move3;
|
||||
CB_Move4.SelectedValue = xk3.Move4;
|
||||
CB_PPu1.SelectedIndex = xk3.Move1_PPUps;
|
||||
CB_PPu2.SelectedIndex = xk3.Move2_PPUps;
|
||||
CB_PPu3.SelectedIndex = xk3.Move3_PPUps;
|
||||
CB_PPu4.SelectedIndex = xk3.Move4_PPUps;
|
||||
TB_PP1.Text = xk3.Move1_PP.ToString();
|
||||
TB_PP2.Text = xk3.Move2_PP.ToString();
|
||||
TB_PP3.Text = xk3.Move3_PP.ToString();
|
||||
TB_PP4.Text = xk3.Move4_PP.ToString();
|
||||
|
||||
// Set Form if count is enough, else cap.
|
||||
CB_Form.SelectedIndex = CB_Form.Items.Count > xk3.AltForm ? xk3.AltForm : CB_Form.Items.Count - 1;
|
||||
|
||||
// Load Extrabyte Value
|
||||
TB_ExtraByte.Text = xk3.Data[Convert.ToInt32(CB_ExtraBytes.Text, 16)].ToString();
|
||||
|
||||
updateStats();
|
||||
|
||||
TB_EXP.Text = xk3.EXP.ToString();
|
||||
Label_Gender.Text = gendersymbols[xk3.Gender];
|
||||
Label_Gender.ForeColor = xk3.Gender == 2 ? Label_Species.ForeColor : (xk3.Gender == 1 ? Color.Red : Color.Blue);
|
||||
}
|
||||
private PKM prepareXK3()
|
||||
{
|
||||
XK3 xk3 = pkm as XK3;
|
||||
if (xk3 == null)
|
||||
return null;
|
||||
|
||||
xk3.Species = Util.getIndex(CB_Species);
|
||||
xk3.G3Item = Util.getIndex(CB_HeldItem);
|
||||
xk3.TID = Util.ToInt32(TB_TID.Text);
|
||||
xk3.SID = Util.ToInt32(TB_SID.Text);
|
||||
xk3.EXP = Util.ToUInt32(TB_EXP.Text);
|
||||
xk3.PID = Util.getHEXval(TB_PID.Text);
|
||||
xk3.AbilityNumber = CB_Ability.SelectedIndex; // 0/1 (stored in IVbits)
|
||||
|
||||
xk3.FatefulEncounter = CHK_Fateful.Checked;
|
||||
xk3.Gender = PKX.getGender(Label_Gender.Text);
|
||||
xk3.EV_HP = Util.ToInt32(TB_HPEV.Text);
|
||||
xk3.EV_ATK = Util.ToInt32(TB_ATKEV.Text);
|
||||
xk3.EV_DEF = Util.ToInt32(TB_DEFEV.Text);
|
||||
xk3.EV_SPE = Util.ToInt32(TB_SPEEV.Text);
|
||||
xk3.EV_SPA = Util.ToInt32(TB_SPAEV.Text);
|
||||
xk3.EV_SPD = Util.ToInt32(TB_SPDEV.Text);
|
||||
|
||||
xk3.CNT_Cool = Util.ToInt32(TB_Cool.Text);
|
||||
xk3.CNT_Beauty = Util.ToInt32(TB_Beauty.Text);
|
||||
xk3.CNT_Cute = Util.ToInt32(TB_Cute.Text);
|
||||
xk3.CNT_Smart = Util.ToInt32(TB_Smart.Text);
|
||||
xk3.CNT_Tough = Util.ToInt32(TB_Tough.Text);
|
||||
xk3.CNT_Sheen = Util.ToInt32(TB_Sheen.Text);
|
||||
|
||||
xk3.PKRS_Days = CB_PKRSDays.SelectedIndex;
|
||||
xk3.PKRS_Strain = CB_PKRSStrain.SelectedIndex;
|
||||
xk3.Nickname = TB_Nickname.Text;
|
||||
xk3.Move1 = Util.getIndex(CB_Move1);
|
||||
xk3.Move2 = Util.getIndex(CB_Move2);
|
||||
xk3.Move3 = Util.getIndex(CB_Move3);
|
||||
xk3.Move4 = Util.getIndex(CB_Move4);
|
||||
xk3.Move1_PP = Util.getIndex(CB_Move1) > 0 ? Util.ToInt32(TB_PP1.Text) : 0;
|
||||
xk3.Move2_PP = Util.getIndex(CB_Move2) > 0 ? Util.ToInt32(TB_PP2.Text) : 0;
|
||||
xk3.Move3_PP = Util.getIndex(CB_Move3) > 0 ? Util.ToInt32(TB_PP3.Text) : 0;
|
||||
xk3.Move4_PP = Util.getIndex(CB_Move4) > 0 ? Util.ToInt32(TB_PP4.Text) : 0;
|
||||
xk3.Move1_PPUps = Util.getIndex(CB_Move1) > 0 ? CB_PPu1.SelectedIndex : 0;
|
||||
xk3.Move2_PPUps = Util.getIndex(CB_Move2) > 0 ? CB_PPu2.SelectedIndex : 0;
|
||||
xk3.Move3_PPUps = Util.getIndex(CB_Move3) > 0 ? CB_PPu3.SelectedIndex : 0;
|
||||
xk3.Move4_PPUps = Util.getIndex(CB_Move4) > 0 ? CB_PPu4.SelectedIndex : 0;
|
||||
|
||||
xk3.IV_HP = Util.ToInt32(TB_HPIV.Text);
|
||||
xk3.IV_ATK = Util.ToInt32(TB_ATKIV.Text);
|
||||
xk3.IV_DEF = Util.ToInt32(TB_DEFIV.Text);
|
||||
xk3.IV_SPE = Util.ToInt32(TB_SPEIV.Text);
|
||||
xk3.IV_SPA = Util.ToInt32(TB_SPAIV.Text);
|
||||
xk3.IV_SPD = Util.ToInt32(TB_SPDIV.Text);
|
||||
xk3.IsEgg = CHK_IsEgg.Checked;
|
||||
xk3.IsNicknamed = CHK_Nicknamed.Checked;
|
||||
|
||||
xk3.OT_Name = TB_OT.Text;
|
||||
xk3.CurrentFriendship = Util.ToInt32(TB_Friendship.Text);
|
||||
|
||||
xk3.Ball = Util.getIndex(CB_Ball);
|
||||
xk3.Met_Level = Util.ToInt32(TB_MetLevel.Text);
|
||||
xk3.OT_Gender = PKX.getGender(Label_OTGender.Text);
|
||||
xk3.Version = Util.getIndex(CB_GameOrigin);
|
||||
xk3.Language = Util.getIndex(CB_Language);
|
||||
|
||||
xk3.Met_Location = Util.getIndex(CB_MetLocation);
|
||||
|
||||
// Toss in Party Stats
|
||||
Array.Resize(ref xk3.Data, xk3.SIZE_PARTY);
|
||||
xk3.Stat_Level = Util.ToInt32(TB_Level.Text);
|
||||
xk3.Stat_HPCurrent = Util.ToInt32(Stat_HP.Text);
|
||||
xk3.Stat_HPMax = Util.ToInt32(Stat_HP.Text);
|
||||
xk3.Stat_ATK = Util.ToInt32(Stat_ATK.Text);
|
||||
xk3.Stat_DEF = Util.ToInt32(Stat_DEF.Text);
|
||||
xk3.Stat_SPE = Util.ToInt32(Stat_SPE.Text);
|
||||
xk3.Stat_SPA = Util.ToInt32(Stat_SPA.Text);
|
||||
xk3.Stat_SPD = Util.ToInt32(Stat_SPD.Text);
|
||||
|
||||
if (HaX)
|
||||
{
|
||||
xk3.Stat_Level = (byte)Math.Min(Convert.ToInt32(MT_Level.Text), byte.MaxValue);
|
||||
}
|
||||
|
||||
// Fix Moves if a slot is empty
|
||||
xk3.FixMoves();
|
||||
|
||||
xk3.RefreshChecksum();
|
||||
return xk3;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -105,12 +105,18 @@
|
|||
<Compile Include="Legality\Tables3.cs" />
|
||||
<Compile Include="Legality\Tables5.cs" />
|
||||
<Compile Include="Legality\Tables4.cs" />
|
||||
<Compile Include="MainWindow\MainXK3.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MainWindow\MainPK2.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MainWindow\MainPK1.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MainWindow\MainCK3.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MainWindow\MainPK6.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
|
@ -141,6 +147,8 @@
|
|||
<Compile Include="PersonalInfo\PersonalInfoORAS.cs" />
|
||||
<Compile Include="PersonalInfo\PersonalInfoXY.cs" />
|
||||
<Compile Include="PersonalInfo\PersonalTable.cs" />
|
||||
<Compile Include="PKM\CK3.cs" />
|
||||
<Compile Include="PKM\XK3.cs" />
|
||||
<Compile Include="PKM\PK1.cs" />
|
||||
<Compile Include="PKM\PK2.cs" />
|
||||
<Compile Include="PKM\PKM.cs" />
|
||||
|
@ -164,6 +172,8 @@
|
|||
<Compile Include="Saves\Inventory.cs" />
|
||||
<Compile Include="Saves\SAV2.cs" />
|
||||
<Compile Include="Saves\SAV1.cs" />
|
||||
<Compile Include="Saves\SAV3XD.cs" />
|
||||
<Compile Include="Saves\SAV3Colosseum.cs" />
|
||||
<Compile Include="Saves\SAV3RSBox.cs" />
|
||||
<Compile Include="Saves\SAV3.cs" />
|
||||
<Compile Include="Saves\SAV4.cs" />
|
||||
|
|
211
PKHeX/PKM/CK3.cs
Normal file
211
PKHeX/PKM/CK3.cs
Normal file
|
@ -0,0 +1,211 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX
|
||||
{
|
||||
public class CK3 : PKM // 3rd Generation PKM File
|
||||
{
|
||||
internal static readonly byte[] ExtraBytes =
|
||||
{
|
||||
0x11, 0x12, 0x13,
|
||||
0x61, 0x62, 0x63, 0x64,
|
||||
0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xDA, 0xDB,
|
||||
0xE4, 0xE5, 0xE6, 0xE7, 0xCE,
|
||||
// 0xFC onwards unused?
|
||||
};
|
||||
public sealed override int SIZE_PARTY => PKX.SIZE_3CSTORED;
|
||||
public override int SIZE_STORED => PKX.SIZE_3CSTORED;
|
||||
public override int Format => 3;
|
||||
public CK3(byte[] decryptedData = null, string ident = null)
|
||||
{
|
||||
Data = (byte[])(decryptedData ?? new byte[SIZE_PARTY]).Clone();
|
||||
PKMConverter.checkEncrypted(ref Data);
|
||||
Identifier = ident;
|
||||
if (Data.Length != SIZE_PARTY)
|
||||
Array.Resize(ref Data, SIZE_PARTY);
|
||||
}
|
||||
public override PKM Clone() { return new CK3(Data); }
|
||||
|
||||
// Future Attributes
|
||||
public override uint EncryptionConstant { get { return PID; } set { } }
|
||||
public override int Nature { get { return (int)(PID % 25); } set { } }
|
||||
public override int AltForm { get { return Species == 201 ? PKX.getUnownForm(PID) : 0; } set { } }
|
||||
|
||||
public override bool IsNicknamed { get { return PKX.getIsNicknamed(Species, Nickname); } set { } }
|
||||
public override int Gender { get { return PKX.getGender(Species, PID); } set { } }
|
||||
public override int Characteristic => -1;
|
||||
public override int CurrentFriendship { get { return OT_Friendship; } set { OT_Friendship = value; } }
|
||||
public override int Ability { get { int[] abils = PersonalTable.RS.getAbilities(Species, 0); return abils[abils[1] == 0 ? 0 : AbilityNumber]; } set { } }
|
||||
public override int CurrentHandler { get { return 0; } set { } }
|
||||
public override int Egg_Location { get { return 0; } set { } }
|
||||
|
||||
// Silly Attributes
|
||||
public override ushort Sanity { get { return 0; } set { } } // valid flag set in pkm structure.
|
||||
public override ushort Checksum { get { return PKX.getCHK(Data); } set { } } // totally false, just a way to get a 'random' ident for the pkm.
|
||||
|
||||
public override int Species { get { return PKX.getG4Species(BigEndian.ToUInt16(Data, 0x00)); } set { BigEndian.GetBytes((ushort)PKX.getG3Species(value)).CopyTo(Data, 0x00); } }
|
||||
// 02-04 unused
|
||||
public override uint PID { get { return BigEndian.ToUInt32(Data, 0x04); } set { BigEndian.GetBytes(value).CopyTo(Data, 0x04); } }
|
||||
public override int Version { get { return SaveUtil.getG3VersionID(Data[0x08]); } set { Data[0x08] = (byte)SaveUtil.getCXDVersionID(value); } }
|
||||
public int CurrentRegion { get { return Data[0x09]; } set { Data[0x09] = (byte)value; } }
|
||||
public int OriginalRegion { get { return Data[0x0A]; } set { Data[0x0A] = (byte)value; } }
|
||||
public override int Language { get { return Data[0x0B]; } set { Data[0x0B] = (byte)value; } }
|
||||
public override int Met_Location { get { return BigEndian.ToUInt16(Data, 0x0C); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x0C);} }
|
||||
public override int Met_Level { get { return Data[0x0E]; } set { Data[0x0E] = (byte)value; } }
|
||||
public override int Ball { get { return Data[0x0F]; } set { Data[0x0F] = (byte)value; } }
|
||||
public override int OT_Gender { get { return Data[0x10]; } set { Data[0x10] = (byte)value; } }
|
||||
public override int SID { get { return BigEndian.ToUInt16(Data, 0x14); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x14); } }
|
||||
public override int TID { get { return BigEndian.ToUInt16(Data, 0x16); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x16); } }
|
||||
public override string OT_Name { get { return PKX.getColoStr(Data, 0x18, 10); } set { PKX.setColoStr(value, 10).CopyTo(Data, 0x18); } } // +2 terminator
|
||||
public override string Nickname { get { return PKX.getColoStr(Data, 0x2E, 10); } set { PKX.setColoStr(value, 10).CopyTo(Data, 0x2E); Nickname2 = value; } } // +2 terminator
|
||||
private string Nickname2 { get { return PKX.getColoStr(Data, 0x44, 10); } set { PKX.setColoStr(value, 10).CopyTo(Data, 0x44); } } // +2 terminator
|
||||
public override uint EXP { get { return BigEndian.ToUInt32(Data, 0x5C); } set { BigEndian.GetBytes(value).CopyTo(Data, 0x5C);} }
|
||||
public override int Stat_Level { get { return Data[0x60]; } set { Data[0x60] = (byte)value; } }
|
||||
|
||||
// 0x64-0x77 are battle/status related
|
||||
// Not that the program cares
|
||||
|
||||
// Moves
|
||||
public override int Move1 { get { return BigEndian.ToUInt16(Data, 0x78); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x78); } }
|
||||
public override int Move1_PP { get { return Data[0x7A]; } set { Data[0x7A] = (byte)value; } }
|
||||
public override int Move1_PPUps { get { return Data[0x7B]; } set { Data[0x7B] = (byte)value; } }
|
||||
public override int Move2 { get { return BigEndian.ToUInt16(Data, 0x7C); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x7C); } }
|
||||
public override int Move2_PP { get { return Data[0x7E]; } set { Data[0x7E] = (byte)value; } }
|
||||
public override int Move2_PPUps { get { return Data[0x7F]; } set { Data[0x7F] = (byte)value; } }
|
||||
public override int Move3 { get { return BigEndian.ToUInt16(Data, 0x80); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x80); } }
|
||||
public override int Move3_PP { get { return Data[0x82]; } set { Data[0x82] = (byte)value; } }
|
||||
public override int Move3_PPUps { get { return Data[0x83]; } set { Data[0x83] = (byte)value; } }
|
||||
public override int Move4 { get { return BigEndian.ToUInt16(Data, 0x84); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x84); } }
|
||||
public override int Move4_PP { get { return Data[0x86]; } set { Data[0x86] = (byte)value; } }
|
||||
public override int Move4_PPUps { get { return Data[0x87]; } set { Data[0x87] = (byte)value; } }
|
||||
|
||||
public override int HeldItem { get { return PKX.getG4Item((ushort)G3Item); } set { } }
|
||||
public int G3Item { get { return BigEndian.ToUInt16(Data, 0x88); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x88); } }
|
||||
|
||||
// More party stats
|
||||
public override int Stat_HPCurrent { get { return BigEndian.ToUInt16(Data, 0x8A); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x8A); } }
|
||||
public override int Stat_HPMax { get { return BigEndian.ToUInt16(Data, 0x8C); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x8C); } }
|
||||
public override int Stat_ATK { get { return BigEndian.ToUInt16(Data, 0x8E); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x8E); } }
|
||||
public override int Stat_DEF { get { return BigEndian.ToUInt16(Data, 0x90); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x90); } }
|
||||
public override int Stat_SPE { get { return BigEndian.ToUInt16(Data, 0x92); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x92); } }
|
||||
public override int Stat_SPA { get { return BigEndian.ToUInt16(Data, 0x94); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x94); } }
|
||||
public override int Stat_SPD { get { return BigEndian.ToUInt16(Data, 0x96); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x96); } }
|
||||
|
||||
// EVs
|
||||
public override int EV_HP {
|
||||
get { return Math.Min(byte.MaxValue, BigEndian.ToUInt16(Data, 0x98)); }
|
||||
set { BigEndian.GetBytes((ushort)(value & 0xFF)).CopyTo(Data, 0x98); } }
|
||||
public override int EV_ATK {
|
||||
get { return Math.Min(byte.MaxValue, BigEndian.ToUInt16(Data, 0x9A)); }
|
||||
set { BigEndian.GetBytes((ushort)(value & 0xFF)).CopyTo(Data, 0x9A); } }
|
||||
public override int EV_DEF {
|
||||
get { return Math.Min(byte.MaxValue, BigEndian.ToUInt16(Data, 0x9C)); }
|
||||
set { BigEndian.GetBytes((ushort)(value & 0xFF)).CopyTo(Data, 0x9C); } }
|
||||
public override int EV_SPA {
|
||||
get { return Math.Min(byte.MaxValue, BigEndian.ToUInt16(Data, 0x9E)); }
|
||||
set { BigEndian.GetBytes((ushort)(value & 0xFF)).CopyTo(Data, 0x9E); } }
|
||||
public override int EV_SPD {
|
||||
get { return Math.Min(byte.MaxValue, BigEndian.ToUInt16(Data, 0xA0)); }
|
||||
set { BigEndian.GetBytes((ushort)(value & 0xFF)).CopyTo(Data, 0xA0); } }
|
||||
public override int EV_SPE {
|
||||
get { return Math.Min(byte.MaxValue, BigEndian.ToUInt16(Data, 0xA2)); }
|
||||
set { BigEndian.GetBytes((ushort)(value & 0xFF)).CopyTo(Data, 0xA2); } }
|
||||
|
||||
// IVs
|
||||
public override int IV_HP {
|
||||
get { return Math.Min((ushort)31, BigEndian.ToUInt16(Data, 0xA4)); }
|
||||
set { BigEndian.GetBytes((ushort)(value & 0x1F)).CopyTo(Data, 0xA4); } }
|
||||
public override int IV_ATK {
|
||||
get { return Math.Min((ushort)31, BigEndian.ToUInt16(Data, 0xA6)); }
|
||||
set { BigEndian.GetBytes((ushort)(value & 0x1F)).CopyTo(Data, 0xA6); } }
|
||||
public override int IV_DEF {
|
||||
get { return Math.Min((ushort)31, BigEndian.ToUInt16(Data, 0xA8)); }
|
||||
set { BigEndian.GetBytes((ushort)(value & 0x1F)).CopyTo(Data, 0xA8); } }
|
||||
public override int IV_SPA {
|
||||
get { return Math.Min((ushort)31, BigEndian.ToUInt16(Data, 0xAA)); }
|
||||
set { BigEndian.GetBytes((ushort)(value & 0x1F)).CopyTo(Data, 0xAA); } }
|
||||
public override int IV_SPD {
|
||||
get { return Math.Min((ushort)31, BigEndian.ToUInt16(Data, 0xAC)); }
|
||||
set { BigEndian.GetBytes((ushort)(value & 0x1F)).CopyTo(Data, 0xAC); } }
|
||||
public override int IV_SPE {
|
||||
get { return Math.Min((ushort)31, BigEndian.ToUInt16(Data, 0xAE)); }
|
||||
set { BigEndian.GetBytes((ushort)(value & 0x1F)).CopyTo(Data, 0xAE); } }
|
||||
|
||||
public override int OT_Friendship { get { return Data[0xB0]; } set { Data[0xB0] = (byte)value; } }
|
||||
|
||||
// Contest
|
||||
public override int CNT_Cool { get { return Data[0xB2]; } set { Data[0xB2] = (byte)value; } }
|
||||
public override int CNT_Beauty { get { return Data[0xB3]; } set { Data[0xB3] = (byte)value; } }
|
||||
public override int CNT_Cute { get { return Data[0xB4]; } set { Data[0xB4] = (byte)value; } }
|
||||
public override int CNT_Smart { get { return Data[0xB5]; } set { Data[0xB5] = (byte)value; } }
|
||||
public override int CNT_Tough { get { return Data[0xB6]; } set { Data[0xB6] = (byte)value; } }
|
||||
public int RibbonCountG3Cool { get { return Data[0xB7]; } set { Data[0xB7] = (byte)value; } }
|
||||
public int RibbonCountG3Beauty { get { return Data[0xB8]; } set { Data[0xB8] = (byte)value; } }
|
||||
public int RibbonCountG3Cute { get { return Data[0xB9]; } set { Data[0xB9] = (byte)value; } }
|
||||
public int RibbonCountG3Smart { get { return Data[0xBA]; } set { Data[0xBA] = (byte)value; } }
|
||||
public int RibbonCountG3Tough { get { return Data[0xBB]; } set { Data[0xBB] = (byte)value; } }
|
||||
public override int CNT_Sheen { get { return Data[0xBC]; } set { Data[0xBC] = (byte)value; } }
|
||||
|
||||
// Ribbons
|
||||
public bool RibbonChampionG3Hoenn { get { return Data[0xBD] == 1; } set { Data[0xBD] = (byte)(value ? 1 : 0); } }
|
||||
public bool RibbonWinning { get { return Data[0xBE] == 1; } set { Data[0xBE] = (byte)(value ? 1 : 0); } }
|
||||
public bool RibbonVictory { get { return Data[0xBF] == 1; } set { Data[0xBF] = (byte)(value ? 1 : 0); } }
|
||||
public bool RibbonArtist { get { return Data[0xC0] == 1; } set { Data[0xC0] = (byte)(value ? 1 : 0); } }
|
||||
public bool RibbonEffort { get { return Data[0xC1] == 1; } set { Data[0xC1] = (byte)(value ? 1 : 0); } }
|
||||
public bool RibbonChampionBattle { get { return Data[0xC2] == 1; } set { Data[0xC2] = (byte)(value ? 1 : 0); } }
|
||||
public bool RibbonChampionRegional { get { return Data[0xC3] == 1; } set { Data[0xC3] = (byte)(value ? 1 : 0); } }
|
||||
public bool RibbonChampionNational { get { return Data[0xC4] == 1; } set { Data[0xC4] = (byte)(value ? 1 : 0); } }
|
||||
public bool RibbonCountry { get { return Data[0xC5] == 1; } set { Data[0xC5] = (byte)(value ? 1 : 0); } }
|
||||
public bool RibbonNational { get { return Data[0xC6] == 1; } set { Data[0xC6] = (byte)(value ? 1 : 0); } }
|
||||
public bool RibbonEarth { get { return Data[0xC7] == 1; } set { Data[0xC7] = (byte)(value ? 1 : 0); } }
|
||||
public bool RibbonWorld { get { return Data[0xC8] == 1; } set { Data[0xC8] = (byte)(value ? 1 : 0); } }
|
||||
public bool Unused1 { get { return ((Data[0xC9]>>0) & 1) == 1; } set { Data[0xC9] = (byte)(Data[0xC9] & ~1 | (value ? 1 : 0)); } }
|
||||
public bool Unused2 { get { return ((Data[0xC9]>>1) & 1) == 1; } set { Data[0xC9] = (byte)(Data[0xC9] & ~2 | (value ? 2 : 0)); } }
|
||||
public bool Unused3 { get { return ((Data[0xC9]>>2) & 1) == 1; } set { Data[0xC9] = (byte)(Data[0xC9] & ~4 | (value ? 4 : 0)); } }
|
||||
public bool Unused4 { get { return ((Data[0xC9]>>3) & 1) == 1; } set { Data[0xC9] = (byte)(Data[0xC9] & ~8 | (value ? 8 : 0)); } }
|
||||
|
||||
public override int PKRS_Strain { get { return Data[0xCA] & 0xF; } set { Data[0xCA] = (byte)(value & 0xF); } }
|
||||
public override bool IsEgg { get { return Data[0xCB] == 1; } set { Data[0xCB] = (byte)(value ? 1 : 0); } }
|
||||
public int AbilityNumber { get { return Data[0xCC]; } set { Data[0xCC] = (byte)(value & 1); } }
|
||||
public override bool Valid => Data[0xCD] == 0;
|
||||
// 0xCE unknown
|
||||
public override byte MarkByte { get { return Data[0xCF]; } protected set { Data[0xCF] = value; } }
|
||||
public override int PKRS_Days { get { return Data[0xD0] & 0xF; } set { Data[0xD0] = (byte)(value & 0xF); } }
|
||||
public ushort ShadowID { get { return BigEndian.ToUInt16(Data, 0xD8); } set { BigEndian.GetBytes(value).CopyTo(Data, 0xD8); } }
|
||||
public int Purification { get { return BigEndian.ToInt32(Data, 0xDC); } set { BigEndian.GetBytes(value).CopyTo(Data, 0xDC); } }
|
||||
public uint EXP_Shadow { get { return BigEndian.ToUInt32(Data, 0xC0); } set { BigEndian.GetBytes(value).CopyTo(Data, 0xC0); } }
|
||||
public override bool FatefulEncounter { get { return Data[0x11C] == 1; } set { Data[0x11C] = (byte)(value ? 1 : 0); } }
|
||||
public new int EncounterType { get { return Data[0xFB]; } set { Data[0xFB] = (byte)value; } }
|
||||
|
||||
// Generated Attributes
|
||||
public override int PSV => (int)((PID >> 16 ^ PID & 0xFFFF) >> 3);
|
||||
public override int TSV => (TID ^ SID) >> 3;
|
||||
public bool Japanese => Language == 1;
|
||||
|
||||
public override byte[] Encrypt()
|
||||
{
|
||||
return (byte[])Data.Clone();
|
||||
}
|
||||
public override bool getGenderIsValid()
|
||||
{
|
||||
int gv = PersonalTable.RS[Species].Gender;
|
||||
|
||||
if (gv == 255)
|
||||
return Gender == 2;
|
||||
if (gv == 254)
|
||||
return Gender == 0;
|
||||
if (gv == 0)
|
||||
return Gender == 1;
|
||||
if (gv <= (PID & 0xFF))
|
||||
return Gender == 0;
|
||||
if ((PID & 0xFF) < gv)
|
||||
return Gender == 1;
|
||||
|
||||
return false;
|
||||
}
|
||||
public override bool CanHoldItem(ushort[] ValidArray)
|
||||
{
|
||||
return ValidArray.Contains((ushort)G3Item);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ using System.Drawing;
|
|||
using System.Drawing.Text;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using PKHeX.Properties;
|
||||
|
||||
namespace PKHeX
|
||||
|
@ -20,6 +21,8 @@ namespace PKHeX
|
|||
internal const int SIZE_2PARTY = 48;
|
||||
internal const int SIZE_2STORED = 32;
|
||||
|
||||
internal const int SIZE_3CSTORED = 312;
|
||||
internal const int SIZE_3XSTORED = 196;
|
||||
internal const int SIZE_3PARTY = 100;
|
||||
internal const int SIZE_3STORED = 80;
|
||||
internal const int SIZE_3BLOCK = 12;
|
||||
|
@ -2228,5 +2231,20 @@ namespace PKHeX
|
|||
.ToArray();
|
||||
}
|
||||
|
||||
public static string getColoStr(byte[] data, int offset, int length)
|
||||
{
|
||||
return Util.TrimFromZero(Encoding.BigEndianUnicode.GetString(data, offset, length * 2));
|
||||
}
|
||||
public static byte[] setColoStr(string value, int length)
|
||||
{
|
||||
if (value.Length > length)
|
||||
value = value.Substring(0, length); // Hard cap
|
||||
string TempNick = value // Replace Special Characters and add Terminator
|
||||
.Replace("\u2640", "\uE08F") // nidoran
|
||||
.Replace("\u2642", "\uE08E") // nidoran
|
||||
.Replace("\u0027", "\u2019") // farfetch'd
|
||||
.PadRight(value.Length + 1, (char)0); // Null Terminator
|
||||
return Encoding.BigEndianUnicode.GetBytes(TempNick);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
217
PKHeX/PKM/XK3.cs
Normal file
217
PKHeX/PKM/XK3.cs
Normal file
|
@ -0,0 +1,217 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX
|
||||
{
|
||||
public class XK3 : PKM // 3rd Generation PKM File
|
||||
{
|
||||
internal static readonly byte[] ExtraBytes =
|
||||
{
|
||||
0x0A, 0x0B, 0x0C, 0x0D, 0x1E, 0x1F,
|
||||
0x2A, 0x2B,
|
||||
0x7A, 0x7B,
|
||||
0x7E, 0x7F
|
||||
};
|
||||
public sealed override int SIZE_PARTY => PKX.SIZE_3CSTORED;
|
||||
public override int SIZE_STORED => PKX.SIZE_3CSTORED;
|
||||
public override int Format => 3;
|
||||
public XK3(byte[] decryptedData = null, string ident = null)
|
||||
{
|
||||
Data = (byte[])(decryptedData ?? new byte[SIZE_PARTY]).Clone();
|
||||
PKMConverter.checkEncrypted(ref Data);
|
||||
Identifier = ident;
|
||||
if (Data.Length != SIZE_PARTY)
|
||||
Array.Resize(ref Data, SIZE_PARTY);
|
||||
}
|
||||
public override PKM Clone() { return new XK3(Data); }
|
||||
|
||||
// Future Attributes
|
||||
public override uint EncryptionConstant { get { return PID; } set { } }
|
||||
public override int Nature { get { return (int)(PID % 25); } set { } }
|
||||
public override int AltForm { get { return Species == 201 ? PKX.getUnownForm(PID) : 0; } set { } }
|
||||
|
||||
public override bool IsNicknamed { get { return PKX.getIsNicknamed(Species, Nickname); } set { } }
|
||||
public override int Gender { get { return PKX.getGender(Species, PID); } set { } }
|
||||
public override int Characteristic => -1;
|
||||
public override int CurrentFriendship { get { return OT_Friendship; } set { OT_Friendship = value; } }
|
||||
public override int Ability { get { int[] abils = PersonalTable.RS.getAbilities(Species, 0); return abils[abils[1] == 0 ? 0 : AbilityNumber]; } set { } }
|
||||
public override int CurrentHandler { get { return 0; } set { } }
|
||||
public override int Egg_Location { get { return 0; } set { } }
|
||||
|
||||
// Silly Attributes
|
||||
public override ushort Sanity { get { return 0; } set { } } // valid flag set in pkm structure.
|
||||
public override ushort Checksum { get { return PKX.getCHK(Data); } set { } } // totally false, just a way to get a 'random' ident for the pkm.
|
||||
|
||||
public override int Species { get { return PKX.getG4Species(BigEndian.ToUInt16(Data, 0x00)); } set { BigEndian.GetBytes((ushort)PKX.getG3Species(value)).CopyTo(Data, 0x00); } }
|
||||
public override int HeldItem { get { return PKX.getG4Item((ushort)G3Item); } set { } }
|
||||
public int G3Item { get { return BigEndian.ToUInt16(Data, 0x02); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x02); } }
|
||||
public override int Stat_HPCurrent { get { return BigEndian.ToUInt16(Data, 0x04); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x04); } }
|
||||
public override int OT_Friendship { get { return Data[0x06]; } set { Data[0x06] = (byte)value; } }
|
||||
public override int Met_Location { get { return BigEndian.ToUInt16(Data, 0x08); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x08); } }
|
||||
// 0x0A-0x0B Unknown
|
||||
// 0x0C-0x0D Unknown
|
||||
public override int Met_Level { get { return Data[0x0E]; } set { Data[0x0E] = (byte)value; } }
|
||||
public override int Ball { get { return Data[0x0F]; } set { Data[0x0F] = (byte)value; } }
|
||||
public override int OT_Gender { get { return Data[0x10]; } set { Data[0x10] = (byte)value; } }
|
||||
public override int Stat_Level { get { return Data[0x11]; } set { Data[0x11] = (byte)value; } }
|
||||
public override int CNT_Sheen { get { return Data[0x12]; } set { Data[0x12] = (byte)value; } }
|
||||
public override int PKRS_Strain { get { return Data[0x13] & 0xF; } set { Data[0x13] = (byte)(value & 0xF); } }
|
||||
public override byte MarkByte { get { return Data[0x14]; } protected set { Data[0x14] = value; } }
|
||||
public override int PKRS_Days { get { return Data[0x15] & 0xF; } set { Data[0x15] = (byte)(value & 0xF); } }
|
||||
// 0x16-0x1C Battle Related
|
||||
private int XDPKMFLAGS { get { return Data[0x1D]; } set { Data[0x1D] = (byte)value; } }
|
||||
public bool UnusedFlag0 { get { return (XDPKMFLAGS & (1 << 0)) == 1 << 0; } set { XDPKMFLAGS = XDPKMFLAGS & ~(1 << 0) | (value ? 1 << 0 : 0); } }
|
||||
public bool UnusedFlag1 { get { return (XDPKMFLAGS & (1 << 1)) == 1 << 1; } set { XDPKMFLAGS = XDPKMFLAGS & ~(1 << 1) | (value ? 1 << 1 : 0); } }
|
||||
public bool CapturedFlag { get { return (XDPKMFLAGS & (1 << 2)) == 1 << 2; } set { XDPKMFLAGS = XDPKMFLAGS & ~(1 << 2) | (value ? 1 << 2 : 0); } }
|
||||
public bool UnusedFlag3 { get { return (XDPKMFLAGS & (1 << 3)) == 1 << 3; } set { XDPKMFLAGS = XDPKMFLAGS & ~(1 << 3) | (value ? 1 << 3 : 0); } }
|
||||
public bool BlockTrades { get { return (XDPKMFLAGS & (1 << 4)) == 1 << 4; } set { XDPKMFLAGS = XDPKMFLAGS & ~(1 << 4) | (value ? 1 << 4 : 0); } }
|
||||
public override bool Valid => (XDPKMFLAGS & (1 << 5)) == 1 << 5;
|
||||
public int AbilityNumber { get { return (XDPKMFLAGS >> 6) & 1; } set { XDPKMFLAGS = XDPKMFLAGS & ~(1 << 6) | (value << 6); } }
|
||||
public override bool IsEgg { get { return (XDPKMFLAGS & (1 << 7)) == 1 << 7; } set { XDPKMFLAGS = XDPKMFLAGS & ~(1 << 7) | (value ? 1 << 7 : 0); } }
|
||||
// 0x1E-0x1F Unknown
|
||||
public override uint EXP { get { return BigEndian.ToUInt32(Data, 0x20); } set { BigEndian.GetBytes(value).CopyTo(Data, 0x20); } }
|
||||
public override int SID { get { return BigEndian.ToUInt16(Data, 0x24); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x24); } }
|
||||
public override int TID { get { return BigEndian.ToUInt16(Data, 0x26); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x26); } }
|
||||
public override uint PID { get { return BigEndian.ToUInt32(Data, 0x28); } set { BigEndian.GetBytes(value).CopyTo(Data, 0x28); } }
|
||||
// 0x2A-0x2B Unknown
|
||||
// 0x2C-0x2F Battle Related
|
||||
public override bool FatefulEncounter { get { return Data[0x30] == 1; } set { Data[0x30] = (byte)(value ? 1 : 0); } }
|
||||
// 0x31-0x32 Unknown
|
||||
public new int EncounterType { get { return Data[0x33]; } set { Data[0x33] = (byte)value; } }
|
||||
public override int Version { get { return SaveUtil.getG3VersionID(Data[0x34]); } set { Data[0x34] = (byte)SaveUtil.getCXDVersionID(value); } }
|
||||
public int CurrentRegion { get { return Data[0x35]; } set { Data[0x35] = (byte)value; } }
|
||||
public int OriginalRegion { get { return Data[0x36]; } set { Data[0x36] = (byte)value; } }
|
||||
public override int Language { get { return Data[0x37]; } set { Data[0x37] = (byte)value; } }
|
||||
public override string OT_Name { get { return PKX.getColoStr(Data, 0x38, 10); } set { PKX.setColoStr(value, 10).CopyTo(Data, 0x38); } } // +2 terminator
|
||||
public override string Nickname { get { return PKX.getColoStr(Data, 0x4E, 10); } set { PKX.setColoStr(value, 10).CopyTo(Data, 0x4E); Nickname2 = value; } } // +2 terminator
|
||||
private string Nickname2 { get { return PKX.getColoStr(Data, 0x64, 10); } set { PKX.setColoStr(value, 10).CopyTo(Data, 0x64); } } // +2 terminator
|
||||
// 0x7A-0x7B Unknown
|
||||
private ushort RIB0 { get { return BigEndian.ToUInt16(Data, 0x7C); } set { BigEndian.GetBytes(value).CopyTo(Data, 0x7C); } }
|
||||
public bool RibbonChampionG3Hoenn { get { return (RIB0 & (1 << 00)) == 1 << 00; } set { RIB0 = (ushort)(RIB0 & ~(1 << 00) | (ushort)(value ? 1 << 00 : 0)); } }
|
||||
public bool RibbonWinning { get { return (RIB0 & (1 << 01)) == 1 << 01; } set { RIB0 = (ushort)(RIB0 & ~(1 << 01) | (ushort)(value ? 1 << 01 : 0)); } }
|
||||
public bool RibbonVictory { get { return (RIB0 & (1 << 02)) == 1 << 02; } set { RIB0 = (ushort)(RIB0 & ~(1 << 02) | (ushort)(value ? 1 << 02 : 0)); } }
|
||||
public bool RibbonArtist { get { return (RIB0 & (1 << 03)) == 1 << 03; } set { RIB0 = (ushort)(RIB0 & ~(1 << 03) | (ushort)(value ? 1 << 03 : 0)); } }
|
||||
public bool RibbonEffort { get { return (RIB0 & (1 << 04)) == 1 << 04; } set { RIB0 = (ushort)(RIB0 & ~(1 << 04) | (ushort)(value ? 1 << 04 : 0)); } }
|
||||
public bool RibbonChampionBattle { get { return (RIB0 & (1 << 05)) == 1 << 05; } set { RIB0 = (ushort)(RIB0 & ~(1 << 05) | (ushort)(value ? 1 << 05 : 0)); } }
|
||||
public bool RibbonChampionRegional { get { return (RIB0 & (1 << 06)) == 1 << 06; } set { RIB0 = (ushort)(RIB0 & ~(1 << 06) | (ushort)(value ? 1 << 06 : 0)); } }
|
||||
public bool RibbonChampionNational { get { return (RIB0 & (1 << 07)) == 1 << 07; } set { RIB0 = (ushort)(RIB0 & ~(1 << 07) | (ushort)(value ? 1 << 07 : 0)); } }
|
||||
public bool RibbonCountry { get { return (RIB0 & (1 << 08)) == 1 << 08; } set { RIB0 = (ushort)(RIB0 & ~(1 << 08) | (ushort)(value ? 1 << 08 : 0)); } }
|
||||
public bool RibbonNational { get { return (RIB0 & (1 << 09)) == 1 << 09; } set { RIB0 = (ushort)(RIB0 & ~(1 << 09) | (ushort)(value ? 1 << 09 : 0)); } }
|
||||
public bool RibbonEarth { get { return (RIB0 & (1 << 10)) == 1 << 10; } set { RIB0 = (ushort)(RIB0 & ~(1 << 10) | (ushort)(value ? 1 << 10 : 0)); } }
|
||||
public bool RibbonWorld { get { return (RIB0 & (1 << 11)) == 1 << 11; } set { RIB0 = (ushort)(RIB0 & ~(1 << 11) | (ushort)(value ? 1 << 11 : 0)); } }
|
||||
public bool Unused1 { get { return (RIB0 & (1 << 12)) == 1 << 12; } set { RIB0 = (ushort)(RIB0 & ~(1 << 12) | (ushort)(value ? 1 << 12 : 0)); } }
|
||||
public bool Unused2 { get { return (RIB0 & (1 << 13)) == 1 << 13; } set { RIB0 = (ushort)(RIB0 & ~(1 << 13) | (ushort)(value ? 1 << 13 : 0)); } }
|
||||
public bool Unused3 { get { return (RIB0 & (1 << 14)) == 1 << 14; } set { RIB0 = (ushort)(RIB0 & ~(1 << 14) | (ushort)(value ? 1 << 14 : 0)); } }
|
||||
public bool Unused4 { get { return (RIB0 & (1 << 15)) == 1 << 15; } set { RIB0 = (ushort)(RIB0 & ~(1 << 15) | (ushort)(value ? 1 << 15 : 0)); } }
|
||||
// 0x7E-0x7F Unknown
|
||||
|
||||
// Moves
|
||||
public override int Move1 { get { return BigEndian.ToUInt16(Data, 0x80); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x80); } }
|
||||
public override int Move1_PP { get { return Data[0x82]; } set { Data[0x82] = (byte)value; } }
|
||||
public override int Move1_PPUps { get { return Data[0x83]; } set { Data[0x83] = (byte)value; } }
|
||||
public override int Move2 { get { return BigEndian.ToUInt16(Data, 0x84); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x84); } }
|
||||
public override int Move2_PP { get { return Data[0x86]; } set { Data[0x86] = (byte)value; } }
|
||||
public override int Move2_PPUps { get { return Data[0x87]; } set { Data[0x87] = (byte)value; } }
|
||||
public override int Move3 { get { return BigEndian.ToUInt16(Data, 0x88); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x88); } }
|
||||
public override int Move3_PP { get { return Data[0x8A]; } set { Data[0x8A] = (byte)value; } }
|
||||
public override int Move3_PPUps { get { return Data[0x8B]; } set { Data[0x8B] = (byte)value; } }
|
||||
public override int Move4 { get { return BigEndian.ToUInt16(Data, 0x8C); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x8C); } }
|
||||
public override int Move4_PP { get { return Data[0x8E]; } set { Data[0x8E] = (byte)value; } }
|
||||
public override int Move4_PPUps { get { return Data[0x8F]; } set { Data[0x8F] = (byte)value; } }
|
||||
|
||||
// More party stats
|
||||
public override int Stat_HPMax { get { return BigEndian.ToUInt16(Data, 0x90); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x90); } }
|
||||
public override int Stat_ATK { get { return BigEndian.ToUInt16(Data, 0x92); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x92); } }
|
||||
public override int Stat_DEF { get { return BigEndian.ToUInt16(Data, 0x94); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x94); } }
|
||||
public override int Stat_SPE { get { return BigEndian.ToUInt16(Data, 0x96); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x96); } }
|
||||
public override int Stat_SPA { get { return BigEndian.ToUInt16(Data, 0x98); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x98); } }
|
||||
public override int Stat_SPD { get { return BigEndian.ToUInt16(Data, 0x9A); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x9A); } }
|
||||
|
||||
// EVs
|
||||
public override int EV_HP
|
||||
{
|
||||
get { return Math.Min(byte.MaxValue, BigEndian.ToUInt16(Data, 0x9C)); }
|
||||
set { BigEndian.GetBytes((ushort)(value & 0xFF)).CopyTo(Data, 0x9C); }
|
||||
}
|
||||
public override int EV_ATK
|
||||
{
|
||||
get { return Math.Min(byte.MaxValue, BigEndian.ToUInt16(Data, 0x9E)); }
|
||||
set { BigEndian.GetBytes((ushort)(value & 0xFF)).CopyTo(Data, 0x9E); }
|
||||
}
|
||||
public override int EV_DEF
|
||||
{
|
||||
get { return Math.Min(byte.MaxValue, BigEndian.ToUInt16(Data, 0xA0)); }
|
||||
set { BigEndian.GetBytes((ushort)(value & 0xFF)).CopyTo(Data, 0xA0); }
|
||||
}
|
||||
public override int EV_SPA
|
||||
{
|
||||
get { return Math.Min(byte.MaxValue, BigEndian.ToUInt16(Data, 0xA2)); }
|
||||
set { BigEndian.GetBytes((ushort)(value & 0xFF)).CopyTo(Data, 0xA2); }
|
||||
}
|
||||
public override int EV_SPD
|
||||
{
|
||||
get { return Math.Min(byte.MaxValue, BigEndian.ToUInt16(Data, 0xA4)); }
|
||||
set { BigEndian.GetBytes((ushort)(value & 0xFF)).CopyTo(Data, 0xA4); }
|
||||
}
|
||||
public override int EV_SPE
|
||||
{
|
||||
get { return Math.Min(byte.MaxValue, BigEndian.ToUInt16(Data, 0xA6)); }
|
||||
set { BigEndian.GetBytes((ushort)(value & 0xFF)).CopyTo(Data, 0xA6); }
|
||||
}
|
||||
|
||||
// IVs
|
||||
public override int IV_HP { get { return Data[0xA8]; } set { Data[0xA8] = (byte)(value & 0x1F); } }
|
||||
public override int IV_ATK { get { return Data[0xA9]; } set { Data[0xA9] = (byte)(value & 0x1F); } }
|
||||
public override int IV_DEF { get { return Data[0xAA]; } set { Data[0xAA] = (byte)(value & 0x1F); } }
|
||||
public override int IV_SPA { get { return Data[0xAB]; } set { Data[0xAB] = (byte)(value & 0x1F); } }
|
||||
public override int IV_SPD { get { return Data[0xAC]; } set { Data[0xAC] = (byte)(value & 0x1F); } }
|
||||
public override int IV_SPE { get { return Data[0xAD]; } set { Data[0xAD] = (byte)(value & 0x1F); } }
|
||||
|
||||
// Contest
|
||||
public override int CNT_Cool { get { return Data[0xAE]; } set { Data[0xAE] = (byte)value; } }
|
||||
public override int CNT_Beauty { get { return Data[0xAF]; } set { Data[0xAF] = (byte)value; } }
|
||||
public override int CNT_Cute { get { return Data[0xB0]; } set { Data[0xB0] = (byte)value; } }
|
||||
public override int CNT_Smart { get { return Data[0xB1]; } set { Data[0xB1] = (byte)value; } }
|
||||
public override int CNT_Tough { get { return Data[0xB2]; } set { Data[0xB2] = (byte)value; } }
|
||||
public int RibbonCountG3Cool { get { return Data[0xB3]; } set { Data[0xB3] = (byte)value; } }
|
||||
public int RibbonCountG3Beauty { get { return Data[0xB4]; } set { Data[0xB4] = (byte)value; } }
|
||||
public int RibbonCountG3Cute { get { return Data[0xB5]; } set { Data[0xB5] = (byte)value; } }
|
||||
public int RibbonCountG3Smart { get { return Data[0xB6]; } set { Data[0xB6] = (byte)value; } }
|
||||
public int RibbonCountG3Tough { get { return Data[0xB7]; } set { Data[0xB7] = (byte)value; } }
|
||||
|
||||
public ushort ShadowID { get { return BigEndian.ToUInt16(Data, 0xBA); } set { BigEndian.GetBytes(value).CopyTo(Data, 0xBA); } }
|
||||
|
||||
// Purification information is stored in the save file and accessed based on the Shadow ID.
|
||||
|
||||
// Generated Attributes
|
||||
public override int PSV => (int)((PID >> 16 ^ PID & 0xFFFF) >> 3);
|
||||
public override int TSV => (TID ^ SID) >> 3;
|
||||
public bool Japanese => Language == 1;
|
||||
|
||||
public override byte[] Encrypt()
|
||||
{
|
||||
return (byte[])Data.Clone();
|
||||
}
|
||||
public override bool getGenderIsValid()
|
||||
{
|
||||
int gv = PersonalTable.RS[Species].Gender;
|
||||
|
||||
if (gv == 255)
|
||||
return Gender == 2;
|
||||
if (gv == 254)
|
||||
return Gender == 0;
|
||||
if (gv == 0)
|
||||
return Gender == 1;
|
||||
if (gv <= (PID & 0xFF))
|
||||
return Gender == 0;
|
||||
if ((PID & 0xFF) < gv)
|
||||
return Gender == 1;
|
||||
|
||||
return false;
|
||||
}
|
||||
public override bool CanHoldItem(ushort[] ValidArray)
|
||||
{
|
||||
return ValidArray.Contains((ushort)G3Item);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -63,7 +63,30 @@ namespace PKHeX
|
|||
BitConverter.GetBytes((ushort)((ushort)Items[i].Count ^ (ushort)SecurityKey)).CopyTo(Data, Offset + i*4 + 2);
|
||||
}
|
||||
}
|
||||
public void getPouchBigEndian(ref byte[] Data)
|
||||
{
|
||||
InventoryItem[] items = new InventoryItem[PouchDataSize];
|
||||
for (int i = 0; i < items.Length; i++)
|
||||
{
|
||||
items[i] = new InventoryItem
|
||||
{
|
||||
Index = BigEndian.ToUInt16(Data, Offset + i * 4),
|
||||
Count = BigEndian.ToUInt16(Data, Offset + i * 4 + 2) ^ (ushort)SecurityKey
|
||||
};
|
||||
}
|
||||
Items = items;
|
||||
}
|
||||
public void setPouchBigEndian(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++)
|
||||
{
|
||||
BigEndian.GetBytes((ushort)Items[i].Index).CopyTo(Data, Offset + i * 4);
|
||||
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];
|
||||
|
|
401
PKHeX/Saves/SAV3Colosseum.cs
Normal file
401
PKHeX/Saves/SAV3Colosseum.cs
Normal file
|
@ -0,0 +1,401 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace PKHeX
|
||||
{
|
||||
public sealed class SAV3Colosseum : SaveFile
|
||||
{
|
||||
public override string BAKName => $"{FileName} [{OT} ({Version}) - {PlayTimeString}].bak";
|
||||
public override string Filter => "GameCube Save File|*.gci";
|
||||
public override string Extension => ".gci";
|
||||
|
||||
// 3 Save files are stored
|
||||
// 0x0000-0x6000 contains memory card data
|
||||
// 0x6000-0x60000 contains the 3 save slots
|
||||
// 0x5A000 / 3 = 0x1E000 per save slot
|
||||
// Checksum is SHA1 over 0-0x1DFD7, stored in the last 20 bytes of the save slot.
|
||||
// Another SHA1 hash is 0x1DFD8, for 20 bytes. Unknown purpose.
|
||||
// Checksum is used as the crypto key.
|
||||
|
||||
private const int SLOT_SIZE = 0x1E000;
|
||||
private const int SLOT_START = 0x6000;
|
||||
private const int SLOT_COUNT = 3;
|
||||
|
||||
private readonly int SaveCount = -1;
|
||||
private readonly int SaveIndex = -1;
|
||||
private readonly ushort[] LegalItems, LegalKeyItems, LegalBalls, LegalTMHMs, LegalBerries, LegalCologne;
|
||||
private readonly int OFS_PouchCologne;
|
||||
public SAV3Colosseum(byte[] data = null)
|
||||
{
|
||||
Data = data == null ? new byte[SaveUtil.SIZE_G3BOX] : (byte[])data.Clone();
|
||||
BAK = (byte[])Data.Clone();
|
||||
Exportable = !Data.SequenceEqual(new byte[Data.Length]);
|
||||
|
||||
if (SaveUtil.getIsG3CXDSAV(Data) != GameVersion.COLO)
|
||||
return;
|
||||
|
||||
OriginalData = (byte[])Data.Clone();
|
||||
|
||||
// Scan all 3 save slots for the highest counter
|
||||
for (int i = 0; i < SLOT_COUNT; i++)
|
||||
{
|
||||
int slotOffset = SLOT_START + i * SLOT_SIZE;
|
||||
int SaveCounter = BigEndian.ToInt32(Data, slotOffset + 4);
|
||||
if (SaveCounter <= SaveCount)
|
||||
continue;
|
||||
|
||||
SaveCount = SaveCounter;
|
||||
SaveIndex = i;
|
||||
}
|
||||
|
||||
// Decrypt most recent save slot
|
||||
{
|
||||
byte[] slot = new byte[SLOT_SIZE];
|
||||
int slotOffset = SLOT_START + SaveIndex * SLOT_SIZE;
|
||||
Array.Copy(Data, slotOffset, slot, 0, slot.Length);
|
||||
byte[] digest = new byte[20];
|
||||
Array.Copy(slot, SLOT_SIZE - 20, digest, 0, digest.Length);
|
||||
|
||||
// Decrypt Slot
|
||||
Data = DecryptColosseum(slot, digest);
|
||||
}
|
||||
|
||||
Trainer1 = 0x00078;
|
||||
Party = 0x000A8;
|
||||
OFS_PouchHeldItem = 0x007F8;
|
||||
OFS_PouchKeyItem = 0x00848;
|
||||
OFS_PouchBalls = 0x0087C;
|
||||
OFS_PouchTMHM = 0x00934;
|
||||
OFS_PouchBerry = 0x009BC;
|
||||
OFS_PouchCologne = 0x00AEC; // Cologne
|
||||
|
||||
Box = 0x00B90;
|
||||
Daycare = 0x08170;
|
||||
|
||||
LegalItems = Legal.Pouch_Items_COLO;
|
||||
LegalKeyItems = Legal.Pouch_Key_COLO;
|
||||
LegalBalls = Legal.Pouch_Ball_RS;
|
||||
LegalTMHMs = Legal.Pouch_TM_RS; // not HMs
|
||||
LegalBerries = Legal.Pouch_Berries_RS;
|
||||
LegalCologne = Legal.Pouch_Cologne_CXD;
|
||||
|
||||
Personal = PersonalTable.RS;
|
||||
HeldItems = Legal.HeldItems_COLO;
|
||||
|
||||
if (!Exportable)
|
||||
resetBoxes();
|
||||
}
|
||||
|
||||
private readonly byte[] OriginalData;
|
||||
public override byte[] Write(bool DSV)
|
||||
{
|
||||
setChecksums();
|
||||
|
||||
// Get updated save slot data
|
||||
byte[] digest = Data.Skip(Data.Length - 20).Take(20).ToArray();
|
||||
byte[] newSAV = EncryptColosseum(Data, digest);
|
||||
|
||||
// Put save slot back in original save data
|
||||
byte[] newFile = (byte[])OriginalData.Clone();
|
||||
Array.Copy(newSAV, 0, newFile, SLOT_START + SaveIndex*SLOT_SIZE, newSAV.Length);
|
||||
return newFile;
|
||||
}
|
||||
|
||||
// Configuration
|
||||
public override SaveFile Clone() { return new SAV3Colosseum(Write(DSV: false)); }
|
||||
|
||||
public override int SIZE_STORED => PKX.SIZE_3CSTORED;
|
||||
public override int SIZE_PARTY => PKX.SIZE_3CSTORED; // unused
|
||||
public override PKM BlankPKM => new CK3();
|
||||
protected override Type PKMType => typeof(CK3);
|
||||
|
||||
public override int MaxMoveID => 354;
|
||||
public override int MaxSpeciesID => 386;
|
||||
public override int MaxAbilityID => 77;
|
||||
public override int MaxItemID => 374;
|
||||
public override int MaxBallID => 0xC;
|
||||
public override int MaxGameID => 5;
|
||||
|
||||
public override int MaxEV => 255;
|
||||
public override int Generation => 3;
|
||||
protected override int GiftCountMax => 1;
|
||||
public override int OTLength => 8;
|
||||
public override int NickLength => 10;
|
||||
public override int MaxMoney => 999999;
|
||||
|
||||
public override int BoxCount => 3;
|
||||
|
||||
// Checksums
|
||||
private readonly SHA1 sha1 = SHA1.Create();
|
||||
private byte[] EncryptColosseum(byte[] input, byte[] digest)
|
||||
{
|
||||
if (input.Length != SLOT_SIZE)
|
||||
return null;
|
||||
|
||||
byte[] d = (byte[])input.Clone();
|
||||
byte[] k = (byte[])digest.Clone(); // digest
|
||||
|
||||
// NOT key
|
||||
for (int i = 0; i < 20; i++)
|
||||
k[i] = (byte)~k[i];
|
||||
|
||||
for (int i = 0x18; i < 0x1DFD8; i += 20)
|
||||
{
|
||||
for (int j = 0; j < 20; j++)
|
||||
d[i + j] ^= k[j];
|
||||
k = sha1.ComputeHash(d, i, 20); // update digest
|
||||
}
|
||||
return d;
|
||||
}
|
||||
private byte[] DecryptColosseum(byte[] input, byte[] digest)
|
||||
{
|
||||
if (input.Length != SLOT_SIZE)
|
||||
return null;
|
||||
|
||||
byte[] d = (byte[])input.Clone();
|
||||
byte[] k = (byte[])digest.Clone();
|
||||
|
||||
// NOT key
|
||||
for (int i = 0; i < 20; i++)
|
||||
k[i] = (byte)~k[i];
|
||||
|
||||
for (int i = 0x18; i < 0x1DFD8; i += 20)
|
||||
{
|
||||
byte[] key = sha1.ComputeHash(d, i, 20); // update digest
|
||||
for (int j = 0; j < 20; j++)
|
||||
d[i + j] ^= k[j];
|
||||
Array.Copy(key, k, 20); // for use in next loop
|
||||
}
|
||||
return d;
|
||||
}
|
||||
protected override void setChecksums()
|
||||
{
|
||||
// Clear Header Checksum
|
||||
BitConverter.GetBytes(0).CopyTo(Data, 12);
|
||||
// Compute checksum of data
|
||||
byte[] checksum = sha1.ComputeHash(Data, 0, 0x1DFD8);
|
||||
// Set Checksum to end
|
||||
Array.Copy(checksum, 0, Data, Data.Length - 20, 20);
|
||||
|
||||
// Header Integrity
|
||||
byte[] H = new byte[8]; Array.Copy(checksum, 0, H, 0, 8);
|
||||
byte[] D = new byte[8]; Array.Copy(Data, 0x18, D, 0, 8);
|
||||
// Decrypt Checksum
|
||||
for (int i = 0; i < 8; i++)
|
||||
D[i] ^= (byte)~H[i];
|
||||
|
||||
// Compute new header checksum
|
||||
int newHC = 0;
|
||||
for (int i = 0; i < 0x18; i += 4)
|
||||
newHC -= BigEndian.ToInt32(Data, i);
|
||||
|
||||
newHC -= BigEndian.ToInt32(D, 0);
|
||||
newHC -= BigEndian.ToInt32(D, 4);
|
||||
|
||||
// Set Header Checksum
|
||||
BigEndian.GetBytes(newHC).CopyTo(Data, 12);
|
||||
}
|
||||
public override bool ChecksumsValid => !ChecksumInfo.Contains("Invalid");
|
||||
public override string ChecksumInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
byte[] data = (byte[])Data.Clone();
|
||||
int oldHC = BigEndian.ToInt32(data, 12);
|
||||
// Clear Header Checksum
|
||||
BitConverter.GetBytes(0).CopyTo(data, 12);
|
||||
byte[] checksum = sha1.ComputeHash(data, 0, 0x1DFD8);
|
||||
// Header Integrity
|
||||
byte[] H = new byte[8];
|
||||
byte[] D = new byte[8];
|
||||
|
||||
Array.Copy(checksum, 0, H, 0, H.Length);
|
||||
Array.Copy(data, 0x00018, D, 0, D.Length);
|
||||
for (int i = 0; i < 8; i++)
|
||||
D[i] ^= (byte)~H[i];
|
||||
|
||||
// Compute new header checksum
|
||||
int newHC = 0;
|
||||
for (int i = 0; i < 0x18; i += 4)
|
||||
newHC -= BigEndian.ToInt32(data, i);
|
||||
|
||||
newHC -= BigEndian.ToInt32(D, 0);
|
||||
newHC -= BigEndian.ToInt32(D, 4);
|
||||
|
||||
byte[] chk = data.Skip(data.Length - 20).Take(20).ToArray();
|
||||
|
||||
bool header = newHC == oldHC;
|
||||
bool body = chk.SequenceEqual(checksum);
|
||||
return $"Header Checksum {(header ? "V" : "Inv")}alid, Body Checksum {(body ? "V" : "Inv")}alid.";
|
||||
}
|
||||
}
|
||||
|
||||
// Trainer Info
|
||||
public override GameVersion Version { get { return GameVersion.COLO; } protected set { } }
|
||||
|
||||
// Storage
|
||||
public override int getPartyOffset(int slot)
|
||||
{
|
||||
return Party + SIZE_STORED * slot;
|
||||
}
|
||||
public override int getBoxOffset(int box)
|
||||
{
|
||||
return Box + (30 * SIZE_STORED + 0x14)*box + 0x14;
|
||||
}
|
||||
public override int CurrentBox { get { return 0; } set { } }
|
||||
public override int getBoxWallpaper(int box)
|
||||
{
|
||||
return box;
|
||||
}
|
||||
public override string getBoxName(int box)
|
||||
{
|
||||
return PKX.getColoStr(Data, Box + 0x24A4*box, 8);
|
||||
}
|
||||
public override void setBoxName(int box, string value)
|
||||
{
|
||||
if (value.Length > 8)
|
||||
value = value.Substring(0, 8); // Hard cap
|
||||
PKX.setColoStr(value, 8).CopyTo(Data, Box + 0x24A4*box);
|
||||
}
|
||||
public override PKM getPKM(byte[] data)
|
||||
{
|
||||
return new CK3(data.Take(SIZE_STORED).ToArray());
|
||||
}
|
||||
public override byte[] decryptPKM(byte[] data)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
protected override void setDex(PKM pkm) { }
|
||||
|
||||
private TimeSpan PlayedSpan
|
||||
{
|
||||
get { return TimeSpan.FromSeconds((double)(Util.SwapEndianness(BitConverter.ToUInt32(Data, 40)) - 0x47000000) / 128); }
|
||||
set { BitConverter.GetBytes(Util.SwapEndianness((uint)(value.TotalSeconds * 128) + 0x47000000)).CopyTo(Data, 40); }
|
||||
}
|
||||
public override int PlayedHours
|
||||
{
|
||||
get { return (ushort)PlayedSpan.Hours; }
|
||||
set { var time = PlayedSpan; PlayedSpan = time - TimeSpan.FromHours(time.Hours) + TimeSpan.FromHours(value); }
|
||||
}
|
||||
public override int PlayedMinutes
|
||||
{
|
||||
get { return (byte)PlayedSpan.Minutes; }
|
||||
set { var time = PlayedSpan; PlayedSpan = time - TimeSpan.FromMinutes(time.Minutes) + TimeSpan.FromMinutes(value); }
|
||||
}
|
||||
public override int PlayedSeconds
|
||||
{
|
||||
get { return (byte)PlayedSpan.Seconds; }
|
||||
set { var time = PlayedSpan; PlayedSpan = time - TimeSpan.FromSeconds(time.Seconds) + TimeSpan.FromSeconds(value); }
|
||||
}
|
||||
|
||||
// Trainer Info (offset 0x78, length 0xB18, end @ 0xB90)
|
||||
public override string OT { get { return PKX.getColoStr(Data, 0x78, 10); } set { PKX.setColoStr(value, 10).CopyTo(Data, 0x78); } }
|
||||
private string OT2 { get { return PKX.getColoStr(Data, 0x8C, 10); } set { PKX.setColoStr(value, 10).CopyTo(Data, 0x8C); OT = value; } }
|
||||
public override ushort SID { get { return BigEndian.ToUInt16(Data, 0xA4); } set { BigEndian.GetBytes(value).CopyTo(Data, 0xA4); } }
|
||||
public override ushort TID { get { return BigEndian.ToUInt16(Data, 0xA6); } set { BigEndian.GetBytes(value).CopyTo(Data, 0xA6); } }
|
||||
|
||||
public override int Gender { get { return Data[0xAF8]; } set { Data[0xAF8] = (byte)value; } }
|
||||
public override uint Money { get { return BigEndian.ToUInt32(Data, 0xAFC); } set { BigEndian.GetBytes(value).CopyTo(Data, 0xAFC); } }
|
||||
public uint Coupons { get { return BigEndian.ToUInt32(Data, 0xB00); } set { BigEndian.GetBytes(value).CopyTo(Data, 0xB00); } }
|
||||
public string RUI_Name { get { return PKX.getColoStr(Data, 0xB3A, 10); } set { PKX.setColoStr(value, 10).CopyTo(Data, 0xB3A); } }
|
||||
|
||||
public override InventoryPouch[] Inventory
|
||||
{
|
||||
get
|
||||
{
|
||||
InventoryPouch[] pouch =
|
||||
{
|
||||
new InventoryPouch(InventoryType.Items, LegalItems, 995, OFS_PouchHeldItem, 20), // 20 COLO, 30 XD
|
||||
new InventoryPouch(InventoryType.KeyItems, LegalKeyItems, 1, OFS_PouchKeyItem, 43),
|
||||
new InventoryPouch(InventoryType.TMHMs, LegalBalls, 995, OFS_PouchTMHM, 16),
|
||||
new InventoryPouch(InventoryType.TMHMs, LegalTMHMs, 995, OFS_PouchTMHM, 64),
|
||||
new InventoryPouch(InventoryType.Berries, LegalBerries, 995, OFS_PouchBerry, 46),
|
||||
new InventoryPouch(InventoryType.Medicine, LegalCologne, 995, OFS_PouchCologne, 3), // Cologne
|
||||
};
|
||||
foreach (var p in pouch)
|
||||
p.getPouchBigEndian(ref Data);
|
||||
return pouch;
|
||||
}
|
||||
set
|
||||
{
|
||||
foreach (var p in value)
|
||||
p.setPouchBigEndian(ref Data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Daycare Structure:
|
||||
// 0x00 -- Occupied
|
||||
// 0x01 -- Deposited Level
|
||||
// 0x02-0x03 -- unused?
|
||||
// 0x04-0x07 -- Initial EXP
|
||||
public override int getDaycareSlotOffset(int loc, int slot) { return Daycare + 8; }
|
||||
public override ulong? getDaycareRNGSeed(int loc) { return null; }
|
||||
public override uint? getDaycareEXP(int loc, int slot) { return null; }
|
||||
public override bool? getDaycareOccupied(int loc, int slot) { return null; }
|
||||
public override void setDaycareEXP(int loc, int slot, uint EXP) { }
|
||||
public override void setDaycareOccupied(int loc, int slot, bool occupied) { }
|
||||
}
|
||||
internal static class BigEndian
|
||||
{
|
||||
internal static uint ToUInt32(byte[] data, int offset)
|
||||
{
|
||||
int val = 0;
|
||||
val |= data[offset + 0] << 24;
|
||||
val |= data[offset + 1] << 16;
|
||||
val |= data[offset + 2] << 8;
|
||||
val |= data[offset + 3] << 0;
|
||||
return (uint)val;
|
||||
}
|
||||
internal static ushort ToUInt16(byte[] data, int offset)
|
||||
{
|
||||
int val = 0;
|
||||
val |= data[offset + 0] << 8;
|
||||
val |= data[offset + 1] << 0;
|
||||
return (ushort)val;
|
||||
}
|
||||
internal static int ToInt32(byte[] data, int offset)
|
||||
{
|
||||
int val = 0;
|
||||
val |= data[offset + 0] << 24;
|
||||
val |= data[offset + 1] << 16;
|
||||
val |= data[offset + 2] << 8;
|
||||
val |= data[offset + 3] << 0;
|
||||
return val;
|
||||
}
|
||||
internal static short ToInt16(byte[] data, int offset)
|
||||
{
|
||||
int val = 0;
|
||||
val |= data[offset + 0] << 8;
|
||||
val |= data[offset + 1] << 0;
|
||||
return (short)val;
|
||||
}
|
||||
internal static byte[] GetBytes(int value)
|
||||
{
|
||||
return Invert(BitConverter.GetBytes(value));
|
||||
}
|
||||
internal static byte[] GetBytes(short value)
|
||||
{
|
||||
return Invert(BitConverter.GetBytes(value));
|
||||
}
|
||||
internal static byte[] GetBytes(uint value)
|
||||
{
|
||||
return Invert(BitConverter.GetBytes(value));
|
||||
}
|
||||
internal static byte[] GetBytes(ushort value)
|
||||
{
|
||||
return Invert(BitConverter.GetBytes(value));
|
||||
}
|
||||
private static byte[] Invert(byte[] data)
|
||||
{
|
||||
byte[] result = new byte[data.Length];
|
||||
int o = 0;
|
||||
int i = data.Length;
|
||||
while (o != data.Length)
|
||||
result[--i] = data[o++];
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
187
PKHeX/Saves/SAV3XD.cs
Normal file
187
PKHeX/Saves/SAV3XD.cs
Normal file
|
@ -0,0 +1,187 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX
|
||||
{
|
||||
public sealed class SAV3XD : SaveFile
|
||||
{
|
||||
public override string BAKName => $"{FileName} [{Version} #{SaveCount.ToString("0000")}].bak";
|
||||
public override string Filter => "GameCube Save File|*.gci";
|
||||
public override string Extension => ".gci";
|
||||
|
||||
private const int SLOT_SIZE = 0x1E000;
|
||||
private const int SLOT_START = 0x6000;
|
||||
private const int SLOT_COUNT = 3;
|
||||
|
||||
private readonly int SaveCount = -1;
|
||||
private readonly int SaveIndex = -1;
|
||||
private readonly ushort[] LegalItems, LegalKeyItems, LegalBalls, LegalTMHMs, LegalBerries, LegalCologne, LegalDisc;
|
||||
private readonly int OFS_PouchCologne, OFS_PouchDisc;
|
||||
public SAV3XD(byte[] data = null)
|
||||
{
|
||||
Data = data == null ? new byte[SaveUtil.SIZE_G3BOX] : (byte[])data.Clone();
|
||||
BAK = (byte[])Data.Clone();
|
||||
Exportable = !Data.SequenceEqual(new byte[Data.Length]);
|
||||
|
||||
if (SaveUtil.getIsG3CXDSAV(Data) != GameVersion.XD)
|
||||
return;
|
||||
|
||||
OriginalData = (byte[])Data.Clone();
|
||||
|
||||
// Scan all 3 save slots for the highest counter
|
||||
for (int i = 0; i < SLOT_COUNT; i++)
|
||||
{
|
||||
int slotOffset = SLOT_START + i * SLOT_SIZE;
|
||||
int SaveCounter = BigEndian.ToInt32(Data, slotOffset + 4);
|
||||
if (SaveCounter <= SaveCount)
|
||||
continue;
|
||||
|
||||
SaveCount = SaveCounter;
|
||||
SaveIndex = i;
|
||||
}
|
||||
|
||||
// Decrypt most recent save slot
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
OFS_PouchHeldItem = 1224;
|
||||
OFS_PouchKeyItem = 1344;
|
||||
OFS_PouchBalls = 1516;
|
||||
OFS_PouchTMHM = 1580;
|
||||
OFS_PouchBerry = 1836;
|
||||
OFS_PouchCologne = 2020;
|
||||
OFS_PouchDisc = 2032;
|
||||
|
||||
LegalItems = Legal.Pouch_Items_XD;
|
||||
LegalKeyItems = Legal.Pouch_Key_XD;
|
||||
LegalBalls = Legal.Pouch_Ball_RS;
|
||||
LegalTMHMs = Legal.Pouch_TM_RS; // not HMs
|
||||
LegalBerries = Legal.Pouch_Berries_RS;
|
||||
LegalCologne = Legal.Pouch_Cologne_CXD;
|
||||
LegalDisc = Legal.Pouch_Disc_XD;
|
||||
|
||||
Personal = PersonalTable.RS;
|
||||
HeldItems = Legal.HeldItems_XD;
|
||||
|
||||
if (!Exportable)
|
||||
resetBoxes();
|
||||
}
|
||||
|
||||
private readonly byte[] OriginalData;
|
||||
public override byte[] Write(bool DSV)
|
||||
{
|
||||
setChecksums();
|
||||
|
||||
// Get updated save slot data
|
||||
byte[] newSAV = null;
|
||||
|
||||
// Put save slot back in original save data
|
||||
byte[] newFile = (byte[])OriginalData.Clone();
|
||||
Array.Copy(newSAV, 0, newFile, SLOT_START + SaveIndex * SLOT_SIZE, newSAV.Length);
|
||||
return newFile;
|
||||
}
|
||||
|
||||
// Configuration
|
||||
public override SaveFile Clone() { return new SAV3(Write(DSV: false), Version); }
|
||||
|
||||
public override int SIZE_STORED => PKX.SIZE_3XSTORED;
|
||||
public override int SIZE_PARTY => PKX.SIZE_3XSTORED; // unused
|
||||
public override PKM BlankPKM => new XK3();
|
||||
protected override Type PKMType => typeof(XK3);
|
||||
|
||||
public override int MaxMoveID => 354;
|
||||
public override int MaxSpeciesID => 386;
|
||||
public override int MaxAbilityID => 77;
|
||||
public override int MaxItemID => 374;
|
||||
public override int MaxBallID => 0xC;
|
||||
public override int MaxGameID => 5;
|
||||
|
||||
public override int MaxEV => 255;
|
||||
public override int Generation => 3;
|
||||
protected override int GiftCountMax => 1;
|
||||
public override int OTLength => 8;
|
||||
public override int NickLength => 10;
|
||||
public override int MaxMoney => 999999;
|
||||
|
||||
public override int BoxCount => 8;
|
||||
public override bool HasParty => false;
|
||||
|
||||
// Checksums
|
||||
protected override void setChecksums()
|
||||
{
|
||||
|
||||
}
|
||||
public override bool ChecksumsValid
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
public override string ChecksumInfo
|
||||
{
|
||||
get { return ""; }
|
||||
}
|
||||
|
||||
// Trainer Info
|
||||
public override GameVersion Version { get { return GameVersion.RSBOX; } protected set { } }
|
||||
|
||||
// Storage
|
||||
public override int getPartyOffset(int slot)
|
||||
{
|
||||
return Party + SIZE_STORED * slot;
|
||||
}
|
||||
public override int getBoxOffset(int box)
|
||||
{
|
||||
return Box + (30 * SIZE_STORED + 0x14)*box + 0x14;
|
||||
}
|
||||
public override int CurrentBox { get { return 0; } set { } }
|
||||
public override int getBoxWallpaper(int box)
|
||||
{
|
||||
return box;
|
||||
}
|
||||
public override string getBoxName(int box)
|
||||
{
|
||||
return PKX.getColoStr(Data, Box + 0x24A4*box, 8);
|
||||
}
|
||||
public override void setBoxName(int box, string value)
|
||||
{
|
||||
if (value.Length > 8)
|
||||
value = value.Substring(0, 8); // Hard cap
|
||||
PKX.setColoStr(value, 8).CopyTo(Data, Box + 0x24A4*box);
|
||||
}
|
||||
public override PKM getPKM(byte[] data)
|
||||
{
|
||||
return new XK3(data.Take(SIZE_STORED).ToArray());
|
||||
}
|
||||
public override byte[] decryptPKM(byte[] data)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
protected override void setDex(PKM pkm) { }
|
||||
|
||||
public override InventoryPouch[] Inventory
|
||||
{
|
||||
get
|
||||
{
|
||||
InventoryPouch[] pouch =
|
||||
{
|
||||
new InventoryPouch(InventoryType.Items, LegalItems, 995, OFS_PouchHeldItem, 30), // 20 COLO, 30 XD
|
||||
new InventoryPouch(InventoryType.KeyItems, LegalKeyItems, 1, OFS_PouchKeyItem, 43),
|
||||
new InventoryPouch(InventoryType.TMHMs, LegalBalls, 995, OFS_PouchTMHM, 16),
|
||||
new InventoryPouch(InventoryType.TMHMs, LegalTMHMs, 995, OFS_PouchTMHM, 64),
|
||||
new InventoryPouch(InventoryType.Berries, LegalBerries, 995, OFS_PouchBerry, 46),
|
||||
new InventoryPouch(InventoryType.Medicine, LegalCologne, 995, OFS_PouchCologne, 3), // Cologne
|
||||
new InventoryPouch(InventoryType.Medicine, LegalDisc, 995, OFS_PouchDisc, 60), // Cologne
|
||||
};
|
||||
foreach (var p in pouch)
|
||||
p.getPouchBigEndian(ref Data);
|
||||
return pouch;
|
||||
}
|
||||
set
|
||||
{
|
||||
foreach (var p in value)
|
||||
p.setPouchBigEndian(ref Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,6 +9,8 @@ namespace PKHeX
|
|||
public enum GameVersion
|
||||
{
|
||||
/* I don't want to assign Gen I/II... */
|
||||
XD = -7,
|
||||
COLO = -6,
|
||||
RSBOX = -5,
|
||||
GS = -4,
|
||||
C = -3,
|
||||
|
@ -49,6 +51,10 @@ namespace PKHeX
|
|||
internal const int SIZE_G4RAW = 0x80000;
|
||||
internal const int SIZE_G3BOX = 0x76000;
|
||||
internal const int SIZE_G3BOXGCI = 0x76040; // +64 if has GCI data
|
||||
internal const int SIZE_G3COLO = 0x60000;
|
||||
internal const int SIZE_G3COLOGCI = 0x60040; // +64 if has GCI data
|
||||
internal const int SIZE_G3XD = 0x56000;
|
||||
internal const int SIZE_G3XDGCI = 0x56040; // +64 if has GCI data
|
||||
internal const int SIZE_G3RAW = 0x20000;
|
||||
internal const int SIZE_G3RAWHALF = 0x10000;
|
||||
internal const int SIZE_G2RAW_U = 0x8000;
|
||||
|
@ -60,7 +66,9 @@ namespace PKHeX
|
|||
internal const int SIZE_G1BAT = 0x802C;
|
||||
|
||||
internal static readonly byte[] FOOTER_DSV = Encoding.ASCII.GetBytes("|-DESMUME SAVE-|");
|
||||
internal static readonly byte[] HEADER_GCI = {0x47, 0x50, 0x58}; // GPX*
|
||||
internal static readonly byte[] HEADER_BOX = Encoding.ASCII.GetBytes("GPX");
|
||||
internal static readonly byte[] HEADER_COLO = Encoding.ASCII.GetBytes("GC6");
|
||||
internal static readonly byte[] HEADER_XD = Encoding.ASCII.GetBytes("GXX");
|
||||
|
||||
/// <summary>Determines the generation of the given save data.</summary>
|
||||
/// <param name="data">Save data of which to determine the generation</param>
|
||||
|
@ -73,6 +81,8 @@ namespace PKHeX
|
|||
return 2;
|
||||
if (getIsG3SAV(data) != GameVersion.Invalid)
|
||||
return 3;
|
||||
if (getIsG3CXDSAV(data) != GameVersion.Invalid)
|
||||
return (int)GameVersion.COLO;
|
||||
if (getIsG3BOXSAV(data) != GameVersion.Invalid)
|
||||
return (int)GameVersion.RSBOX;
|
||||
if (getIsG4SAV(data) != GameVersion.Invalid)
|
||||
|
@ -244,6 +254,32 @@ namespace PKHeX
|
|||
|
||||
return CHK_A == chkA && CHK_B == chkB ? GameVersion.RSBOX : GameVersion.Invalid;
|
||||
}
|
||||
/// <summary>Determines the type of 3rd gen Colosseum</summary>
|
||||
/// <param name="data">Save data of which to determine the type</param>
|
||||
/// <returns>Version Identifier or Invalid if type cannot be determined.</returns>
|
||||
public static GameVersion getIsG3CXDSAV(byte[] data)
|
||||
{
|
||||
if (!new[] { SIZE_G3COLO, SIZE_G3COLOGCI }.Contains(data.Length))
|
||||
return GameVersion.Invalid;
|
||||
|
||||
// Check the intro bytes for each save slot
|
||||
byte[] slotintroColo = {0x01, 0x01, 0x00, 0x00};
|
||||
byte[] slotintroXD = {0x01, 0x01, 0x01, 0x00};
|
||||
int offset = data.Length - SIZE_G3COLO;
|
||||
int coloct = 0;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
var ident = data.Skip(0x6000 + offset + 0x1E000*i).Take(4).ToArray();
|
||||
if (ident.SequenceEqual(slotintroColo))
|
||||
{
|
||||
coloct++;
|
||||
continue;
|
||||
}
|
||||
if (!ident.SequenceEqual(slotintroXD))
|
||||
return GameVersion.Invalid;
|
||||
}
|
||||
return coloct == 3 ? GameVersion.COLO : GameVersion.XD;
|
||||
}
|
||||
/// <summary>Determines the type of 4th gen save</summary>
|
||||
/// <param name="data">Save data of which to determine the type</param>
|
||||
/// <returns>Version Identifier or Invalid if type cannot be determined.</returns>
|
||||
|
@ -394,6 +430,10 @@ namespace PKHeX
|
|||
return new SAV3(data);
|
||||
case (int)GameVersion.RSBOX:
|
||||
return new SAV3RSBox(data);
|
||||
case (int)GameVersion.COLO:
|
||||
return new SAV3Colosseum(data);
|
||||
case (int)GameVersion.XD:
|
||||
return new SAV3XD(data);
|
||||
case 4:
|
||||
return new SAV4(data);
|
||||
case 5:
|
||||
|
@ -525,13 +565,31 @@ namespace PKHeX
|
|||
}
|
||||
if (input.Length == SIZE_G3BOXGCI)
|
||||
{
|
||||
bool gci = HEADER_GCI.SequenceEqual(input.Take(HEADER_GCI.Length));
|
||||
bool gci = HEADER_BOX.SequenceEqual(input.Take(HEADER_BOX.Length));
|
||||
if (gci)
|
||||
{
|
||||
header = input.Take(SIZE_G3BOXGCI - SIZE_G3BOX).ToArray();
|
||||
input = input.Skip(header.Length).ToArray();
|
||||
}
|
||||
}
|
||||
if (input.Length == SIZE_G3COLOGCI)
|
||||
{
|
||||
bool gci = HEADER_COLO.SequenceEqual(input.Take(HEADER_COLO.Length));
|
||||
if (gci)
|
||||
{
|
||||
header = input.Take(SIZE_G3COLOGCI - SIZE_G3COLO).ToArray();
|
||||
input = input.Skip(header.Length).ToArray();
|
||||
}
|
||||
}
|
||||
if (input.Length == SIZE_G3XDGCI)
|
||||
{
|
||||
bool gci = HEADER_XD.SequenceEqual(input.Take(HEADER_XD.Length));
|
||||
if (gci)
|
||||
{
|
||||
header = input.Take(SIZE_G3XDGCI - SIZE_G3XD).ToArray();
|
||||
input = input.Skip(header.Length).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int getDexFormIndexBW(int species, int formct)
|
||||
|
@ -652,5 +710,32 @@ namespace PKHeX
|
|||
default: return getDexFormIndexXY(species, formct);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getCXDVersionID(int gen3version)
|
||||
{
|
||||
switch ((GameVersion)gen3version)
|
||||
{
|
||||
case GameVersion.FR: return 1;
|
||||
case GameVersion.LG: return 2;
|
||||
case GameVersion.S: return 8;
|
||||
case GameVersion.R: return 9;
|
||||
case GameVersion.E: return 10;
|
||||
case GameVersion.CXD: return 11;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
public static int getG3VersionID(int CXDversion)
|
||||
{
|
||||
switch (CXDversion)
|
||||
{
|
||||
case 1: return (int)GameVersion.FR;
|
||||
case 2: return (int)GameVersion.LG;
|
||||
case 8: return (int)GameVersion.S;
|
||||
case 9: return (int)GameVersion.R;
|
||||
case 10: return (int)GameVersion.E;
|
||||
case 11: return (int)GameVersion.CXD;
|
||||
default: return (int)GameVersion.Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue