mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-27 06:20:25 +00:00
Initial (pretty broken) US SAV2 loading/viewing
This commit is contained in:
parent
c0750647f6
commit
2e938a6ab2
17 changed files with 1342 additions and 24 deletions
|
@ -169,7 +169,7 @@ namespace PKHeX
|
|||
public static string[] gendersymbols = { "♂", "♀", "-" };
|
||||
public static string[] specieslist, movelist, itemlist, abilitylist, types, natures, forms,
|
||||
memories, genloc, trainingbags, trainingstage, characteristics,
|
||||
encountertypelist, gamelanguages, balllist, gamelist, pokeblocks, g3items, g1items = { };
|
||||
encountertypelist, gamelanguages, balllist, gamelist, pokeblocks, g3items, g2items, g1items = { };
|
||||
public static string[] metGSC_00000, metRSEFRLG_00000 = { };
|
||||
public static string[] metHGSS_00000, metHGSS_02000, metHGSS_03000 = { };
|
||||
public static string[] metBW2_00000, metBW2_30000, metBW2_40000, metBW2_60000 = { };
|
||||
|
@ -874,9 +874,10 @@ namespace PKHeX
|
|||
GB_Markings.Visible = SAV.Generation > 2;
|
||||
|
||||
Label_HeldItem.Visible = CB_HeldItem.Visible = SAV.Generation > 1;
|
||||
Label_Total.Visible = TB_IVTotal.Visible = TB_EVTotal.Visible = L_Potential.Visible =
|
||||
Label_HiddenPowerPrefix.Visible = CB_HPType.Visible = SAV.Generation > 1;
|
||||
Label_CharacteristicPrefix.Visible = L_Characteristic.Visible = SAV.Generation > 1;
|
||||
Label_Total.Visible = TB_IVTotal.Visible = TB_EVTotal.Visible = L_Potential.Visible = SAV.Generation > 2;
|
||||
Label_HiddenPowerPrefix.Visible = CB_HPType.Visible = SAV.Generation > 1;
|
||||
CB_HPType.Enabled = SAV.Generation > 2;
|
||||
Label_CharacteristicPrefix.Visible = L_Characteristic.Visible = SAV.Generation > 2;
|
||||
Label_ContestStats.Visible = Label_Cool.Visible = Label_Tough.Visible = Label_Smart.Visible =
|
||||
Label_Sheen.Visible = Label_Beauty.Visible = Label_Cute.Visible = TB_Cool.Visible = TB_Tough.Visible =
|
||||
TB_Smart.Visible = TB_Sheen.Visible = TB_Beauty.Visible = TB_Cute.Visible = Label_Nature.Visible =
|
||||
|
@ -941,6 +942,11 @@ namespace PKHeX
|
|||
getPKMfromFields = preparePK1;
|
||||
extraBytes = new byte[] {};
|
||||
break;
|
||||
case 2:
|
||||
getFieldsfromPKM = populateFieldsPK2;
|
||||
getPKMfromFields = preparePK2;
|
||||
extraBytes = new byte[] { };
|
||||
break;
|
||||
case 3:
|
||||
getFieldsfromPKM = populateFieldsPK3;
|
||||
getPKMfromFields = preparePK3;
|
||||
|
@ -970,7 +976,7 @@ namespace PKHeX
|
|||
bool init = fieldsInitialized;
|
||||
fieldsInitialized = false;
|
||||
populateFilteredDataSources();
|
||||
populateFields((pkm.Format != SAV.Generation || SAV.Generation == 1) ? SAV.BlankPKM : pk);
|
||||
populateFields((pkm.Format != SAV.Generation || SAV.Generation < 3) ? SAV.BlankPKM : pk);
|
||||
fieldsInitialized |= init;
|
||||
|
||||
// SAV Specific Limits
|
||||
|
@ -1046,6 +1052,7 @@ namespace PKHeX
|
|||
|
||||
// Past Generation strings
|
||||
g3items = Util.getStringList("ItemsG3", "en");
|
||||
g2items = Util.getStringList("ItemsG2", "en");
|
||||
g1items = Util.getStringList("ItemsG1", "en");
|
||||
metRSEFRLG_00000 = Util.getStringList("rsefrlg_00000", "en");
|
||||
metGSC_00000 = Util.getStringList("gsc_00000", "en");
|
||||
|
@ -1271,6 +1278,8 @@ namespace PKHeX
|
|||
string[] items = itemlist;
|
||||
if (SAV.Generation == 3)
|
||||
items = g3items;
|
||||
if (SAV.Generation == 2)
|
||||
items = g2items;
|
||||
|
||||
ItemDataSource = Util.getCBList(items, (HaX ? Enumerable.Range(0, SAV.MaxItemID) : SAV.HeldItems.Select(i => (int)i)).ToArray());
|
||||
CB_HeldItem.DataSource = new BindingSource(ItemDataSource.Where(i => i.Value <= SAV.MaxItemID).ToList(), null);
|
||||
|
@ -1410,7 +1419,7 @@ namespace PKHeX
|
|||
bool isShiny = pkm.IsShiny;
|
||||
|
||||
// Set the Controls
|
||||
BTN_Shinytize.Visible = BTN_Shinytize.Enabled = !isShiny && SAV.Generation > 2;
|
||||
BTN_Shinytize.Visible = BTN_Shinytize.Enabled = !isShiny && SAV.Generation > 1;
|
||||
Label_IsShiny.Visible = isShiny && SAV.Generation > 1;
|
||||
|
||||
// Refresh Markings (for Shiny Star if applicable)
|
||||
|
@ -1707,6 +1716,16 @@ namespace PKHeX
|
|||
if (SAV.Generation < 3)
|
||||
{
|
||||
TB_HPIV.Text = pkm.IV_HP.ToString("00");
|
||||
if (SAV.Generation == 2)
|
||||
{
|
||||
Label_Gender.Text = gendersymbols[pkm.Gender];
|
||||
Label_Gender.ForeColor = pkm.Gender == 2
|
||||
? Label_Species.ForeColor
|
||||
: (pkm.Gender == 1 ? Color.Red : Color.Blue);
|
||||
CB_Form.SelectedIndex = pkm.AltForm;
|
||||
setIsShiny(null);
|
||||
getQuickFiller(dragout);
|
||||
}
|
||||
}
|
||||
|
||||
CB_HPType.SelectedValue = pkm.HPType;
|
||||
|
@ -2260,6 +2279,8 @@ namespace PKHeX
|
|||
{
|
||||
CHK_Nicknamed.Checked = false;
|
||||
TB_Friendship.Text = "1";
|
||||
if (SAV.Generation == 2)
|
||||
pkm.IsEgg = true;
|
||||
|
||||
// If we are an egg, it won't have a met location.
|
||||
CHK_AsEgg.Checked = true;
|
||||
|
@ -2273,6 +2294,9 @@ namespace PKHeX
|
|||
if (!CHK_Nicknamed.Checked)
|
||||
updateNickname(null, null);
|
||||
|
||||
if (SAV.Generation == 2)
|
||||
pkm.IsEgg = false;
|
||||
|
||||
TB_Friendship.Text = SAV.Personal[Util.getIndex(CB_Species)].BaseFriendship.ToString();
|
||||
|
||||
if (CB_EggLocation.SelectedIndex == 0)
|
||||
|
@ -2284,7 +2308,7 @@ namespace PKHeX
|
|||
}
|
||||
// Display hatch counter if it is an egg, Display Friendship if it is not.
|
||||
Label_HatchCounter.Visible = CHK_IsEgg.Checked && SAV.Generation > 1;
|
||||
Label_Friendship.Visible = !CHK_IsEgg.Checked && SAV.Generation > 2;
|
||||
Label_Friendship.Visible = !CHK_IsEgg.Checked && SAV.Generation > 1;
|
||||
|
||||
|
||||
// Update image to (not) show egg.
|
||||
|
@ -2313,7 +2337,16 @@ namespace PKHeX
|
|||
pkm.AltForm = CB_Form.SelectedIndex;
|
||||
pkm.Version = Util.getIndex(CB_GameOrigin);
|
||||
|
||||
pkm.setShinyPID();
|
||||
if (pkm.Format > 2)
|
||||
pkm.setShinyPID();
|
||||
else
|
||||
{
|
||||
TB_ATKIV.Text = "15";
|
||||
TB_DEFIV.Text = "10";
|
||||
TB_SPEIV.Text = "10";
|
||||
TB_SPAIV.Text = "10";
|
||||
updateIVs(null, null);
|
||||
}
|
||||
TB_PID.Text = pkm.PID.ToString("X8");
|
||||
|
||||
if (pkm.GenNumber < 6 && TB_EC.Visible)
|
||||
|
@ -3454,7 +3487,7 @@ namespace PKHeX
|
|||
new SAV_PokedexORAS().ShowDialog();
|
||||
else if (SAV.XY)
|
||||
new SAV_PokedexXY().ShowDialog();
|
||||
else if (SAV.RBY)
|
||||
else if (SAV.RBY || SAV.GSC)
|
||||
new SAV_SimplePokedex().ShowDialog();
|
||||
}
|
||||
private void B_OUTPasserby_Click(object sender, EventArgs e)
|
||||
|
|
133
PKHeX/MainWindow/MainPK2.cs
Normal file
133
PKHeX/MainWindow/MainPK2.cs
Normal file
|
@ -0,0 +1,133 @@
|
|||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace PKHeX
|
||||
{
|
||||
public partial class Main
|
||||
{
|
||||
private void populateFieldsPK2()
|
||||
{
|
||||
PK2 pk2 = pkm as PK2;
|
||||
if (pk2 == null)
|
||||
return;
|
||||
|
||||
// Do first
|
||||
pk2.Stat_Level = PKX.getLevel(pk2.Species, pk2.EXP);
|
||||
if (pk2.Stat_Level == 100)
|
||||
pk2.EXP = PKX.getEXP(pk2.Stat_Level, pk2.Species);
|
||||
|
||||
CB_Species.SelectedValue = pk2.Species;
|
||||
TB_Level.Text = pk2.Stat_Level.ToString();
|
||||
TB_EXP.Text = pk2.EXP.ToString();
|
||||
CB_HeldItem.SelectedValue = pk2.HeldItem;
|
||||
CB_Form.SelectedIndex = pk2.AltForm;
|
||||
CHK_IsEgg.Checked = pk2.IsEgg;
|
||||
|
||||
// Load rest
|
||||
TB_TID.Text = pk2.TID.ToString("00000");
|
||||
CHK_Nicknamed.Checked = pk2.IsNicknamed;
|
||||
TB_Nickname.Text = pk2.Nickname;
|
||||
TB_OT.Text = pk2.OT_Name;
|
||||
GB_OT.BackgroundImage = null;
|
||||
|
||||
// Reset Label and ComboBox visibility, as well as non-data checked status.
|
||||
Label_PKRS.Visible = false;
|
||||
Label_PKRSdays.Visible = false;
|
||||
|
||||
TB_HPIV.Text = pk2.IV_HP.ToString();
|
||||
TB_ATKIV.Text = pk2.IV_ATK.ToString();
|
||||
TB_DEFIV.Text = pk2.IV_DEF.ToString();
|
||||
TB_SPEIV.Text = pk2.IV_SPE.ToString();
|
||||
TB_SPAIV.Text = pk2.IV_SPA.ToString();
|
||||
|
||||
TB_HPEV.Text = pk2.EV_HP.ToString();
|
||||
TB_ATKEV.Text = pk2.EV_ATK.ToString();
|
||||
TB_DEFEV.Text = pk2.EV_DEF.ToString();
|
||||
TB_SPEEV.Text = pk2.EV_SPE.ToString();
|
||||
TB_SPAEV.Text = pk2.EV_SPA.ToString();
|
||||
|
||||
CB_Move1.SelectedValue = pk2.Move1;
|
||||
CB_Move2.SelectedValue = pk2.Move2;
|
||||
CB_Move3.SelectedValue = pk2.Move3;
|
||||
CB_Move4.SelectedValue = pk2.Move4;
|
||||
CB_PPu1.SelectedIndex = pk2.Move1_PPUps;
|
||||
CB_PPu2.SelectedIndex = pk2.Move2_PPUps;
|
||||
CB_PPu3.SelectedIndex = pk2.Move3_PPUps;
|
||||
CB_PPu4.SelectedIndex = pk2.Move4_PPUps;
|
||||
TB_PP1.Text = pk2.Move1_PP.ToString();
|
||||
TB_PP2.Text = pk2.Move2_PP.ToString();
|
||||
TB_PP3.Text = pk2.Move3_PP.ToString();
|
||||
TB_PP4.Text = pk2.Move4_PP.ToString();
|
||||
|
||||
CB_Language.SelectedIndex = pk2.Japanese ? 0 : 1;
|
||||
|
||||
updateStats();
|
||||
setIsShiny(null);
|
||||
|
||||
Label_Gender.Text = gendersymbols[pk2.Gender];
|
||||
Label_Gender.ForeColor = pk2.Gender == 2 ? Label_Species.ForeColor : (pk2.Gender == 1 ? Color.Red : Color.Blue);
|
||||
TB_EXP.Text = pk2.EXP.ToString();
|
||||
}
|
||||
private PKM preparePK2()
|
||||
{
|
||||
PK2 pk2 = pkm as PK2;
|
||||
if (pk2 == null)
|
||||
return null;
|
||||
|
||||
pk2.Species = Util.getIndex(CB_Species);
|
||||
pk2.TID = Util.ToInt32(TB_TID.Text);
|
||||
pk2.EXP = Util.ToUInt32(TB_EXP.Text);
|
||||
pk2.HeldItem = Util.getIndex(CB_HeldItem);
|
||||
pk2.IsEgg = CHK_IsEgg.Checked;
|
||||
|
||||
pk2.EV_HP = Util.ToInt32(TB_HPEV.Text);
|
||||
pk2.EV_ATK = Util.ToInt32(TB_ATKEV.Text);
|
||||
pk2.EV_DEF = Util.ToInt32(TB_DEFEV.Text);
|
||||
pk2.EV_SPE = Util.ToInt32(TB_SPEEV.Text);
|
||||
pk2.EV_SPC = Util.ToInt32(TB_SPAEV.Text);
|
||||
|
||||
pk2.Nickname = TB_Nickname.Text;
|
||||
pk2.Move1 = Util.getIndex(CB_Move1);
|
||||
pk2.Move2 = Util.getIndex(CB_Move2);
|
||||
pk2.Move3 = Util.getIndex(CB_Move3);
|
||||
pk2.Move4 = Util.getIndex(CB_Move4);
|
||||
pk2.Move1_PP = Util.getIndex(CB_Move1) > 0 ? Util.ToInt32(TB_PP1.Text) : 0;
|
||||
pk2.Move2_PP = Util.getIndex(CB_Move2) > 0 ? Util.ToInt32(TB_PP2.Text) : 0;
|
||||
pk2.Move3_PP = Util.getIndex(CB_Move3) > 0 ? Util.ToInt32(TB_PP3.Text) : 0;
|
||||
pk2.Move4_PP = Util.getIndex(CB_Move4) > 0 ? Util.ToInt32(TB_PP4.Text) : 0;
|
||||
pk2.Move1_PPUps = Util.getIndex(CB_Move1) > 0 ? CB_PPu1.SelectedIndex : 0;
|
||||
pk2.Move2_PPUps = Util.getIndex(CB_Move2) > 0 ? CB_PPu2.SelectedIndex : 0;
|
||||
pk2.Move3_PPUps = Util.getIndex(CB_Move3) > 0 ? CB_PPu3.SelectedIndex : 0;
|
||||
pk2.Move4_PPUps = Util.getIndex(CB_Move4) > 0 ? CB_PPu4.SelectedIndex : 0;
|
||||
|
||||
pk2.IV_HP = Util.ToInt32(TB_HPIV.Text);
|
||||
pk2.IV_ATK = Util.ToInt32(TB_ATKIV.Text);
|
||||
pk2.IV_DEF = Util.ToInt32(TB_DEFIV.Text);
|
||||
pk2.IV_SPE = Util.ToInt32(TB_SPEIV.Text);
|
||||
pk2.IV_SPA = Util.ToInt32(TB_SPAIV.Text);
|
||||
|
||||
pk2.OT_Name = TB_OT.Text;
|
||||
|
||||
// Toss in Party Stats
|
||||
Array.Resize(ref pk2.Data, pk2.SIZE_PARTY);
|
||||
pk2.Stat_Level = Util.ToInt32(TB_Level.Text);
|
||||
pk2.Stat_HPCurrent = Util.ToInt32(Stat_HP.Text);
|
||||
pk2.Stat_HPMax = Util.ToInt32(Stat_HP.Text);
|
||||
pk2.Stat_ATK = Util.ToInt32(Stat_ATK.Text);
|
||||
pk2.Stat_DEF = Util.ToInt32(Stat_DEF.Text);
|
||||
pk2.Stat_SPE = Util.ToInt32(Stat_SPE.Text);
|
||||
pk2.Stat_SPA = Util.ToInt32(Stat_SPA.Text);
|
||||
pk2.Stat_SPD = Util.ToInt32(Stat_SPD.Text);
|
||||
|
||||
if (HaX)
|
||||
{
|
||||
pk2.Stat_Level = (byte)Math.Min(Convert.ToInt32(MT_Level.Text), byte.MaxValue);
|
||||
}
|
||||
|
||||
// Fix Moves if a slot is empty
|
||||
pk2.FixMoves();
|
||||
|
||||
return pk2;
|
||||
}
|
||||
}
|
||||
}
|
BIN
PKHeX/Misc/personal_gs
Normal file
BIN
PKHeX/Misc/personal_gs
Normal file
Binary file not shown.
|
@ -73,6 +73,9 @@
|
|||
<Compile Include="Legality\Tables3.cs" />
|
||||
<Compile Include="Legality\Tables5.cs" />
|
||||
<Compile Include="Legality\Tables4.cs" />
|
||||
<Compile Include="MainWindow\MainPK2.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MainWindow\MainPK1.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
|
@ -93,6 +96,7 @@
|
|||
<Compile Include="PersonalInfo\PersonalInfo.cs" />
|
||||
<Compile Include="PersonalInfo\PersonalInfoB2W2.cs" />
|
||||
<Compile Include="PersonalInfo\PersonalInfoBW.cs" />
|
||||
<Compile Include="PersonalInfo\PersonalInfoG2.cs" />
|
||||
<Compile Include="PersonalInfo\PersonalInfoG1.cs" />
|
||||
<Compile Include="PersonalInfo\PersonalInfoG3.cs" />
|
||||
<Compile Include="PersonalInfo\PersonalInfoG4.cs" />
|
||||
|
@ -100,6 +104,7 @@
|
|||
<Compile Include="PersonalInfo\PersonalInfoXY.cs" />
|
||||
<Compile Include="PersonalInfo\PersonalTable.cs" />
|
||||
<Compile Include="PKM\PK1.cs" />
|
||||
<Compile Include="PKM\PK2.cs" />
|
||||
<Compile Include="PKM\PKM.cs" />
|
||||
<Compile Include="PKM\PKMConverter.cs" />
|
||||
<Compile Include="PKM\ShowdownSet.cs" />
|
||||
|
@ -119,6 +124,7 @@
|
|||
<Compile Include="Saves\BlockInfo.cs" />
|
||||
<Compile Include="Saves\BoxWallpaper.cs" />
|
||||
<Compile Include="Saves\Inventory.cs" />
|
||||
<Compile Include="Saves\SAV2.cs" />
|
||||
<Compile Include="Saves\SAV1.cs" />
|
||||
<Compile Include="Saves\SAV3.cs" />
|
||||
<Compile Include="Saves\SAV4.cs" />
|
||||
|
@ -422,6 +428,7 @@
|
|||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<None Include="app.config" />
|
||||
<None Include="Misc\personal_gs" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
|
@ -471,9 +478,11 @@
|
|||
<None Include="Resources\byte\lvlmove_xy.pkl" />
|
||||
<None Include="Resources\byte\personal_b2w2" />
|
||||
<None Include="Resources\byte\personal_bw" />
|
||||
<None Include="Resources\byte\personal_c" />
|
||||
<None Include="Resources\byte\personal_dp" />
|
||||
<None Include="Resources\byte\personal_e" />
|
||||
<None Include="Resources\byte\personal_fr" />
|
||||
<None Include="Resources\byte\personal_gs" />
|
||||
<None Include="Resources\byte\personal_hgss" />
|
||||
<None Include="Resources\byte\personal_lg" />
|
||||
<None Include="Resources\byte\personal_pt" />
|
||||
|
@ -2746,6 +2755,9 @@
|
|||
<ItemGroup>
|
||||
<None Include="Resources\text\gen3\text_ItemsG1_en.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Resources\text\gen3\text_ItemsG2_en.txt" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace PKHeX
|
|||
internal const int STRLEN_U = 11;
|
||||
private int StringLength => Japanese ? STRLEN_J : STRLEN_U;
|
||||
|
||||
public override int Format => 1;
|
||||
public override int Format => 2;
|
||||
|
||||
public bool Japanese => otname.Length == STRLEN_J;
|
||||
|
||||
|
@ -92,8 +92,7 @@ namespace PKHeX
|
|||
{
|
||||
// Oh god this is such total abuse of what this method is meant to do
|
||||
// Please forgive me
|
||||
return (byte[]) Data.Clone();
|
||||
// return new PokemonList1(this).GetBytes();
|
||||
return new PokemonList2(this).GetBytes();
|
||||
}
|
||||
|
||||
// Please forgive me.
|
||||
|
@ -213,8 +212,7 @@ namespace PKHeX
|
|||
|
||||
public override bool getGenderIsValid()
|
||||
{
|
||||
return true;
|
||||
int gv = PersonalTable.GSC[Species].Gender;
|
||||
int gv = PersonalTable.C[Species].Gender;
|
||||
|
||||
if (gv == 255)
|
||||
return Gender == 2;
|
||||
|
@ -222,29 +220,90 @@ namespace PKHeX
|
|||
return Gender == 0;
|
||||
if (gv == 0)
|
||||
return Gender == 1;
|
||||
if (gv <= (PID & 0xFF))
|
||||
return Gender == 0;
|
||||
if ((PID & 0xFF) < gv)
|
||||
return Gender == 1;
|
||||
|
||||
switch (gv)
|
||||
{
|
||||
case 191:
|
||||
return IV_ATK >= 2 ? Gender == 0 : Gender == 1;
|
||||
case 127:
|
||||
return IV_ATK >= 5 ? Gender == 0 : Gender == 1;
|
||||
case 63:
|
||||
return IV_ATK >= 7 ? Gender == 0 : Gender == 1;
|
||||
case 31:
|
||||
return IV_ATK >= 12 ? Gender == 0 : Gender == 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool IsEgg { get; set; }
|
||||
public override int Gender { get { return 0; } set { } }
|
||||
|
||||
public override int Gender
|
||||
{
|
||||
get
|
||||
{
|
||||
int gv = PersonalTable.C[Species].Gender;
|
||||
if (gv == 255)
|
||||
return 2;
|
||||
if (gv == 254)
|
||||
return 0;
|
||||
if (gv == 0)
|
||||
return 1;
|
||||
switch (gv)
|
||||
{
|
||||
case 191:
|
||||
return IV_ATK >= 2 ? 0 : 1;
|
||||
case 127:
|
||||
return IV_ATK >= 5 ? 0 : 1;
|
||||
case 63:
|
||||
return IV_ATK >= 7 ? 0 : 1;
|
||||
case 31:
|
||||
return IV_ATK >= 12 ? 0 : 1;
|
||||
}
|
||||
Console.WriteLine("Unknown Gender value: " + gv);
|
||||
return 0;
|
||||
}
|
||||
set { }
|
||||
}
|
||||
|
||||
public bool hasMetData => CaughtData != 0;
|
||||
|
||||
public override bool CanHoldItem(ushort[] ValidArray)
|
||||
{
|
||||
return false;
|
||||
return ValidArray.Contains((ushort)HeldItem);
|
||||
}
|
||||
|
||||
#region Future, Unused Attributes
|
||||
public override uint EncryptionConstant { get { return 0; } set { } }
|
||||
public override uint PID { get { return 0; } set { } }
|
||||
public override int Nature { get { return 0; } set { } }
|
||||
public override int AltForm { get { return 0; } set { } }
|
||||
|
||||
public override int AltForm
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Species != 201) // Unown
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
uint formeVal = 0;
|
||||
formeVal |= (uint)((IV_ATK & 0x6) << 5);
|
||||
formeVal |= (uint)((IV_DEF & 0x6) << 3);
|
||||
formeVal |= (uint)((IV_SPE & 0x6) << 1);
|
||||
formeVal |= (uint)((IV_SPC & 0x6) >> 1);
|
||||
return (int)(formeVal / 10);
|
||||
}
|
||||
}
|
||||
set{ }
|
||||
}
|
||||
|
||||
public override int HPType
|
||||
{
|
||||
get { return 4 * (IV_ATK % 4) + (IV_DEF % 4); }
|
||||
set
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
public override bool IsShiny => IV_DEF == 10 && IV_SPE == 10 && IV_SPC == 10 && (new[] { 2, 3, 6, 7, 10, 11, 14, 15 }).Contains(IV_ATK);
|
||||
public override ushort Sanity { get { return 0; } set { } }
|
||||
public override bool ChecksumValid => true;
|
||||
public override ushort Checksum { get { return 0; } set { } }
|
||||
|
|
|
@ -226,7 +226,7 @@ namespace PKHeX
|
|||
public abstract int CurrentHandler { get; set; }
|
||||
|
||||
// Derived
|
||||
public bool IsShiny => TSV == PSV;
|
||||
public virtual bool IsShiny => TSV == PSV;
|
||||
public bool Gen6 => Version >= 24 && Version <= 29;
|
||||
public bool XY => Version == (int)GameVersion.X || Version == (int)GameVersion.Y;
|
||||
public bool AO => Version == (int)GameVersion.AS || Version == (int)GameVersion.OR;
|
||||
|
@ -335,7 +335,7 @@ namespace PKHeX
|
|||
get { return new[] { CNT_Cool, CNT_Beauty, CNT_Cute, CNT_Smart, CNT_Tough, CNT_Sheen }; }
|
||||
set { if (value?.Length != 6) return; CNT_Cool = value[0]; CNT_Beauty = value[1]; CNT_Cute = value[2]; CNT_Smart = value[3]; CNT_Tough = value[4]; CNT_Sheen = value[5]; }
|
||||
}
|
||||
public int HPType
|
||||
public virtual int HPType
|
||||
{
|
||||
get { return 15 * ((IV_HP & 1) + 2 * (IV_ATK & 1) + 4 * (IV_DEF & 1) + 8 * (IV_SPE & 1) + 16 * (IV_SPA & 1) + 32 * (IV_SPD & 1)) / 63; }
|
||||
set
|
||||
|
|
|
@ -528,6 +528,8 @@ namespace PKHeX
|
|||
Image itemimg = (Image)Resources.ResourceManager.GetObject("item_" + item) ?? Resources.helditem;
|
||||
if ((generation == 3 || generation == 4) && 328 <= item && item <= 419) // gen3/4 TM
|
||||
itemimg = Resources.item_tm;
|
||||
if (generation == 2)
|
||||
itemimg = Resources.helditem; // Don't even try
|
||||
|
||||
// Redraw
|
||||
baseImage = Util.LayerImage(baseImage, itemimg, 22 + (15 - itemimg.Width) / 2, 15 + (15 - itemimg.Height), 1);
|
||||
|
|
80
PKHeX/PersonalInfo/PersonalInfoG2.cs
Normal file
80
PKHeX/PersonalInfo/PersonalInfoG2.cs
Normal file
|
@ -0,0 +1,80 @@
|
|||
using System.Linq;
|
||||
|
||||
namespace PKHeX
|
||||
{
|
||||
public class PersonalInfoG2 : PersonalInfo
|
||||
{
|
||||
protected PersonalInfoG2() { }
|
||||
public const int SIZE = 0x20;
|
||||
public PersonalInfoG2(byte[] data)
|
||||
{
|
||||
if (data.Length != SIZE)
|
||||
return;
|
||||
|
||||
Data = data;
|
||||
TMHM = getBits(Data.Skip(0x18).Take(0x8).ToArray());
|
||||
}
|
||||
public override byte[] Write()
|
||||
{
|
||||
setBits(TMHM).CopyTo(Data, 0x18);
|
||||
return Data;
|
||||
}
|
||||
|
||||
public int DEX_ID { get { return Data[0x00]; } set { Data[0x00] = (byte)value; } }
|
||||
public override int HP { get { return Data[0x01]; } set { Data[0x01] = (byte)value; } }
|
||||
public override int ATK { get { return Data[0x02]; } set { Data[0x02] = (byte)value; } }
|
||||
public override int DEF { get { return Data[0x03]; } set { Data[0x03] = (byte)value; } }
|
||||
public override int SPE { get { return Data[0x04]; } set { Data[0x04] = (byte)value; } }
|
||||
public override int SPA { get { return Data[0x05]; } set { Data[0x05] = (byte)value; } }
|
||||
public override int SPD { get { return Data[0x06]; } set { Data[0x06] = (byte)value; } }
|
||||
public override int[] Types
|
||||
{
|
||||
get { return new int[] { Data[0x07], Data[0x08] }; }
|
||||
set
|
||||
{
|
||||
if (value?.Length != 2) return;
|
||||
Data[0x07] = (byte)value[0];
|
||||
Data[0x08] = (byte)value[1];
|
||||
}
|
||||
}
|
||||
public override int CatchRate { get { return Data[0x09]; } set { Data[0x09] = (byte)value; } }
|
||||
public override int BaseEXP { get { return Data[0x0A]; } set { Data[0x0A] = (byte)value; } }
|
||||
|
||||
public override int[] Items
|
||||
{
|
||||
get { return new int[] { Data[0xB], Data[0xC] }; }
|
||||
set
|
||||
{
|
||||
if (value?.Length != 2) return;
|
||||
Data[0xB] = (byte) value[0];
|
||||
Data[0xC] = (byte) value[1];
|
||||
}
|
||||
}
|
||||
public override int Gender { get { return Data[0xD]; } set { Data[0xD] = (byte)value; } }
|
||||
public override int HatchCycles { get { return Data[0xF]; } set { Data[0xF] = (byte)value; } }
|
||||
public override int EXPGrowth { get { return Data[0x16]; } set { Data[0x16] = (byte)value; } }
|
||||
public override int[] EggGroups
|
||||
{
|
||||
get { return new int[] { Data[0x17] >> 4, Data[0x17] & 0xF }; }
|
||||
set
|
||||
{
|
||||
if (value?.Length != 2) return;
|
||||
Data[0x17] = (byte)(((value[0] & 0xF) << 4) | (value[1] & 0xF));
|
||||
}
|
||||
}
|
||||
|
||||
// EV Yields are just aliases for base stats in Gen I
|
||||
public override int EV_HP { get { return HP; } set { } }
|
||||
public override int EV_ATK { get { return ATK; } set { } }
|
||||
public override int EV_DEF { get { return DEF; } set { } }
|
||||
public override int EV_SPE { get { return SPE; } set { } }
|
||||
public override int EV_SPA { get { return SPA; } set { } }
|
||||
public override int EV_SPD { get { return SPD; } set { } }
|
||||
|
||||
// Future game values, unused
|
||||
public override int[] Abilities { get { return new[] { 0, 0 }; } set { } }
|
||||
public override int BaseFriendship { get { return 0; } set { } }
|
||||
public override int EscapeRate { get { return 0; } set { } }
|
||||
public override int Color { get { return 0; } set { } }
|
||||
}
|
||||
}
|
|
@ -15,6 +15,8 @@ namespace PKHeX
|
|||
internal static readonly PersonalTable FR = new PersonalTable(Properties.Resources.personal_fr, GameVersion.FR);
|
||||
internal static readonly PersonalTable E = new PersonalTable(Properties.Resources.personal_e, GameVersion.E);
|
||||
internal static readonly PersonalTable RS = new PersonalTable(Properties.Resources.personal_rs, GameVersion.RS);
|
||||
internal static readonly PersonalTable C = new PersonalTable(Properties.Resources.personal_c, GameVersion.C);
|
||||
internal static readonly PersonalTable GS = new PersonalTable(Properties.Resources.personal_c, GameVersion.GS);
|
||||
internal static readonly PersonalTable RBY = new PersonalTable(Properties.Resources.personal_rby, GameVersion.RBY);
|
||||
|
||||
private static byte[][] splitBytes(byte[] data, int size)
|
||||
|
@ -33,6 +35,8 @@ namespace PKHeX
|
|||
switch (format)
|
||||
{
|
||||
case GameVersion.RBY: size = PersonalInfoG1.SIZE; break;
|
||||
case GameVersion.GS:
|
||||
case GameVersion.C: size = PersonalInfoG2.SIZE; break;
|
||||
case GameVersion.RS:
|
||||
case GameVersion.E:
|
||||
case GameVersion.FR:
|
||||
|
@ -58,6 +62,11 @@ namespace PKHeX
|
|||
for (int i = 0; i < d.Length; i++)
|
||||
d[i] = new PersonalInfoG1(entries[i]);
|
||||
break;
|
||||
case GameVersion.GS:
|
||||
case GameVersion.C:
|
||||
for (int i = 0; i < d.Length; i++)
|
||||
d[i] = new PersonalInfoG2(entries[i]);
|
||||
break;
|
||||
case GameVersion.RS:
|
||||
case GameVersion.E:
|
||||
case GameVersion.FR:
|
||||
|
|
74
PKHeX/Properties/Resources.Designer.cs
generated
74
PKHeX/Properties/Resources.Designer.cs
generated
|
@ -15495,6 +15495,16 @@ namespace PKHeX.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
internal static byte[] personal_c {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("personal_c", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
|
@ -15525,6 +15535,16 @@ namespace PKHeX.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
internal static byte[] personal_gs {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("personal_gs", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
|
@ -25209,6 +25229,60 @@ namespace PKHeX.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to (None)
|
||||
///Master Ball
|
||||
///Ultra Ball
|
||||
///BrightPowder
|
||||
///Great Ball
|
||||
///Poké Ball
|
||||
///Teru-sama (0)
|
||||
///Bicycle
|
||||
///Moon Stone
|
||||
///Antidote
|
||||
///Burn Heal
|
||||
///Ice Heal
|
||||
///Awakening
|
||||
///Parlyz Heal
|
||||
///Full Restore
|
||||
///Max Potion
|
||||
///Hyper Potion
|
||||
///Super Potion
|
||||
///Potion
|
||||
///Escape Rope
|
||||
///Repel
|
||||
///Max Elixer
|
||||
///Fire Stone
|
||||
///Thunder Stone
|
||||
///Water Stone
|
||||
///Teru-sama (1)
|
||||
///HP Up
|
||||
///Protein
|
||||
///Iron
|
||||
///Carbos
|
||||
///Lucky Punch
|
||||
///Calcium
|
||||
///Rare Candy
|
||||
///X Accuracy
|
||||
///Leaf Stone
|
||||
///Metal Powder
|
||||
///Nugget
|
||||
///Poké Doll
|
||||
///Full Heal
|
||||
///Revive
|
||||
///Max Revive
|
||||
///Guard Spec.
|
||||
///Super Repel
|
||||
///Max Repel
|
||||
///Dire Hit
|
||||
///Ter [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string text_ItemsG2_en {
|
||||
get {
|
||||
return ResourceManager.GetString("text_ItemsG2_en", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to (None)
|
||||
///Master Ball
|
||||
|
|
|
@ -6403,4 +6403,13 @@
|
|||
<data name="text_ItemsG1_en" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\text\gen3\text_ItemsG1_en.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16</value>
|
||||
</data>
|
||||
<data name="personal_c" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\resources\byte\personal_c;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="personal_gs" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\resources\byte\personal_gs;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="text_ItemsG2_en" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\resources\text\gen3\text_itemsg2_en.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
</root>
|
BIN
PKHeX/Resources/byte/personal_c
Normal file
BIN
PKHeX/Resources/byte/personal_c
Normal file
Binary file not shown.
BIN
PKHeX/Resources/byte/personal_gs
Normal file
BIN
PKHeX/Resources/byte/personal_gs
Normal file
Binary file not shown.
255
PKHeX/Resources/text/gen3/text_ItemsG2_en.txt
Normal file
255
PKHeX/Resources/text/gen3/text_ItemsG2_en.txt
Normal file
|
@ -0,0 +1,255 @@
|
|||
(None)
|
||||
Master Ball
|
||||
Ultra Ball
|
||||
BrightPowder
|
||||
Great Ball
|
||||
Poké Ball
|
||||
Teru-sama (0)
|
||||
Bicycle
|
||||
Moon Stone
|
||||
Antidote
|
||||
Burn Heal
|
||||
Ice Heal
|
||||
Awakening
|
||||
Parlyz Heal
|
||||
Full Restore
|
||||
Max Potion
|
||||
Hyper Potion
|
||||
Super Potion
|
||||
Potion
|
||||
Escape Rope
|
||||
Repel
|
||||
Max Elixer
|
||||
Fire Stone
|
||||
Thunder Stone
|
||||
Water Stone
|
||||
Teru-sama (1)
|
||||
HP Up
|
||||
Protein
|
||||
Iron
|
||||
Carbos
|
||||
Lucky Punch
|
||||
Calcium
|
||||
Rare Candy
|
||||
X Accuracy
|
||||
Leaf Stone
|
||||
Metal Powder
|
||||
Nugget
|
||||
Poké Doll
|
||||
Full Heal
|
||||
Revive
|
||||
Max Revive
|
||||
Guard Spec.
|
||||
Super Repel
|
||||
Max Repel
|
||||
Dire Hit
|
||||
Teru-sama (2)
|
||||
Fresh Water
|
||||
Soda Pop
|
||||
Lemonade
|
||||
X Attack
|
||||
Teru-sama (3)
|
||||
X Defend
|
||||
X Speed
|
||||
X Special
|
||||
Coin Case
|
||||
Itemfinder
|
||||
Teru-sama (4)
|
||||
Exp Share
|
||||
Old Rod
|
||||
Good Rod
|
||||
Silver Leaf
|
||||
Super Rod
|
||||
PP Up
|
||||
Ether
|
||||
Max Ether
|
||||
Elixer
|
||||
Red Scale
|
||||
SecretPotion
|
||||
S.S. Ticket
|
||||
Mystery Egg
|
||||
Clear Bell*
|
||||
Silver Wing
|
||||
Moomoo Milk
|
||||
Quick Claw
|
||||
PSNCureBerry
|
||||
Gold Leaf
|
||||
Soft Sand
|
||||
Sharp Beak
|
||||
PRZCureBerry
|
||||
Burnt Berry
|
||||
Ice Berry
|
||||
Poison Barb
|
||||
King's Rock
|
||||
Bitter Berry
|
||||
Mint Berry
|
||||
Red Apricorn
|
||||
TinyMushroom
|
||||
Big Mushroom
|
||||
SilverPowder
|
||||
Blu Apricorn
|
||||
Teru-sama (5)
|
||||
Amulet Coin
|
||||
Ylw Apricorn
|
||||
Grn Apricorn
|
||||
Cleanse Tag
|
||||
Mystic Water
|
||||
TwistedSpoon
|
||||
Wht Apricorn
|
||||
Black Belt
|
||||
Blk Apricorn
|
||||
Teru-sama (6)
|
||||
Pnk Apricorn
|
||||
BlackGlasses
|
||||
SlowpokeTail
|
||||
Pink Bow
|
||||
Stick
|
||||
Smoke Ball
|
||||
NeverMeltIce
|
||||
Magnet
|
||||
MiracleBerry
|
||||
Pearl
|
||||
Big Pearl
|
||||
Everstone
|
||||
Spell Tag
|
||||
RageCandyBar
|
||||
GS Ball*
|
||||
Blue Card*
|
||||
Miracle Seed
|
||||
Thick Club
|
||||
Focus Band
|
||||
Teru-sama (7)
|
||||
EnergyPowder
|
||||
Energy Root
|
||||
Heal Powder
|
||||
Revival Herb
|
||||
Hard Stone
|
||||
Lucky Egg
|
||||
Card Key
|
||||
Machine Part
|
||||
Egg Ticket*
|
||||
Lost Item
|
||||
Stardust
|
||||
Star Piece
|
||||
Basement Key
|
||||
Pass
|
||||
Teru-sama (8)
|
||||
Teru-sama (9)
|
||||
Teru-sama (10)
|
||||
Charcoal
|
||||
Berry Juice
|
||||
Scope Lens
|
||||
Teru-sama (11)
|
||||
Teru-sama (12)
|
||||
Metal Coat
|
||||
Dragon Fang
|
||||
Teru-sama (13)
|
||||
Leftovers
|
||||
Teru-sama (14)
|
||||
Teru-sama (15)
|
||||
Teru-sama (16)
|
||||
MysteryBerry
|
||||
Dragon Scale
|
||||
Berserk Gene
|
||||
Teru-sama (17)
|
||||
Teru-sama (18)
|
||||
Teru-sama (19)
|
||||
Sacred Ash
|
||||
Heavy Ball
|
||||
Flower Mail
|
||||
Level Ball
|
||||
Lure Ball
|
||||
Fast Ball
|
||||
Teru-sama (20)
|
||||
Light Ball
|
||||
Friend Ball
|
||||
Moon Ball
|
||||
Love Ball
|
||||
Normal Box
|
||||
Gorgeous Box
|
||||
Sun Stone
|
||||
Polkadot Bow
|
||||
Teru-sama (21)
|
||||
Up-Grade
|
||||
Berry
|
||||
Gold Berry
|
||||
SquirtBottle
|
||||
Teru-sama (22)
|
||||
Park Ball
|
||||
Rainbow Wing
|
||||
Teru-sama (23)
|
||||
Brick Piece
|
||||
Surf Mail
|
||||
Litebluemail
|
||||
Portraitmail
|
||||
Lovely Mail
|
||||
Eon Mail
|
||||
Morph Mail
|
||||
Bluesky Mail
|
||||
Music Mail
|
||||
Mirage Mail
|
||||
Teru-sama (24)
|
||||
TM01
|
||||
TM02
|
||||
TM03
|
||||
TM04
|
||||
TM04 (Unused)
|
||||
TM05
|
||||
TM06
|
||||
TM07
|
||||
TM08
|
||||
TM09
|
||||
TM10
|
||||
TM11
|
||||
TM12
|
||||
TM13
|
||||
TM14
|
||||
TM15
|
||||
TM16
|
||||
TM17
|
||||
TM18
|
||||
TM19
|
||||
TM20
|
||||
TM21
|
||||
TM22
|
||||
TM23
|
||||
TM24
|
||||
TM25
|
||||
TM26
|
||||
TM27
|
||||
TM28
|
||||
TM28 (Unused)
|
||||
TM29
|
||||
TM30
|
||||
TM31
|
||||
TM32
|
||||
TM33
|
||||
TM34
|
||||
TM35
|
||||
TM36
|
||||
TM37
|
||||
TM38
|
||||
TM39
|
||||
TM40
|
||||
TM41
|
||||
TM42
|
||||
TM43
|
||||
TM44
|
||||
TM45
|
||||
TM46
|
||||
TM47
|
||||
TM48
|
||||
TM49
|
||||
TM50
|
||||
HM01
|
||||
HM02
|
||||
HM03
|
||||
HM04
|
||||
HM05
|
||||
HM06
|
||||
HM07
|
||||
HM08 (Unused)
|
||||
HM09 (Unused)
|
||||
HM10 (Unused)
|
||||
HM11 (Unused)
|
||||
HM12 (Unused)
|
569
PKHeX/Saves/SAV2.cs
Normal file
569
PKHeX/Saves/SAV2.cs
Normal file
|
@ -0,0 +1,569 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX
|
||||
{
|
||||
public sealed class SAV2 : SaveFile
|
||||
{
|
||||
public override string BAKName => $"{FileName} [{OT} ({Version})" +/* - {LastSavedTime}*/ "].bak";
|
||||
public override string Filter => "SAV File|*.sav";
|
||||
public override string Extension => ".sav";
|
||||
|
||||
public SAV2(byte[] data = null)
|
||||
{
|
||||
Data = data == null ? new byte[SaveUtil.SIZE_G2RAW] : (byte[])data.Clone();
|
||||
BAK = (byte[])Data.Clone();
|
||||
Exportable = !Data.SequenceEqual(new byte[Data.Length]);
|
||||
|
||||
Version = data == null ? GameVersion.GSC : SaveUtil.getIsG2SAV(Data);
|
||||
if (Version == GameVersion.Invalid)
|
||||
return;
|
||||
|
||||
Box = Data.Length;
|
||||
Array.Resize(ref Data, Data.Length + SIZE_RESERVED);
|
||||
Party = getPartyOffset(0);
|
||||
|
||||
Japanese = false;
|
||||
Personal = Version == GameVersion.GS ? PersonalTable.GS : PersonalTable.C;
|
||||
|
||||
OptionsOffset = 0x2000;
|
||||
Trainer1 = 0x2009;
|
||||
switch (Version)
|
||||
{
|
||||
case GameVersion.GS:
|
||||
DaylightSavingsOffset = Japanese ? -1 : 0x2037;
|
||||
TimePlayedOffset = Japanese ? -1 : 0x2053;
|
||||
PaletteOffset = Japanese ? -1 : 0x206B;
|
||||
MoneyOffset = Japanese ? -1 : 0x23DB;
|
||||
JohtoBadgesOffset = Japanese ? -1 : 0xD57C;
|
||||
CurrentBoxIndexOffset = Japanese ? -1 : 0x2724;
|
||||
BoxNamesOffset = Japanese ? -1 : 0x2727;
|
||||
PartyOffset = Japanese ? 0x283E : 0x288A;
|
||||
PokedexCaughtOffset = Japanese ? -1 : 0x2A4C;
|
||||
PokedexSeenOffset = Japanese ? -1 : 0x2A6C;
|
||||
CurrentBoxOffset = Japanese ? -1 : 0x2D6C;
|
||||
GenderOffset = -1; // No gender in GSC
|
||||
break;
|
||||
case GameVersion.C:
|
||||
DaylightSavingsOffset = Japanese ? -1 : 0x2037;
|
||||
TimePlayedOffset = Japanese ? -1 : 0x2054;
|
||||
PaletteOffset = Japanese ? -1 : 0x206A;
|
||||
MoneyOffset = Japanese ? -1 : 0x23DC;
|
||||
JohtoBadgesOffset = Japanese ? -1 : 0x23E5;
|
||||
CurrentBoxIndexOffset = Japanese ? -1 : 0x2700;
|
||||
BoxNamesOffset = Japanese ? 0x2708 : 0x2703;
|
||||
PartyOffset = Japanese ? 0x281A : 0x2865;
|
||||
PokedexCaughtOffset = Japanese ? -1 : 0x2A27;
|
||||
PokedexSeenOffset = Japanese ? -1 : 0x2A47;
|
||||
CurrentBoxOffset = 0x2D10;
|
||||
GenderOffset = Japanese ? -1 : 0x3E3D;
|
||||
break;
|
||||
}
|
||||
LegalItems = new ushort[] { 3, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46, 47, 48, 49, 51, 52, 53, 57, 60, 62, 63, 64, 65, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 91, 92, 93, 94, 95, 96, 97, 98, 99, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 117, 118, 119, 121, 122, 123, 124, 125, 126, 131, 132, 138, 139, 140, 143, 144, 146, 150, 151, 152, 156, 158, 163, 168, 169, 170, 172, 173, 174, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189 };
|
||||
LegalBalls = new ushort[] { 1, 2, 4, 5, 157, 159, 160, 161, 164, 165, 166, 167};
|
||||
HeldItems = new ushort[] {0}.Concat(LegalItems).Concat(LegalBalls).ToArray();
|
||||
Array.Sort(HeldItems);
|
||||
|
||||
// Stash boxes after the save file's end.
|
||||
byte[] TempBox = new byte[SIZE_STOREDBOX];
|
||||
for (int i = 0; i < BoxCount; i++)
|
||||
{
|
||||
if (i < (Japanese ? 6 : 7))
|
||||
Array.Copy(Data, 0x4000 + i * (TempBox.Length + 2), TempBox, 0, TempBox.Length);
|
||||
else
|
||||
Array.Copy(Data, 0x6000 + (i - (Japanese ? 6 : 7)) * (TempBox.Length + 2), TempBox, 0, TempBox.Length);
|
||||
PokemonList2 PL2 = new PokemonList2(TempBox, Japanese ? PokemonList2.CapacityType.StoredJP : PokemonList2.CapacityType.Stored, Japanese);
|
||||
for (int j = 0; j < PL2.Pokemon.Length; j++)
|
||||
{
|
||||
if (j < PL2.Count)
|
||||
{
|
||||
byte[] pkDat = new PokemonList2(PL2[j]).GetBytes();
|
||||
pkDat.CopyTo(Data, Data.Length - SIZE_RESERVED + i * SIZE_BOX + j * SIZE_STORED);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] pkDat = new byte[PokemonList2.GetDataLength(PokemonList2.CapacityType.Single, Japanese)];
|
||||
pkDat.CopyTo(Data, Data.Length - SIZE_RESERVED + i * SIZE_BOX + j * SIZE_STORED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Array.Copy(Data, CurrentBoxOffset, TempBox, 0, TempBox.Length);
|
||||
PokemonList2 curBoxPL = new PokemonList2(TempBox, Japanese ? PokemonList2.CapacityType.StoredJP : PokemonList2.CapacityType.Stored, Japanese);
|
||||
for (int i = 0; i < curBoxPL.Pokemon.Length; i++)
|
||||
{
|
||||
if (i < curBoxPL.Count)
|
||||
{
|
||||
byte[] pkDat = new PokemonList2(curBoxPL[i]).GetBytes();
|
||||
pkDat.CopyTo(Data, Data.Length - SIZE_RESERVED + CurrentBox * SIZE_BOX + i * SIZE_STORED);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] pkDat = new byte[PokemonList2.GetDataLength(PokemonList2.CapacityType.Single, Japanese)];
|
||||
pkDat.CopyTo(Data, Data.Length - SIZE_RESERVED + CurrentBox * SIZE_BOX + i * SIZE_STORED);
|
||||
}
|
||||
}
|
||||
|
||||
byte[] TempParty = new byte[PokemonList2.GetDataLength(PokemonList2.CapacityType.Party, Japanese)];
|
||||
Array.Copy(Data, PartyOffset, TempParty, 0, TempParty.Length);
|
||||
PokemonList2 partyList = new PokemonList2(TempParty, PokemonList2.CapacityType.Party, Japanese);
|
||||
for (int i = 0; i < partyList.Pokemon.Length; i++)
|
||||
{
|
||||
if (i < partyList.Count)
|
||||
{
|
||||
byte[] pkDat = new PokemonList2(partyList[i]).GetBytes();
|
||||
pkDat.CopyTo(Data, getPartyOffset(i));
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] pkDat = new byte[PokemonList2.GetDataLength(PokemonList2.CapacityType.Single, Japanese)];
|
||||
pkDat.CopyTo(Data, getPartyOffset(i));
|
||||
}
|
||||
}
|
||||
/*
|
||||
byte[] rawDC = new byte[0x38];
|
||||
Array.Copy(Data, Japanese ? 0x2CA7 : 0x2CF4, rawDC, 0, rawDC.Length);
|
||||
byte[] TempDaycare = new byte[PokemonList1.GetDataLength(PokemonList1.CapacityType.Single, Japanese)];
|
||||
TempDaycare[0] = rawDC[0];
|
||||
Array.Copy(rawDC, 1, TempDaycare, 2 + 1 + PKX.SIZE_1PARTY + StringLength, StringLength);
|
||||
Array.Copy(rawDC, 1 + StringLength, TempDaycare, 2 + 1 + PKX.SIZE_1PARTY, StringLength);
|
||||
Array.Copy(rawDC, 1 + 2 * StringLength, TempDaycare, 2 + 1, PKX.SIZE_1STORED);
|
||||
PokemonList1 daycareList = new PokemonList1(TempDaycare, PokemonList1.CapacityType.Single, Japanese);
|
||||
daycareList.GetBytes().CopyTo(Data, getPartyOffset(7));
|
||||
Daycare = getPartyOffset(7);
|
||||
*/
|
||||
// Enable Pokedex editing
|
||||
Console.WriteLine(SIZE_STOREDBOX.ToString("X"));
|
||||
PokeDex = 0;
|
||||
|
||||
if (!Exportable)
|
||||
resetBoxes();
|
||||
}
|
||||
|
||||
private const int SIZE_RESERVED = 0x8000; // unpacked box data
|
||||
public override byte[] Write(bool DSV)
|
||||
{
|
||||
for (int i = 0; i < BoxCount; i++)
|
||||
{
|
||||
PokemonList1 boxPL = new PokemonList1(Japanese ? PokemonList1.CapacityType.StoredJP : PokemonList1.CapacityType.Stored, Japanese);
|
||||
int slot = 0;
|
||||
for (int j = 0; j < boxPL.Pokemon.Length; j++)
|
||||
{
|
||||
PK1 boxPK = (PK1) getPKM(getData(getBoxOffset(i) + j*SIZE_STORED, SIZE_STORED));
|
||||
if (boxPK.Species > 0)
|
||||
boxPL[slot++] = boxPK;
|
||||
}
|
||||
if (i < BoxCount / 2)
|
||||
boxPL.GetBytes().CopyTo(Data, 0x4000 + i * SIZE_STOREDBOX);
|
||||
else
|
||||
boxPL.GetBytes().CopyTo(Data, 0x6000 + (i - BoxCount / 2) * SIZE_STOREDBOX);
|
||||
if (i == CurrentBox)
|
||||
boxPL.GetBytes().CopyTo(Data, Japanese ? 0x302D : 0x30C0);
|
||||
}
|
||||
|
||||
PokemonList1 partyPL = new PokemonList1(PokemonList1.CapacityType.Party, Japanese);
|
||||
int pSlot = 0;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
PK1 partyPK = (PK1)getPKM(getData(getPartyOffset(i), SIZE_STORED));
|
||||
if (partyPK.Species > 0)
|
||||
partyPL[pSlot++] = partyPK;
|
||||
}
|
||||
partyPL.GetBytes().CopyTo(Data, Japanese ? 0x2ED5 : 0x2F2C);
|
||||
|
||||
// Daycare is read-only, but in case it ever becomes editable, copy it back in.
|
||||
byte[] rawDC = getData(getDaycareSlotOffset(loc: 0, slot: 0), SIZE_STORED);
|
||||
byte[] dc = new byte[1 + 2*StringLength + PKX.SIZE_1STORED];
|
||||
dc[0] = rawDC[0];
|
||||
Array.Copy(rawDC, 2 + 1 + PKX.SIZE_1PARTY + StringLength, dc, 1, StringLength);
|
||||
Array.Copy(rawDC, 2 + 1 + PKX.SIZE_1PARTY, dc, 1 + StringLength, StringLength);
|
||||
Array.Copy(rawDC, 2 + 1, dc, 1 + 2*StringLength, PKX.SIZE_1STORED);
|
||||
dc.CopyTo(Data, Japanese ? 0x2CA7 : 0x2CF4);
|
||||
|
||||
setChecksums();
|
||||
byte[] outData = new byte[Data.Length - SIZE_RESERVED];
|
||||
Array.Copy(Data, outData, outData.Length);
|
||||
return outData;
|
||||
}
|
||||
|
||||
|
||||
// Configuration
|
||||
public override SaveFile Clone() { return new SAV2(Data.Take(Data.Length - SIZE_RESERVED).ToArray()); }
|
||||
|
||||
public override int SIZE_STORED => Japanese ? PKX.SIZE_2JLIST : PKX.SIZE_2ULIST;
|
||||
public override int SIZE_PARTY => Japanese ? PKX.SIZE_2JLIST : PKX.SIZE_2ULIST;
|
||||
|
||||
public int SIZE_BOX => BoxSlotCount*SIZE_STORED;
|
||||
|
||||
public int SIZE_STOREDBOX => PokemonList2.GetDataLength(Japanese ? PokemonList2.CapacityType.StoredJP : PokemonList2.CapacityType.Stored, Japanese);
|
||||
|
||||
public override PKM BlankPKM => new PK2(null, null, Japanese);
|
||||
protected override Type PKMType => typeof(PK2);
|
||||
|
||||
public override int MaxMoveID => 251;
|
||||
public override int MaxSpeciesID => 251;
|
||||
public override int MaxAbilityID => 0;
|
||||
public override int MaxItemID => 255;
|
||||
public override int MaxBallID => 0;
|
||||
public override int MaxGameID => 99; // What do I set this to...?
|
||||
|
||||
public override int BoxCount => Japanese ? 9 : 14;
|
||||
public override int MaxEV => 65535;
|
||||
public override int MaxIV => 15;
|
||||
public override int Generation => 2;
|
||||
protected override int GiftCountMax => 0;
|
||||
public override int OTLength => Japanese ? 5 : 7;
|
||||
public override int NickLength => Japanese ? 5 : 10;
|
||||
public override int BoxSlotCount => Japanese ? 30 : 20;
|
||||
|
||||
public override bool HasParty => true;
|
||||
private int StringLength => Japanese ? PK2.STRLEN_J : PK2.STRLEN_U;
|
||||
|
||||
|
||||
// Offsets
|
||||
protected int OptionsOffset { get; set; } = int.MinValue;
|
||||
protected int DaylightSavingsOffset { get; set; } = int.MinValue;
|
||||
protected int TimePlayedOffset { get; set; } = int.MinValue;
|
||||
protected int PaletteOffset { get; set; } = int.MinValue;
|
||||
protected int MoneyOffset { get; set; } = int.MinValue;
|
||||
protected int JohtoBadgesOffset { get; set; } = int.MinValue;
|
||||
protected int CurrentBoxIndexOffset { get; set; } = int.MinValue;
|
||||
protected int BoxNamesOffset { get; set; } = int.MinValue;
|
||||
protected int PartyOffset { get; set; } = int.MinValue;
|
||||
protected int PokedexSeenOffset { get; set; } = int.MinValue;
|
||||
protected int PokedexCaughtOffset { get; set; } = int.MinValue;
|
||||
protected int CurrentBoxOffset { get; set; } = int.MinValue;
|
||||
protected int GenderOffset { get; set; } = int.MinValue;
|
||||
|
||||
// Checksums
|
||||
protected override void setChecksums()
|
||||
{
|
||||
ushort accum = 0;
|
||||
for (int i = 0x2009; i <= 0x2B3A; i++)
|
||||
accum += Data[i];
|
||||
if (Version == GameVersion.C && Japanese)
|
||||
BitConverter.GetBytes(Util.SwapEndianness(accum)).CopyTo(Data, 0x2D0D);
|
||||
|
||||
for (int i = 0x2B3B; i <= 0x2B82; i++)
|
||||
accum += Data[i];
|
||||
if (Version == GameVersion.C && !Japanese)
|
||||
BitConverter.GetBytes(Util.SwapEndianness(accum)).CopyTo(Data, 0x2D0D);
|
||||
|
||||
/* TODO: Find Japanese GS Checksum region */
|
||||
|
||||
for (int i = 0x2B83; i <= 0x2D68; i++)
|
||||
accum += Data[i];
|
||||
if (Version == GameVersion.GS && !Japanese)
|
||||
BitConverter.GetBytes(Util.SwapEndianness(accum)).CopyTo(Data, 0x2D69);
|
||||
|
||||
}
|
||||
public override bool ChecksumsValid
|
||||
{
|
||||
get
|
||||
{
|
||||
ushort accum = 0;
|
||||
for (int i = 0x2009; i <= 0x2B3A; i++)
|
||||
accum += Data[i];
|
||||
if (Version == GameVersion.C && Japanese)
|
||||
return accum == Util.SwapEndianness(BitConverter.ToUInt16(Data, 0x2D0D)); // Japanese Crystal
|
||||
|
||||
for (int i = 0x2B3B; i <= 0x2B82; i++)
|
||||
accum += Data[i];
|
||||
if (Version == GameVersion.C && !Japanese)
|
||||
return accum == Util.SwapEndianness(BitConverter.ToUInt16(Data, 0x2D0D)); // Japanese Crystal
|
||||
|
||||
/* TODO: Find Japanese GS Checksum region */
|
||||
|
||||
for (int i = 0x2B83; i <= 0x2D68; i++)
|
||||
accum += Data[i];
|
||||
if (Version == GameVersion.GS && !Japanese)
|
||||
return accum == Util.SwapEndianness(BitConverter.ToUInt16(Data, 0x2D69)); // US Gold/Silver
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public override string ChecksumInfo => ChecksumsValid ? "Checksum valid." : "Checksum invalid";
|
||||
|
||||
// Trainer Info
|
||||
public override GameVersion Version { get; protected set; }
|
||||
|
||||
public override string OT
|
||||
{
|
||||
get { return PKX.getG1Str(Data.Skip(0x200B).Take(StringLength).ToArray(), Japanese); }
|
||||
set
|
||||
{
|
||||
byte[] strdata = PKX.setG1Str(value, Japanese);
|
||||
if (strdata.Length > StringLength)
|
||||
throw new ArgumentException("OT Name too long for given save file.");
|
||||
strdata.CopyTo(Data, 0x200B);
|
||||
}
|
||||
}
|
||||
public override int Gender
|
||||
{
|
||||
get { return 0; }
|
||||
set { }
|
||||
}
|
||||
public override ushort TID
|
||||
{
|
||||
get { return Util.SwapEndianness(BitConverter.ToUInt16(Data, 0x2009)); }
|
||||
set { BitConverter.GetBytes(Util.SwapEndianness(value)).CopyTo(Data, 0x2009); }
|
||||
}
|
||||
public override ushort SID
|
||||
{
|
||||
get { return 0; }
|
||||
set { }
|
||||
}
|
||||
public override int PlayedHours
|
||||
{
|
||||
get { return BitConverter.ToUInt16(Data, Japanese ? 0x2CA0 : 0x2CED); }
|
||||
set { BitConverter.GetBytes((ushort)value).CopyTo(Data, Japanese ? 0x2CA0 : 0x2CED); }
|
||||
}
|
||||
public override int PlayedMinutes
|
||||
{
|
||||
get { return Data[Japanese ? 0x2CA2 : 0x2CEF]; }
|
||||
set { Data[Japanese ? 0x2CA2 : 0x2CEF] = (byte)value; }
|
||||
}
|
||||
public override int PlayedSeconds
|
||||
{
|
||||
get { return Data[Japanese ? 0x2CA3 : 0x2CF0]; }
|
||||
set { Data[Japanese ? 0x2CA3 : 0x2CF0] = (byte)value; }
|
||||
}
|
||||
|
||||
public int Badges
|
||||
{
|
||||
get { return Data[Japanese ? 0x25F8 : 0x2602]; }
|
||||
set { if (value < 0) return; Data[Japanese ? 0x25F8 : 0x2602] = (byte)value; }
|
||||
}
|
||||
private byte Options
|
||||
{
|
||||
get { return Data[Japanese ? 0x25F7 : 0x2601]; }
|
||||
set { Data[Japanese ? 0x25F7 : 0x2601] = value; }
|
||||
}
|
||||
public bool BattleEffects
|
||||
{
|
||||
get { return (Options & 0x80) == 0; }
|
||||
set { Options = (byte)((Options & 0x7F) | (value ? 0 : 0x80)); }
|
||||
}
|
||||
public bool BattleStyleSwitch
|
||||
{
|
||||
get { return (Options & 0x40) == 0; }
|
||||
set { Options = (byte)((Options & 0xBF) | (value ? 0 : 0x40)); }
|
||||
}
|
||||
public int Sound
|
||||
{
|
||||
get { return (Options & 0x30) >> 4; }
|
||||
set
|
||||
{
|
||||
var new_sound = value;
|
||||
if (new_sound > 3)
|
||||
new_sound = 3;
|
||||
if (new_sound < 0)
|
||||
new_sound = 0;
|
||||
Options = (byte)((Options & 0xCF) | (new_sound << 4));
|
||||
}
|
||||
}
|
||||
public int TextSpeed
|
||||
{
|
||||
get { return Options & 0x7; }
|
||||
set
|
||||
{
|
||||
var new_speed = value;
|
||||
if (new_speed > 7)
|
||||
new_speed = 7;
|
||||
if (new_speed < 0)
|
||||
new_speed = 0;
|
||||
Options = (byte)((Options & 0xF8) | new_speed);
|
||||
}
|
||||
}
|
||||
public override uint Money
|
||||
{
|
||||
get { return uint.Parse((Util.SwapEndianness(BitConverter.ToUInt32(Data, Japanese ? 0x25EE : 0x25F3)) >> 8).ToString("X6")); }
|
||||
set
|
||||
{
|
||||
BitConverter.GetBytes(Util.SwapEndianness(Convert.ToUInt32(value.ToString("000000"), 16))).Skip(1).ToArray().CopyTo(Data, Japanese ? 0x25EE : 0x25F3);
|
||||
}
|
||||
}
|
||||
public uint Coin
|
||||
{
|
||||
get
|
||||
{
|
||||
return uint.Parse(Util.SwapEndianness(BitConverter.ToUInt16(Data, Japanese ? 0x2846 : 0x2850)).ToString("X4"));
|
||||
}
|
||||
set
|
||||
{
|
||||
BitConverter.GetBytes(Util.SwapEndianness(Convert.ToUInt16(value.ToString("0000"), 16))).ToArray().CopyTo(Data, Japanese ? 0x2846 : 0x2850);
|
||||
}
|
||||
}
|
||||
|
||||
private readonly ushort[] LegalItems, LegalKeyItems, LegalBalls, LegalTMHMs, LegalBerries;
|
||||
public override InventoryPouch[] Inventory
|
||||
{
|
||||
get
|
||||
{
|
||||
ushort[] legalItems = LegalItems;
|
||||
InventoryPouch[] pouch =
|
||||
{
|
||||
new InventoryPouch(InventoryType.Items, legalItems, 99, Japanese ? 0x25C4 : 0x25C9, 20),
|
||||
new InventoryPouch(InventoryType.MailItems, legalItems, 99, Japanese ? 0x27DC : 0x27E6, 50)
|
||||
};
|
||||
foreach (var p in pouch)
|
||||
{
|
||||
p.getPouchG1(ref Data);
|
||||
}
|
||||
return pouch;
|
||||
}
|
||||
set
|
||||
{
|
||||
foreach (var p in value)
|
||||
{
|
||||
int ofs = 0;
|
||||
for (int i = 0; i < p.Count; i++)
|
||||
{
|
||||
while (p.Items[ofs].Count == 0)
|
||||
ofs++;
|
||||
p.Items[i] = p.Items[ofs++];
|
||||
}
|
||||
while (ofs < p.Items.Length)
|
||||
p.Items[ofs++] = new InventoryItem { Count = 0, Index = 0 };
|
||||
p.setPouchG1(ref Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
public override int getDaycareSlotOffset(int loc, int slot)
|
||||
{
|
||||
return Daycare;
|
||||
}
|
||||
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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Storage
|
||||
public override int PartyCount
|
||||
{
|
||||
get { return Data[PartyOffset]; }
|
||||
protected set
|
||||
{
|
||||
Data[PartyOffset] = (byte)value;
|
||||
}
|
||||
}
|
||||
public override int getBoxOffset(int box)
|
||||
{
|
||||
return Data.Length - SIZE_RESERVED + box * SIZE_BOX;
|
||||
}
|
||||
public override int getPartyOffset(int slot)
|
||||
{
|
||||
return Data.Length - SIZE_RESERVED + BoxCount * SIZE_BOX + slot * SIZE_STORED;
|
||||
}
|
||||
public override int CurrentBox
|
||||
{
|
||||
get { return Data[CurrentBoxIndexOffset] & 0x7F; }
|
||||
set { Data[CurrentBoxIndexOffset] = (byte)((Data[Japanese ? 0x2842 : 0x284C] & 0x80) | (value & 0x7F)); }
|
||||
}
|
||||
public override int getBoxWallpaper(int box)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
public override string getBoxName(int box)
|
||||
{
|
||||
return PKX.getG1Str(Data.Skip(BoxNamesOffset + box*9).Take(9).ToArray(), Japanese);
|
||||
}
|
||||
public override void setBoxName(int box, string value)
|
||||
{
|
||||
// Don't allow for custom box names
|
||||
}
|
||||
|
||||
public override PKM getPKM(byte[] data)
|
||||
{
|
||||
if (data.Length == SIZE_STORED)
|
||||
return new PokemonList2(data, PokemonList2.CapacityType.Single, Japanese)[0];
|
||||
return new PK2(data);
|
||||
}
|
||||
public override byte[] decryptPKM(byte[] data)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
// Pokédex
|
||||
public override bool getSeen(PKM pkm)
|
||||
{
|
||||
if (pkm.Species == 0)
|
||||
return false;
|
||||
if (pkm.Species > MaxSpeciesID)
|
||||
return false;
|
||||
if (Version == GameVersion.Unknown)
|
||||
return false;
|
||||
|
||||
int bit = pkm.Species - 1;
|
||||
int ofs = bit >> 3;
|
||||
byte bitval = (byte)(1 << (bit & 7));
|
||||
// Get the Seen Flag
|
||||
return (Data[PokedexSeenOffset + ofs] & bitval) != 0;
|
||||
}
|
||||
public override bool getCaught(PKM pkm)
|
||||
{
|
||||
if (pkm.Species == 0)
|
||||
return false;
|
||||
if (pkm.Species > MaxSpeciesID)
|
||||
return false;
|
||||
if (Version == GameVersion.Unknown)
|
||||
return false;
|
||||
|
||||
int bit = pkm.Species - 1;
|
||||
int ofs = bit >> 3;
|
||||
byte bitval = (byte)(1 << (bit & 7));
|
||||
// Get the Caught Flag
|
||||
return (Data[PokedexCaughtOffset + ofs] & bitval) != 0;
|
||||
}
|
||||
protected internal override void setSeen(PKM pkm, bool seen = true)
|
||||
{
|
||||
if (pkm.Species == 0)
|
||||
return;
|
||||
if (pkm.Species > MaxSpeciesID)
|
||||
return;
|
||||
if (Version == GameVersion.Unknown)
|
||||
return;
|
||||
|
||||
int bit = pkm.Species - 1;
|
||||
int ofs = bit >> 3;
|
||||
byte bitval = (byte)(1 << (bit & 7));
|
||||
// Set the Seen Flag
|
||||
Data[PokedexSeenOffset + ofs] &= (byte)(~bitval);
|
||||
if (seen)
|
||||
Data[PokedexSeenOffset + ofs] |= bitval;
|
||||
}
|
||||
protected internal override void setCaught(PKM pkm, bool caught = true)
|
||||
{
|
||||
if (pkm.Species == 0)
|
||||
return;
|
||||
if (pkm.Species > MaxSpeciesID)
|
||||
return;
|
||||
if (Version == GameVersion.Unknown)
|
||||
return;
|
||||
|
||||
int bit = pkm.Species - 1;
|
||||
int ofs = bit >> 3;
|
||||
byte bitval = (byte)(1 << (bit & 7));
|
||||
// Set the Captured Flag
|
||||
Data[PokedexCaughtOffset + ofs] &= (byte)(~bitval);
|
||||
if (caught)
|
||||
Data[PokedexCaughtOffset + ofs] |= bitval;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -63,6 +63,8 @@ namespace PKHeX
|
|||
public bool RS => Version == GameVersion.RS;
|
||||
public bool RBY => Version == GameVersion.RBY;
|
||||
|
||||
public bool GSC => Version == GameVersion.GS || Version == GameVersion.C;
|
||||
|
||||
public virtual int MaxMoveID => int.MaxValue;
|
||||
public virtual int MaxSpeciesID => int.MaxValue;
|
||||
public virtual int MaxAbilityID => int.MaxValue;
|
||||
|
|
|
@ -3,11 +3,15 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace PKHeX
|
||||
{
|
||||
public enum GameVersion
|
||||
{
|
||||
/* I don't want to assign Gen I/II... */
|
||||
GS = -4,
|
||||
C = -3,
|
||||
Invalid = -2,
|
||||
Any = -1,
|
||||
Unknown = 0,
|
||||
|
@ -45,6 +49,10 @@ namespace PKHeX
|
|||
internal const int SIZE_G4RAW = 0x80000;
|
||||
internal const int SIZE_G3RAW = 0x20000;
|
||||
internal const int SIZE_G3RAWHALF = 0x10000;
|
||||
internal const int SIZE_G2RAW = 0x8000;
|
||||
internal const int SIZE_G2BAT = 0x802C;
|
||||
internal const int SIZE_G2EMU = 0x10000;
|
||||
internal const int SIZE_G2EMUBAT = 0x1002C;
|
||||
internal const int SIZE_G1RAW = 0x8000;
|
||||
internal const int SIZE_G1BAT = 0x802C;
|
||||
|
||||
|
@ -57,6 +65,8 @@ namespace PKHeX
|
|||
{
|
||||
if (getIsG1SAV(data) != GameVersion.Invalid)
|
||||
return 1;
|
||||
if (getIsG2SAV(data) != GameVersion.Invalid)
|
||||
return 2;
|
||||
if (getIsG3SAV(data) != GameVersion.Invalid)
|
||||
return 3;
|
||||
if (getIsG4SAV(data) != GameVersion.Invalid)
|
||||
|
@ -108,6 +118,71 @@ namespace PKHeX
|
|||
}
|
||||
return true;
|
||||
}
|
||||
/// <summary>Determines the type of 2nd 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>
|
||||
public static GameVersion getIsG2SAV(byte[] data)
|
||||
{
|
||||
if (data.Length != SIZE_G2RAW && data.Length != SIZE_G2BAT && data.Length != SIZE_G2EMU && data.Length != SIZE_G2EMUBAT)
|
||||
return GameVersion.Invalid;
|
||||
|
||||
// Check if it's not an american save or a japanese save
|
||||
if (getIsG2SAVU(data) != GameVersion.Invalid)
|
||||
return getIsG2SAVU(data);
|
||||
if (getIsG2SAVJ(data) != GameVersion.Invalid)
|
||||
return getIsG2SAVJ(data);
|
||||
return GameVersion.Invalid;
|
||||
}
|
||||
/// <summary>Determines if 2nd gen save is non-japanese</summary>
|
||||
/// <param name="data">Save data of which to determine the region</param>
|
||||
/// <returns>True if a valid non-japanese save, False otherwise.</returns>
|
||||
public static GameVersion getIsG2SAVU(byte[] data)
|
||||
{
|
||||
bool gs = true;
|
||||
bool c = true;
|
||||
foreach (int ofs in new[] { 0x288A, 0x2D6C })
|
||||
{
|
||||
byte num_entries = data[ofs];
|
||||
if (num_entries > 20 || data[ofs + 1 + num_entries] != 0xFF)
|
||||
gs = false;
|
||||
}
|
||||
foreach (int ofs in new[] { 0x2865, 0x2D10 })
|
||||
{
|
||||
byte num_entries = data[ofs];
|
||||
if (num_entries > 20 || data[ofs + 1 + num_entries] != 0xFF)
|
||||
c = false;
|
||||
}
|
||||
if (gs)
|
||||
return GameVersion.GS;
|
||||
if (c)
|
||||
return GameVersion.C;
|
||||
return GameVersion.Invalid;
|
||||
}
|
||||
/// <summary>Determines if 2nd gen save is japanese</summary>
|
||||
/// <param name="data">Save data of which to determine the region</param>
|
||||
/// <returns>True if a valid japanese save, False otherwise.</returns>
|
||||
public static GameVersion getIsG2SAVJ(byte[] data)
|
||||
{
|
||||
bool gs = true;
|
||||
bool c = true;
|
||||
foreach (int ofs in new[] { 0x283E, 0x2D10 })
|
||||
{
|
||||
byte num_entries = data[ofs];
|
||||
if (num_entries > 30 || data[ofs + 1 + num_entries] != 0xFF)
|
||||
gs = false;
|
||||
}
|
||||
foreach (int ofs in new[] { 0x281A, 0x2D10 })
|
||||
{
|
||||
byte num_entries = data[ofs];
|
||||
if (num_entries > 30 || data[ofs + 1 + num_entries] != 0xFF)
|
||||
c = false;
|
||||
}
|
||||
if (gs)
|
||||
return GameVersion.GS;
|
||||
if (c)
|
||||
return GameVersion.C;
|
||||
return GameVersion.Invalid;
|
||||
}
|
||||
/// <summary>Determines the type of 3th 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>
|
||||
|
@ -218,6 +293,10 @@ namespace PKHeX
|
|||
case GameVersion.RBY:
|
||||
return GameVersion.RBY;
|
||||
|
||||
case GameVersion.GS:
|
||||
case GameVersion.C:
|
||||
return GameVersion.GSC;
|
||||
|
||||
case GameVersion.R:
|
||||
case GameVersion.S:
|
||||
return GameVersion.RS;
|
||||
|
@ -270,6 +349,8 @@ namespace PKHeX
|
|||
{
|
||||
case 1:
|
||||
return new SAV1(data);
|
||||
case 2:
|
||||
return new SAV2(data);
|
||||
case 3:
|
||||
return new SAV3(data);
|
||||
case 4:
|
||||
|
|
Loading…
Reference in a new issue