Ejemplo n.º 1
0
        /// <summary>
        /// Creates an instance of <see cref="PKM"/> from the given data.
        /// </summary>
        /// <param name="data">Raw data of the Pokemon file.</param>
        /// <param name="ident">Optional identifier for the Pokemon.  Usually the full path of the source file.</param>
        /// <returns>An instance of <see cref="PKM"/> created from the given <paramref name="data"/>, or null if <paramref name="data"/> is invalid.</returns>
        public static PKM getPKMfromBytes(byte[] data, string ident = null)
        {
            checkEncrypted(ref data);
            switch (getPKMDataFormat(data))
            {
            case 1:
                var PL1 = new PokemonList1(data, PokemonList1.CapacityType.Single, data.Length == PKX.SIZE_1JLIST);
                if (ident != null)
                {
                    PL1[0].Identifier = ident;
                }
                return(PL1[0]);

            case 2:
                var PL2 = new PokemonList2(data, PokemonList2.CapacityType.Single, data.Length == PKX.SIZE_2JLIST);
                if (ident != null)
                {
                    PL2[0].Identifier = ident;
                }
                return(PL2[0]);

            case 3:
                switch (data.Length)
                {
                case PKX.SIZE_3CSTORED: return(new CK3(data, ident));

                case PKX.SIZE_3XSTORED: return(new XK3(data, ident));

                default: return(new PK3(data, ident));
                }

            case 4:
                var pk = new PK4(data, ident);
                if (!pk.Valid || pk.Sanity != 0)
                {
                    var bk = new BK4(data, ident);
                    if (bk.Valid)
                    {
                        return(bk);
                    }
                }
                return(pk);

            case 5:
                return(new PK5(data, ident));

            case 6:
                PKM pkx = new PK6(data, ident);
                if (pkx.SM)
                {
                    pkx = new PK7(data, ident);
                }
                return(pkx);

            default:
                return(null);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Creates an instance of <see cref="PKM"/> from the given data.
        /// </summary>
        /// <param name="data">Raw data of the Pokemon file.</param>
        /// <param name="ident">Optional identifier for the Pokemon.  Usually the full path of the source file.</param>
        /// <param name="prefer">Optional identifier for the preferred generation.  Usually the generation of the destination save file.</param>
        /// <returns>An instance of <see cref="PKM"/> created from the given <paramref name="data"/>, or null if <paramref name="data"/> is invalid.</returns>
        public static PKM GetPKMfromBytes(byte[] data, string ident = null, int prefer = 7)
        {
            int format = GetPKMDataFormat(data);

            switch (format)
            {
            case 1:
                var PL1 = new PokemonList1(data, PokemonList1.CapacityType.Single, data.Length == PKX.SIZE_1JLIST);
                if (ident != null)
                {
                    PL1[0].Identifier = ident;
                }
                return(PL1[0]);

            case 2:
                var PL2 = new PokemonList2(data, PokemonList2.CapacityType.Single, data.Length == PKX.SIZE_2JLIST);
                if (ident != null)
                {
                    PL2[0].Identifier = ident;
                }
                return(PL2[0]);

            case 3:
                switch (data.Length)
                {
                case PKX.SIZE_3CSTORED: return(new CK3(data, ident));

                case PKX.SIZE_3XSTORED: return(new XK3(data, ident));

                default: return(new PK3(data, ident));
                }

            case 4:
                var pk = new PK4(data, ident);
                if (!pk.Valid || pk.Sanity != 0)
                {
                    var bk = new BK4(data, ident);
                    if (bk.Valid)
                    {
                        return(bk);
                    }
                }
                return(pk);

            case 5:
                return(new PK5(data, ident));

            case 6:
                var pkx = new PK6(data, ident);
                return(CheckPKMFormat7(pkx, prefer));

            default:
                return(null);
            }
        }
Ejemplo n.º 3
0
Archivo: SAV2.cs Proyecto: kwsch/PKHeX
        public SAV2(byte[] data = null, GameVersion versionOverride = GameVersion.Any)
        {
            Data = data == null ? new byte[SaveUtil.SIZE_G2RAW_U] : (byte[])data.Clone();
            BAK = (byte[])Data.Clone();
            Exportable = !Data.SequenceEqual(new byte[Data.Length]);

            if (data == null)
                Version = GameVersion.C;
            else if (versionOverride != GameVersion.Any)
                Version = versionOverride;
            else
                Version = SaveUtil.getIsG2SAV(Data);

            if (Version == GameVersion.Invalid)
                return;

            Japanese = SaveUtil.getIsG2SAVJ(Data) != GameVersion.Invalid;
            if (Japanese && Data.Length < SaveUtil.SIZE_G2RAW_J)
                Array.Resize(ref Data, SaveUtil.SIZE_G2RAW_J);

            Box = Data.Length;
            Array.Resize(ref Data, Data.Length + SIZE_RESERVED);
            Party = getPartyOffset(0);
            
            Personal = Version == GameVersion.GS ? PersonalTable.GS : PersonalTable.C;

            getSAVOffsets();

            LegalItems = Legal.Pouch_Items_GSC;
            LegalBalls = Legal.Pouch_Ball_GSC;
            LegalKeyItems = Version == GameVersion.C ? Legal.Pouch_Key_C : Legal.Pouch_Key_GS;
            LegalTMHMs = Legal.Pouch_TMHM_GSC;
            HeldItems = Legal.HeldItems_GSC;
            
            // 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));
                }
            }

            // Daycare currently undocumented for all Gen II games.

            // Enable Pokedex editing
            PokeDex = 0;

            if (!Exportable)
                resetBoxes();
        }
