Exemplo n.º 1
0
        public SAV3(byte[] data = null, GameVersion versionOverride = GameVersion.Any)
        {
            Data       = data == null ? new byte[SaveUtil.SIZE_G3RAW] : (byte[])data.Clone();
            BAK        = (byte[])Data.Clone();
            Exportable = !Data.SequenceEqual(new byte[Data.Length]);

            if (data == null)
            {
                Version = GameVersion.FRLG;
            }
            else if (versionOverride != GameVersion.Any)
            {
                Version = versionOverride;
            }
            else
            {
                Version = SaveUtil.getIsG3SAV(Data);
            }
            if (Version == GameVersion.Invalid)
            {
                return;
            }

            int[] BlockOrder1 = new int[14];
            for (int i = 0; i < 14; i++)
            {
                BlockOrder1[i] = BitConverter.ToInt16(Data, i * 0x1000 + 0xFF4);
            }
            int zeroBlock1 = Array.IndexOf(BlockOrder1, 0);

            if (data.Length > SaveUtil.SIZE_G3RAWHALF)
            {
                int[] BlockOrder2 = new int[14];
                for (int i = 0; i < 14; i++)
                {
                    BlockOrder2[i] = BitConverter.ToInt16(Data, 0xE000 + i * 0x1000 + 0xFF4);
                }
                int zeroBlock2 = Array.IndexOf(BlockOrder2, 0);

                if (zeroBlock2 < 0)
                {
                    ActiveSAV = 0;
                }
                else if (zeroBlock1 < 0)
                {
                    ActiveSAV = 1;
                }
                else
                {
                    ActiveSAV = BitConverter.ToUInt32(Data, zeroBlock1 * 0x1000 + 0xFFC) >
                                BitConverter.ToUInt32(Data, zeroBlock2 * 0x1000 + 0xEFFC)
                    ? 0
                    : 1;
                }
                BlockOrder = ActiveSAV == 0 ? BlockOrder1 : BlockOrder2;
            }
            else
            {
                ActiveSAV  = 0;
                BlockOrder = BlockOrder1;
            }

            BlockOfs = new int[14];
            for (int i = 0; i < 14; i++)
            {
                BlockOfs[i] = Array.IndexOf(BlockOrder, i) * 0x1000 + ABO;
            }

            // Set up PC data buffer beyond end of save file.
            Box = Data.Length;
            Array.Resize(ref Data, Data.Length + SIZE_RESERVED); // More than enough empty space.

            // Copy chunk to the allocated location
            for (int i = 5; i < 14; i++)
            {
                int blockIndex = Array.IndexOf(BlockOrder, i);
                if (blockIndex == -1) // block empty
                {
                    continue;
                }
                Array.Copy(Data, blockIndex * 0x1000 + ABO, Data, Box + (i - 5) * 0xF80, chunkLength[i]);
            }

            switch (Version)
            {
            case GameVersion.RS:
                LegalKeyItems     = Legal.Pouch_Key_RS;
                OFS_PouchHeldItem = BlockOfs[1] + 0x0560;
                OFS_PouchKeyItem  = BlockOfs[1] + 0x05B0;
                OFS_PouchBalls    = BlockOfs[1] + 0x0600;
                OFS_PouchTMHM     = BlockOfs[1] + 0x0640;
                OFS_PouchBerry    = BlockOfs[1] + 0x0740;
                Personal          = PersonalTable.RS;
                break;

            case GameVersion.FRLG:
                LegalKeyItems     = Legal.Pouch_Key_FRLG;
                OFS_PouchHeldItem = BlockOfs[1] + 0x0310;
                OFS_PouchKeyItem  = BlockOfs[1] + 0x03B8;
                OFS_PouchBalls    = BlockOfs[1] + 0x0430;
                OFS_PouchTMHM     = BlockOfs[1] + 0x0464;
                OFS_PouchBerry    = BlockOfs[1] + 0x054C;
                Personal          = PersonalTable.FR;
                break;

            case GameVersion.E:
                LegalKeyItems     = Legal.Pouch_Key_E;
                OFS_PouchHeldItem = BlockOfs[1] + 0x0560;
                OFS_PouchKeyItem  = BlockOfs[1] + 0x05D8;
                OFS_PouchBalls    = BlockOfs[1] + 0x0650;
                OFS_PouchTMHM     = BlockOfs[1] + 0x0690;
                OFS_PouchBerry    = BlockOfs[1] + 0x0790;
                Personal          = PersonalTable.E;
                break;
            }
            LegalItems   = Legal.Pouch_Items_RS;
            LegalBalls   = Legal.Pouch_Ball_RS;
            LegalTMHMs   = Legal.Pouch_TMHM_RS;
            LegalBerries = Legal.Pouch_Berries_RS;

            HeldItems = Legal.HeldItems_RS;

            if (!Exportable)
            {
                resetBoxes();
            }
        }
