Esempio n. 1
0
        public void Flush()
        {
            string Full_Save_Name = Save_Path + Path.DirectorySeparatorChar + Save_Name + Save_Extension;

            Save_File   = new FileStream(Full_Save_Name, FileMode.OpenOrCreate);
            Save_Writer = new BinaryWriter(Save_File);
            if (Game_System == SaveGeneration.GCN) // TODO: Condense Wild World and GCN save logic into one if statement
            {
                Write(Save_Data_Start_Offset + 0x12, Checksum.Calculate(Working_Save_Data.Skip(Save_Data_Start_Offset).Take(Save_Info.Save_Offsets.Save_Size).ToArray(), 0x12), true);
                Working_Save_Data.Skip(Save_Data_Start_Offset).Take(Save_Info.Save_Offsets.Save_Size).ToArray().CopyTo(Working_Save_Data,
                                                                                                                       Save_Data_Start_Offset + Save_Info.Save_Offsets.Save_Size); //Update second save copy
            }
            else if (Save_Type == SaveType.Wild_World)
            {
                Write(Save_Data_Start_Offset + 0x15FDC, Checksum.Calculate(Working_Save_Data.Skip(Save_Data_Start_Offset).Take(0x15FE0).ToArray(),
                                                                           0x15FDC, true));
                Working_Save_Data.Skip(Save_Data_Start_Offset).Take(0x15FE0).ToArray().CopyTo(Working_Save_Data, Save_Data_Start_Offset + 0x15FE0); //Update both save copies on WW
            }
            else if (Save_Type == SaveType.City_Folk)
            {
                for (int i = 0; i < 4; i++)
                {
                    int  Player_Data_Offset = Save_Data_Start_Offset + i * 0x86C0 + 0x1140;
                    uint Player_CRC32       = CRC32.GetCRC32(Working_Save_Data.Skip(Player_Data_Offset + 4).Take(0x759C).ToArray());
                    Write(Player_Data_Offset, Player_CRC32, true);
                }
                Write(Save_Data_Start_Offset + 0x5EC60, CRC32.GetCRC32(Working_Save_Data.Skip(Save_Data_Start_Offset + 0x5EC64).Take(0x1497C).ToArray()), true);
                Write(Save_Data_Start_Offset + 0x5EB04, CRC32.GetCRC32(Working_Save_Data.Skip(Save_Data_Start_Offset + 0x5EB08).Take(0x152).ToArray(), 0x12141018), true);
                Write(Save_Data_Start_Offset + 0x73600, CRC32.GetCRC32(Working_Save_Data.Skip(Save_Data_Start_Offset + 0x73604).Take(0x19BD1C).ToArray()), true);
                Write(Save_Data_Start_Offset, CRC32.GetCRC32(Working_Save_Data.Skip(Save_Data_Start_Offset + 4).Take(0x1C).ToArray()), true);
                Write(Save_Data_Start_Offset + 0x20, CRC32.GetCRC32(Working_Save_Data.Skip(Save_Data_Start_Offset + 0x24).Take(0x111C).ToArray()), true);
            }
            else if (Save_Type == SaveType.New_Leaf)
            {
                Write(Save_Data_Start_Offset, NL_CRC32.Calculate_CRC32(Working_Save_Data.Skip(Save_Data_Start_Offset + 4).Take(0x1C).ToArray()));
                for (int i = 0; i < 4; i++)
                {
                    int DataOffset = Save_Data_Start_Offset + 0x20 + i * 0x9F10;
                    Write(DataOffset, NL_CRC32.Calculate_CRC32(Working_Save_Data.Skip(DataOffset + 4).Take(0x6B64).ToArray()));
                    int DataOffset2 = Save_Data_Start_Offset + 0x20 + 0x6B68 + i * 0x9F10;
                    Write(DataOffset2, NL_CRC32.Calculate_CRC32(Working_Save_Data.Skip(DataOffset2 + 4).Take(0x33A4).ToArray()));
                }
                Write(Save_Data_Start_Offset + 0x27C60, NL_CRC32.Calculate_CRC32(Working_Save_Data.Skip(Save_Data_Start_Offset + 0x27C60 + 4).Take(0x218B0).ToArray()));
                Write(Save_Data_Start_Offset + 0x49520, NL_CRC32.Calculate_CRC32(Working_Save_Data.Skip(Save_Data_Start_Offset + 0x49520 + 4).Take(0x44B8).ToArray()));
                Write(Save_Data_Start_Offset + 0x4D9DC, NL_CRC32.Calculate_CRC32(Working_Save_Data.Skip(Save_Data_Start_Offset + 0x4D9DC + 4).Take(0x1E420).ToArray()));
                Write(Save_Data_Start_Offset + 0x6BE00, NL_CRC32.Calculate_CRC32(Working_Save_Data.Skip(Save_Data_Start_Offset + 0x6BE00 + 4).Take(0x20).ToArray()));
                Write(Save_Data_Start_Offset + 0x6BE24, NL_CRC32.Calculate_CRC32(Working_Save_Data.Skip(Save_Data_Start_Offset + 0x6BE24 + 4).Take(0x13AF8).ToArray()));
            }
            else if (Save_Type == SaveType.Welcome_Amiibo)
            {
                Write(Save_Data_Start_Offset, NL_CRC32.Calculate_CRC32(Working_Save_Data.Skip(Save_Data_Start_Offset + 4).Take(0x1C).ToArray()));
                for (int i = 0; i < 4; i++)
                {
                    int DataOffset = Save_Data_Start_Offset + 0x20 + i * 0xA480;
                    Write(DataOffset, NL_CRC32.Calculate_CRC32(Working_Save_Data.Skip(DataOffset + 4).Take(0x6B84).ToArray()));
                    int DataOffset2 = Save_Data_Start_Offset + 0x20 + 0x6B88 + i * 0xA480;
                    Write(DataOffset2, NL_CRC32.Calculate_CRC32(Working_Save_Data.Skip(DataOffset2 + 4).Take(0x38F4).ToArray()));
                }
                Write(Save_Data_Start_Offset + 0x29220, NL_CRC32.Calculate_CRC32(Working_Save_Data.Skip(Save_Data_Start_Offset + 0x29220 + 4).Take(0x22BC8).ToArray()));
                Write(Save_Data_Start_Offset + 0x4BE00, NL_CRC32.Calculate_CRC32(Working_Save_Data.Skip(Save_Data_Start_Offset + 0x4BE00 + 4).Take(0x44B8).ToArray()));
                Write(Save_Data_Start_Offset + 0x533A4, NL_CRC32.Calculate_CRC32(Working_Save_Data.Skip(Save_Data_Start_Offset + 0x533A4 + 4).Take(0x1E4D8).ToArray()));
                Write(Save_Data_Start_Offset + 0x71880, NL_CRC32.Calculate_CRC32(Working_Save_Data.Skip(Save_Data_Start_Offset + 0x71880 + 4).Take(0x20).ToArray()));
                Write(Save_Data_Start_Offset + 0x718A4, NL_CRC32.Calculate_CRC32(Working_Save_Data.Skip(Save_Data_Start_Offset + 0x718A4 + 4).Take(0xBE4).ToArray()));
                Write(Save_Data_Start_Offset + 0x738D4, NL_CRC32.Calculate_CRC32(Working_Save_Data.Skip(Save_Data_Start_Offset + 0x738D4 + 4).Take(0x16188).ToArray()));
            }
            Save_Writer.Write(Save_Type == SaveType.Doubutsu_no_Mori ? SaveDataManager.ByteSwap(Working_Save_Data) : Working_Save_Data); //Doubutsu no Mori is dword byteswapped
            Save_Writer.Flush();
            Save_File.Flush();

            Save_Writer.Close();
            Save_File.Close();
        }