Ejemplo n.º 4
0
Archivo: SAV2.cs Proyecto: kwsch/PKHeX
        private const int SIZE_RESERVED = 0x8000; // unpacked box data
        public override byte[] Write(bool DSV)
        {
            for (int i = 0; i < BoxCount; i++)
            {
                PokemonList2 boxPL = new PokemonList2(Japanese ? PokemonList2.CapacityType.StoredJP : PokemonList2.CapacityType.Stored, Japanese);
                int slot = 0;
                for (int j = 0; j < boxPL.Pokemon.Length; j++)
                {
                    PK2 boxPK = (PK2) getPKM(getData(getBoxOffset(i) + j*SIZE_STORED, SIZE_STORED));
                    if (boxPK.Species > 0)
                        boxPL[slot++] = boxPK;
                }
                if (i < (Japanese ? 6 : 7))
                    boxPL.GetBytes().CopyTo(Data, 0x4000 + i * (SIZE_STOREDBOX + 2));
                else
                    boxPL.GetBytes().CopyTo(Data, 0x6000 + (i - (Japanese ? 6 : 7)) * (SIZE_STOREDBOX + 2));
                if (i == CurrentBox)
                    boxPL.GetBytes().CopyTo(Data, CurrentBoxOffset);
            }

            PokemonList2 partyPL = new PokemonList2(PokemonList2.CapacityType.Party, Japanese);
            int pSlot = 0;
            for (int i = 0; i < 6; i++)
            {
                PK2 partyPK = (PK2)getPKM(getData(getPartyOffset(i), SIZE_STORED));
                if (partyPK.Species > 0)
                    partyPL[pSlot++] = partyPK;
            }
            partyPL.GetBytes().CopyTo(Data, PartyOffset);

            setChecksums();
            if (Version == GameVersion.C && !Japanese)
            {
                Array.Copy(Data, 0x2009, Data, 0x1209, 0xB7A);
            }
            if (Version == GameVersion.C && Japanese)
            {
                Array.Copy(Data, 0x2009, Data, 0x7209, 0xB32);
            }
            if (Version == GameVersion.GS && !Japanese)
            {
                Array.Copy(Data, 0x2009, Data, 0x15C7, 0x222F - 0x2009);
                Array.Copy(Data, 0x222F, Data, 0x3D69, 0x23D9 - 0x222F);
                Array.Copy(Data, 0x23D9, Data, 0x0C6B, 0x2856 - 0x23D9);
                Array.Copy(Data, 0x2856, Data, 0x7E39, 0x288A - 0x2856);
                Array.Copy(Data, 0x288A, Data, 0x10E8, 0x2D69 - 0x288A);
            }
            if (Version == GameVersion.GS && Japanese)
            {
                Array.Copy(Data, 0x2009, Data, 0x7209, 0xC83);
            }
            byte[] outData = new byte[Data.Length - SIZE_RESERVED];
            Array.Copy(Data, outData, outData.Length);
            return outData;
        }