Exemplo n.º 2
0
        public SAV2(byte[] data = null)
        {
            Data       = data == null ? new byte[SaveUtil.SIZE_G2RAW_U] : (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;
            }

            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();
            }
        }
Exemplo n.º 3
0
 public MysteryGift Clone()
 {
     byte[] data = (byte[])Data.Clone();
     return(getMysteryGift(data));
 }
Exemplo n.º 4
0
 public override byte[] Encrypt()
 {
     return((byte[])Data.Clone());
 }
Exemplo n.º 5
0
        public SAV3XD(byte[] data = null)
        {
            Data       = data == null ? new byte[SaveUtil.SIZE_G3XD] : (byte[])data.Clone();
            BAK        = (byte[])Data.Clone();
            Exportable = !Data.SequenceEqual(new byte[Data.Length]);

            if (SaveUtil.getIsG3XDSAV(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
            {
                byte[] slot       = new byte[SLOT_SIZE];
                int    slotOffset = SLOT_START + SaveIndex * SLOT_SIZE;
                Array.Copy(Data, slotOffset, slot, 0, slot.Length);

                ushort[] keys = new ushort[4];
                for (int i = 0; i < keys.Length; i++)
                {
                    keys[i] = BigEndian.ToUInt16(slot, 8 + i * 2);
                }

                // Decrypt Slot
                Data = SaveUtil.DecryptGC(slot, 0x00010, 0x27FD8, keys);
            }

            // Get Offset Info
            ushort[] subLength = new ushort[16];
            for (int i = 0; i < 16; i++)
            {
                subLength[i]  = BigEndian.ToUInt16(Data, 0x20 + 2 * i);
                subOffsets[i] = BigEndian.ToUInt16(Data, 0x40 + 4 * i) | BigEndian.ToUInt16(Data, 0x40 + 4 * i + 2) << 16;
            }
            // Offsets are displaced by the 0xA8 savedata region
            Trainer1 = subOffsets[1] + 0xA8;
            Party    = Trainer1 + 0x30;
            Box      = subOffsets[2] + 0xA8;
            Daycare  = subOffsets[4] + 0xA8;
            Memo     = subOffsets[5] + 0xA8;
            Shadow   = subOffsets[7] + 0xA8;
            // Purifier = subOffsets[14] + 0xA8;

            StrategyMemo = new StrategyMemo(Data, Memo, xd: true);
            ShadowInfo   = new ShadowInfoTableXD(Data.Skip(Shadow).Take(subLength[7]).ToArray());

            OFS_PouchHeldItem = Trainer1 + 0x4C8;
            OFS_PouchKeyItem  = Trainer1 + 0x540;
            OFS_PouchBalls    = Trainer1 + 0x5EC;
            OFS_PouchTMHM     = Trainer1 + 0x62C;
            OFS_PouchBerry    = Trainer1 + 0x72C;
            OFS_PouchCologne  = Trainer1 + 0x7E4;
            OFS_PouchDisc     = Trainer1 + 0x7F0;

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

            // Since PartyCount is not stored in the save file,
            // Count up how many party slots are active.
            for (int i = 0; i < 6; i++)
            {
                if (getPartySlot(getPartyOffset(i)).Species != 0)
                {
                    PartyCount++;
                }
            }
        }