Esempio n. 2
0
        public void Flush()
        {
            var fullSaveName = SavePath + Path.DirectorySeparatorChar + SaveName + SaveExtension;

            _saveFile   = new FileStream(fullSaveName, FileMode.OpenOrCreate);
            _saveWriter = new BinaryWriter(_saveFile);
            switch (SaveType)
            {
            case SaveType.DoubutsuNoMoriPlus:
            case SaveType.AnimalCrossing:
            case SaveType.DoubutsuNoMoriEPlus:
            case SaveType.AnimalForestEPlus:
                Write(SaveDataStartOffset + SaveInfo.SaveOffsets.Checksum,
                      new UInt16BEChecksum().Calculate(
                          SaveData.Skip(SaveDataStartOffset).Take(SaveInfo.SaveOffsets.SaveSize).ToArray(),
                          (uint)SaveInfo.SaveOffsets.Checksum), IsBigEndian);

                SaveData.Skip(SaveDataStartOffset).Take(SaveInfo.SaveOffsets.SaveSize).ToArray().CopyTo(
                    SaveData,
                    SaveDataStartOffset + SaveInfo.SaveOffsets.SaveSize);
                break;

            case SaveType.WildWorld:
                Write(SaveDataStartOffset + SaveInfo.SaveOffsets.Checksum,
                      new UInt16LEChecksum().Calculate(
                          SaveData.Skip(SaveDataStartOffset).Take(SaveInfo.SaveOffsets.SaveSize).ToArray(),
                          (uint)SaveInfo.SaveOffsets.Checksum), IsBigEndian);

                SaveData.Skip(SaveDataStartOffset).Take(SaveInfo.SaveOffsets.SaveSize).ToArray().CopyTo(
                    SaveData,
                    SaveDataStartOffset + SaveInfo.SaveOffsets.SaveSize);
                break;

            case SaveType.DoubutsuNoMori:
            case SaveType.DongwuSenlin:
                Write(SaveDataStartOffset + SaveInfo.SaveOffsets.Checksum,
                      new UInt16BEChecksum().Calculate(
                          SaveData.Skip(SaveDataStartOffset).Take(0xF980).ToArray(),
                          (uint)SaveInfo.SaveOffsets.Checksum), IsBigEndian);

                SaveData.Skip(SaveDataStartOffset).Take(SaveInfo.SaveOffsets.SaveSize).ToArray().CopyTo(
                    SaveData,
                    SaveDataStartOffset + SaveInfo.SaveOffsets.SaveSize);
                break;

            case SaveType.CityFolk:
                var crc32 = new CRC32();
                for (var i = 0; i < 4; i++)
                {
                    var playerDataOffset = SaveDataStartOffset + i * 0x86C0 + 0x1140;
                    var playerCrc32      =
                        crc32.Calculate(SaveData.Skip(playerDataOffset + 4).Take(0x759C).ToArray());
                    Write(playerDataOffset, playerCrc32, true);
                }

                Write(SaveDataStartOffset + 0x5EC60,
                      crc32.Calculate(SaveData.Skip(SaveDataStartOffset + 0x5EC64).Take(0x1497C).ToArray()),
                      true);
                Write(SaveDataStartOffset + 0x5EB04,
                      crc32.Calculate(SaveData.Skip(SaveDataStartOffset + 0x5EB08).Take(0x152).ToArray(),
                                      0x12141018), true);
                Write(SaveDataStartOffset + 0x73600,
                      crc32.Calculate(SaveData.Skip(SaveDataStartOffset + 0x73604).Take(0x19BD1C).ToArray()),
                      true);
                Write(SaveDataStartOffset,
                      crc32.Calculate(SaveData.Skip(SaveDataStartOffset + 4).Take(0x1C).ToArray()), true);
                Write(SaveDataStartOffset + 0x20,
                      crc32.Calculate(SaveData.Skip(SaveDataStartOffset + 0x24).Take(0x111C).ToArray()), true);
                break;

            case SaveType.NewLeaf:
                var crc32Type1 = new NewLeafCRC32Type1();

                Write(SaveDataStartOffset,
                      crc32Type1.Calculate(SaveData.Skip(SaveDataStartOffset + 4).Take(0x1C).ToArray()));
                for (var i = 0; i < 4; i++)
                {
                    var dataOffset = SaveDataStartOffset + 0x20 + i * 0x9F10;
                    Write(dataOffset,
                          crc32Type1.Calculate(SaveData.Skip(dataOffset + 4).Take(0x6B64).ToArray()));

                    var dataOffset2 = SaveDataStartOffset + 0x20 + 0x6B68 + i * 0x9F10;
                    Write(dataOffset2,
                          crc32Type1.Calculate(SaveData.Skip(dataOffset2 + 4).Take(0x33A4).ToArray()));
                }

                Write(SaveDataStartOffset + 0x27C60,
                      crc32Type1.Calculate(SaveData.Skip(SaveDataStartOffset + 0x27C60 + 4).Take(0x218B0)
                                           .ToArray()));
                Write(SaveDataStartOffset + 0x49520,
                      crc32Type1.Calculate(SaveData.Skip(SaveDataStartOffset + 0x49520 + 4).Take(0x44B8)
                                           .ToArray()));
                Write(SaveDataStartOffset + 0x4D9DC,
                      crc32Type1.Calculate(SaveData.Skip(SaveDataStartOffset + 0x4D9DC + 4).Take(0x1E420)
                                           .ToArray()));
                Write(SaveDataStartOffset + 0x6BE00,
                      crc32Type1.Calculate(SaveData.Skip(SaveDataStartOffset + 0x6BE00 + 4).Take(0x20)
                                           .ToArray()));
                Write(SaveDataStartOffset + 0x6BE24,
                      crc32Type1.Calculate(SaveData.Skip(SaveDataStartOffset + 0x6BE24 + 4).Take(0x13AF8)
                                           .ToArray()));
                break;

            case SaveType.WelcomeAmiibo:
                var waCrc32Type1 = new NewLeafCRC32Type1();
                var waCrc32Type2 = new NewLeafCRC32Type2();

                // CRC32 Implementation Type 1 Checksums
                Write(SaveDataStartOffset,
                      waCrc32Type1.Calculate(SaveData.Skip(SaveDataStartOffset + 4).Take(0x1C).ToArray()));
                for (var i = 0; i < 4; i++)
                {
                    var dataOffset = SaveDataStartOffset + 0x20 + i * 0xA480;
                    Write(dataOffset,
                          waCrc32Type1.Calculate(SaveData.Skip(dataOffset + 4).Take(0x6B84).ToArray()));

                    var dataOffset2 = SaveDataStartOffset + 0x20 + 0x6B88 + i * 0xA480;
                    Write(dataOffset2,
                          waCrc32Type1.Calculate(SaveData.Skip(dataOffset2 + 4).Take(0x38F4).ToArray()));
                }

                Write(SaveDataStartOffset + 0x29220,
                      waCrc32Type1.Calculate(SaveData.Skip(SaveDataStartOffset + 0x29220 + 4).Take(0x22BC8)
                                             .ToArray()));
                Write(SaveDataStartOffset + 0x4BE00,
                      waCrc32Type1.Calculate(SaveData.Skip(SaveDataStartOffset + 0x4BE00 + 4).Take(0x44B8)
                                             .ToArray()));
                Write(SaveDataStartOffset + 0x533A4,
                      waCrc32Type1.Calculate(SaveData.Skip(SaveDataStartOffset + 0x533A4 + 4).Take(0x1E4D8)
                                             .ToArray()));
                Write(SaveDataStartOffset + 0x71880,
                      waCrc32Type1.Calculate(SaveData.Skip(SaveDataStartOffset + 0x71880 + 4).Take(0x20)
                                             .ToArray()));
                Write(SaveDataStartOffset + 0x718A4,
                      waCrc32Type1.Calculate(SaveData.Skip(SaveDataStartOffset + 0x718A4 + 4).Take(0xBE4)
                                             .ToArray()));
                Write(SaveDataStartOffset + 0x738D4,
                      waCrc32Type1.Calculate(SaveData.Skip(SaveDataStartOffset + 0x738D4 + 4).Take(0x16188)
                                             .ToArray()));

                // CRC32 Implementation Type 2 Checksums
                Write(SaveDataStartOffset + 0x502BC,
                      waCrc32Type2.Calculate(SaveData.Skip(SaveDataStartOffset + 0x502BC + 4).Take(0x28F0)
                                             .ToArray()));
                Write(SaveDataStartOffset + 0x52BB0,
                      waCrc32Type2.Calculate(SaveData.Skip(SaveDataStartOffset + 0x52BB0 + 4).Take(0x7F0)
                                             .ToArray()));
                Write(SaveDataStartOffset + 0x7248C,
                      waCrc32Type2.Calculate(SaveData.Skip(SaveDataStartOffset + 0x7248C + 4).Take(0x1444)
                                             .ToArray()));
                break;
            }

            _saveWriter.Write(SaveType == SaveType.DoubutsuNoMori && _byteswap
                ? SaveDataManager.ByteSwap(SaveData)
                : SaveData); // Doubutsu no Mori is dword byteswapped
            _saveWriter.Flush();
            _saveFile.Flush();

            _saveWriter.Close();
            _saveFile.Close();
            _saveWriter.Dispose();
            _saveFile.Dispose();
            ChangesMade = false;
        }