Ejemplo n.º 5
0
        public SAV2(byte[] data = null, GameVersion versionOverride = GameVersion.Any)
        {
            Data       = data == null ? new byte[SaveUtil.SIZE_G2RAW_U] : (byte[])data.Clone();
            BAK        = (byte[])Data.Clone();
            Exportable = !Data.SequenceEqual(new byte[Data.Length]);

            if (data == null)
            {
                Version = GameVersion.C;
            }
            else if (versionOverride != GameVersion.Any)
            {
                Version = versionOverride;
            }
            else
            {
                Version = SaveUtil.GetIsG2SAV(Data);
            }

            if (Version == GameVersion.Invalid)
            {
                return;
            }

            Japanese = SaveUtil.GetIsG2SAVJ(Data) != GameVersion.Invalid;
            if (Japanese && Data.Length < SaveUtil.SIZE_G2RAW_J)
            {
                Array.Resize(ref Data, SaveUtil.SIZE_G2RAW_J);
            }

            Box = Data.Length;
            Array.Resize(ref Data, Data.Length + SIZE_RESERVED);
            Party = GetPartyOffset(0);

            Personal = Version == GameVersion.GS ? PersonalTable.GS : PersonalTable.C;

            GetSAVOffsets();

            LegalItems    = Legal.Pouch_Items_GSC;
            LegalBalls    = Legal.Pouch_Ball_GSC;
            LegalKeyItems = Version == GameVersion.C ? Legal.Pouch_Key_C : Legal.Pouch_Key_GS;
            LegalTMHMs    = Legal.Pouch_TMHM_GSC;
            HeldItems     = Legal.HeldItems_GSC;

            // 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));
                }
            }

            // Daycare currently undocumented for all Gen II games.

            // Enable Pokedex editing
            PokeDex = 0;

            if (!Exportable)
            {
                ClearBoxes();
            }
        }
Ejemplo n.º 6
0
        private const int SIZE_RESERVED = 0x8000; // unpacked box data

        protected override byte[] Write(bool DSV)
        {
            for (int i = 0; i < BoxCount; i++)
            {
                PokemonList2 boxPL = new PokemonList2(Japanese ? PokemonList2.CapacityType.StoredJP : PokemonList2.CapacityType.Stored, Japanese);
                int          slot  = 0;
                for (int j = 0; j < boxPL.Pokemon.Length; j++)
                {
                    PK2 boxPK = (PK2)GetPKM(GetData(GetBoxOffset(i) + j * SIZE_STORED, SIZE_STORED));
                    if (boxPK.Species > 0)
                    {
                        boxPL[slot++] = boxPK;
                    }
                }
                if (i < (Japanese ? 6 : 7))
                {
                    boxPL.GetBytes().CopyTo(Data, 0x4000 + i * (SIZE_STOREDBOX + 2));
                }
                else
                {
                    boxPL.GetBytes().CopyTo(Data, 0x6000 + (i - (Japanese ? 6 : 7)) * (SIZE_STOREDBOX + 2));
                }
                if (i == CurrentBox)
                {
                    boxPL.GetBytes().CopyTo(Data, CurrentBoxOffset);
                }
            }

            PokemonList2 partyPL = new PokemonList2(PokemonList2.CapacityType.Party, Japanese);
            int          pSlot   = 0;

            for (int i = 0; i < 6; i++)
            {
                PK2 partyPK = (PK2)GetPKM(GetData(GetPartyOffset(i), SIZE_STORED));
                if (partyPK.Species > 0)
                {
                    partyPL[pSlot++] = partyPK;
                }
            }
            partyPL.GetBytes().CopyTo(Data, PartyOffset);

            SetChecksums();
            if (Version == GameVersion.C && !Japanese)
            {
                Array.Copy(Data, 0x2009, Data, 0x1209, 0xB7A);
            }
            if (Version == GameVersion.C && Japanese)
            {
                Array.Copy(Data, 0x2009, Data, 0x7209, 0xADA);
            }
            if (Version == GameVersion.GS && !Japanese)
            {
                Array.Copy(Data, 0x2009, Data, 0x15C7, 0x222F - 0x2009);
                Array.Copy(Data, 0x222F, Data, 0x3D69, 0x23D9 - 0x222F);
                Array.Copy(Data, 0x23D9, Data, 0x0C6B, 0x2856 - 0x23D9);
                Array.Copy(Data, 0x2856, Data, 0x7E39, 0x288A - 0x2856);
                Array.Copy(Data, 0x288A, Data, 0x10E8, 0x2D69 - 0x288A);
            }
            if (Version == GameVersion.GS && Japanese)
            {
                Array.Copy(Data, 0x2009, Data, 0x7209, 0xC83);
            }
            byte[] outData = new byte[Data.Length - SIZE_RESERVED];
            Array.Copy(Data, outData, outData.Length);
            return(outData);
        }
