Beispiel #1
0
        public SAV3(byte[] data = null, GameVersion versionOverride = GameVersion.Any)
        {
            Data       = data ?? new byte[SaveUtil.SIZE_G3RAW];
            BAK        = (byte[])Data.Clone();
            Exportable = !IsRangeEmpty(0, 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[BLOCK_COUNT];
            for (int i = 0; i < BLOCK_COUNT; i++)
            {
                BlockOrder1[i] = BitConverter.ToInt16(Data, i * SIZE_BLOCK + 0xFF4);
            }
            int zeroBlock1 = Array.IndexOf(BlockOrder1, 0);

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

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

            BlockOfs = new int[BLOCK_COUNT];
            for (int i = 0; i < BLOCK_COUNT; i++)
            {
                int index = Array.IndexOf(BlockOrder, i);
                BlockOfs[i] = index < 0 ? int.MinValue : index * SIZE_BLOCK + 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 < BLOCK_COUNT; i++)
            {
                int blockIndex = Array.IndexOf(BlockOrder, i);
                if (blockIndex == -1) // block empty
                {
                    continue;
                }
                Array.Copy(Data, blockIndex * SIZE_BLOCK + ABO, Data, Box + (i - 5) * 0xF80, chunkLength[i]);
            }

            // Japanese games are limited to 5 character OT names; any unused characters are 0xFF.
            // 5 for JP, 7 for INT. There's always 1 terminator, thus we can check 0x6-0x7 being 0xFFFF = INT
            // OT name is stored at the top of the first block.
            Japanese = BitConverter.ToInt16(Data, BlockOfs[0] + 0x6) == 0;

            PokeDex = BlockOfs[0] + 0x18;
            switch (Version)
            {
            case GameVersion.RS:
                LegalKeyItems     = Legal.Pouch_Key_RS;
                OFS_PCItem        = BlockOfs[1] + 0x0498;
                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;
                SeenFlagOffsets   = new[] { PokeDex + 0x44, BlockOfs[1] + 0x938, BlockOfs[4] + 0xC0C };
                EventFlag         = BlockOfs[2] + 0x2A0;
                EventConst        = EventFlag + EventFlagMax / 8;
                Daycare           = BlockOfs[4] + 0x11C;
                break;

            case GameVersion.E:
                LegalKeyItems     = Legal.Pouch_Key_E;
                OFS_PCItem        = BlockOfs[1] + 0x0498;
                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;
                SeenFlagOffsets   = new[] { PokeDex + 0x44, BlockOfs[1] + 0x988, BlockOfs[4] + 0xCA4 };
                EventFlag         = BlockOfs[2] + 0x2F0;
                EventConst        = EventFlag + EventFlagMax / 8;
                Daycare           = BlockOfs[4] + 0x1B0;
                break;

            case GameVersion.FRLG:
                LegalKeyItems     = Legal.Pouch_Key_FRLG;
                OFS_PCItem        = BlockOfs[1] + 0x0298;
                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;
                SeenFlagOffsets   = new[] { PokeDex + 0x44, BlockOfs[1] + 0x5F8, BlockOfs[4] + 0xB98 };
                EventFlag         = BlockOfs[2] + 0x000;
                EventConst        = EventFlag + EventFlagMax / 8;
                Daycare           = BlockOfs[4] + 0x100;
                break;
            }
            LoadEReaderBerryData();
            LegalItems   = Legal.Pouch_Items_RS;
            LegalBalls   = Legal.Pouch_Ball_RS;
            LegalTMHMs   = Legal.Pouch_TMHM_RS;
            LegalBerries = Legal.Pouch_Berries_RS;
            HeldItems    = Legal.HeldItems_RS;

            // Sanity Check SeenFlagOffsets -- early saves may not have block 4 initialized yet
            SeenFlagOffsets = SeenFlagOffsets?.Where(z => z >= 0).ToArray();

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