Ejemplo n.º 7
0
        protected override byte[] Write(bool DSV)
        {
            for (int i = 0; i < BoxCount; i++)
            {
                PokemonList2 boxPL = new PokemonList2(Japanese ? PokemonList2.CapacityType.StoredJP : PokemonList2.CapacityType.Stored, Japanese);
                int          slot  = 0;
                for (int j = 0; j < boxPL.Pokemon.Length; j++)
                {
                    PK2 boxPK = (PK2)GetPKM(GetData(GetBoxOffset(i) + j * SIZE_STORED, SIZE_STORED));
                    if (boxPK.Species > 0)
                    {
                        boxPL[slot++] = boxPK;
                    }
                }
                if (i < (Japanese ? 6 : 7))
                {
                    boxPL.GetBytes().CopyTo(Data, 0x4000 + i * (SIZE_STOREDBOX + 2));
                }
                else
                {
                    boxPL.GetBytes().CopyTo(Data, 0x6000 + (i - (Japanese ? 6 : 7)) * (SIZE_STOREDBOX + 2));
                }
                if (i == CurrentBox)
                {
                    boxPL.GetBytes().CopyTo(Data, Offsets.CurrentBox);
                }
            }

            PokemonList2 partyPL = new PokemonList2(PokemonList2.CapacityType.Party, Japanese);
            int          pSlot   = 0;

            for (int i = 0; i < 6; i++)
            {
                PK2 partyPK = (PK2)GetPKM(GetData(GetPartyOffset(i), SIZE_STORED));
                if (partyPK.Species > 0)
                {
                    partyPL[pSlot++] = partyPK;
                }
            }
            partyPL.GetBytes().CopyTo(Data, Offsets.Party);

            SetChecksums();
            if (Japanese)
            {
                switch (Version)
                {
                case GameVersion.GS: Array.Copy(Data, Offsets.Trainer1, Data, 0x7209, 0xC83); break;

                case GameVersion.C:  Array.Copy(Data, Offsets.Trainer1, Data, 0x7209, 0xADA); break;
                }
            }
            else if (Korean)
            {
                // Calculate oddball checksum
                ushort     sum         = 0;
                ushort[][] offsetpairs =
                {
                    new ushort[] { 0x106B, 0x1533 },
                    new ushort[] { 0x1534, 0x1A12 },
                    new ushort[] { 0x1A13, 0x1C38 },
                    new ushort[] { 0x3DD8, 0x3F79 },
                    new ushort[] { 0x7E39, 0x7E6A },
                };
                foreach (ushort[] p in offsetpairs)
                {
                    for (int i = p[0]; i < p[1]; i++)
                    {
                        sum += Data[i];
                    }
                }
                BitConverter.GetBytes(sum).CopyTo(Data, 0x7E6B);
            }
            else
            {
                switch (Version)
                {
                case GameVersion.GS:
                    Array.Copy(Data, 0x2009, Data, 0x15C7, 0x222F - 0x2009);
                    Array.Copy(Data, 0x222F, Data, 0x3D69, 0x23D9 - 0x222F);
                    Array.Copy(Data, 0x23D9, Data, 0x0C6B, 0x2856 - 0x23D9);
                    Array.Copy(Data, 0x2856, Data, 0x7E39, 0x288A - 0x2856);
                    Array.Copy(Data, 0x288A, Data, 0x10E8, 0x2D69 - 0x288A);
                    break;

                case GameVersion.C:
                    Array.Copy(Data, 0x2009, Data, 0x1209, 0xB7A);
                    break;
                }
            }
            byte[] outData = new byte[Data.Length - SIZE_RESERVED];
            Array.Copy(Data, outData, outData.Length);
            return(outData);
        }
Ejemplo n.º 8
0
 /// <summary>
 /// Creates an instance of <see cref="PKM"/> from the given data.
 /// </summary>
 /// <param name="data">Raw data of the Pokemon file.</param>
 /// <param name="ident">Optional identifier for the Pokemon.  Usually the full path of the source file.</param>
 /// <returns>An instance of <see cref="PKM"/> created from the given <paramref name="data"/>, or null if <paramref name="data"/> is invalid.</returns>
 public static PKM getPKMfromBytes(byte[] data, string ident = null)
 {
     checkEncrypted(ref data);
     switch (getPKMDataFormat(data))
     {
         case 1:
             var PL1 = new PokemonList1(data, PokemonList1.CapacityType.Single, data.Length == PKX.SIZE_1JLIST);
             if (ident != null)
                 PL1[0].Identifier = ident;
             return PL1[0];
         case 2:
             var PL2 = new PokemonList2(data, PokemonList2.CapacityType.Single, data.Length == PKX.SIZE_2JLIST);
             if (ident != null)
                 PL2[0].Identifier = ident;
             return PL2[0];
         case 3:
             switch (data.Length) { 
                 case PKX.SIZE_3CSTORED: return new CK3(data, ident);
                 case PKX.SIZE_3XSTORED: return new XK3(data, ident);
                 default: return new PK3(data, ident);
             }
         case 4:
             var pk = new PK4(data, ident);
             if (!pk.Valid || pk.Sanity != 0)
             {
                 var bk = new BK4(data, ident);
                 if (bk.Valid)
                     return bk;
             }
             return pk;
         case 5:
             return new PK5(data, ident);
         case 6:
             PKM pkx = new PK6(data, ident);
             if (pkx.SM)
                 pkx = new PK7(data, ident);
             return pkx;
         default:
             return null;
     }
 }
Ejemplo n.º 9
0
        public SAV2(byte[] data = null, GameVersion versionOverride = GameVersion.Any)
        {
            Data       = data ?? new byte[SaveUtil.SIZE_G2RAW_U];
            BAK        = (byte[])Data.Clone();
            Exportable = !IsRangeEmpty(0, Data.Length);

            if (data == null)
            {
                Version = GameVersion.C;
            }
            else if (versionOverride != GameVersion.Any)
            {
                Version = versionOverride;
            }
            else
            {
                Version = SaveUtil.GetIsG2SAV(Data);
            }

            if (Version == GameVersion.Invalid)
            {
                return;
            }

            Japanese = SaveUtil.GetIsG2SAVJ(Data) != GameVersion.Invalid;
            if (!Japanese)
            {
                Korean = SaveUtil.GetIsG2SAVK(Data) != GameVersion.Invalid;
            }

            Box = Data.Length;
            Array.Resize(ref Data, Data.Length + SIZE_RESERVED);
            Party = GetPartyOffset(0);

            Personal = Version == GameVersion.GS ? PersonalTable.GS : PersonalTable.C;

            Offsets = new SAV2Offsets(this);

            LegalItems    = Legal.Pouch_Items_GSC;
            LegalBalls    = Legal.Pouch_Ball_GSC;
            LegalKeyItems = Version == GameVersion.C ? Legal.Pouch_Key_C : Legal.Pouch_Key_GS;
            LegalTMHMs    = Legal.Pouch_TMHM_GSC;
            HeldItems     = Legal.HeldItems_GSC;

            // 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, Offsets.CurrentBox, 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, Offsets.Party, 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));
                }
            }

            // Daycare currently undocumented for all Gen II games.
            if (Offsets.Daycare >= 0)
            {
                int offset = Offsets.Daycare;

                DaycareFlags[0] = Data[offset]; offset++;
                var pk1      = ReadPKMFromOffset(offset);  // parent 1
                var daycare1 = new PokemonList2(pk1);
                offset         += StringLength * 2 + 0x20; // nick/ot/pkm
                DaycareFlags[1] = Data[offset]; offset++;
                byte steps = Data[offset]; offset++;
                byte BreedMotherOrNonDitto = Data[offset]; offset++;
                var  pk2      = ReadPKMFromOffset(offset);     // parent 2
                var  daycare2 = new PokemonList2(pk2);
                offset += StringLength * 2 + PKX.SIZE_2STORED; // nick/ot/pkm
                var pk3 = ReadPKMFromOffset(offset);           // egg!
                pk3.IsEgg = true;
                var daycare3 = new PokemonList2(pk3);

                daycare1.GetBytes().CopyTo(Data, GetPartyOffset(7 + (0 * 2)));
                daycare2.GetBytes().CopyTo(Data, GetPartyOffset(7 + (1 * 2)));
                daycare3.GetBytes().CopyTo(Data, GetPartyOffset(7 + (2 * 2)));
                Daycare = Offsets.Daycare;
            }

            // Enable Pokedex editing
            PokeDex   = 0;
            EventFlag = Offsets.EventFlag;

            if (!Exportable)
            {
                ClearBoxes();
            }
        }