diff --git a/NHSE.Core/Hashing/FileHashRevision.cs b/NHSE.Core/Hashing/FileHashRevision.cs index dd4dc02..49a9a64 100644 --- a/NHSE.Core/Hashing/FileHashRevision.cs +++ b/NHSE.Core/Hashing/FileHashRevision.cs @@ -270,7 +270,7 @@ public static class FileHashRevision #endregion - #region REVISION 1.4.0 + #region REVISION 1.5.0 private const int REV_150_MAIN_SAVE_SIZE = 0xB20750; private const int REV_150_PERSONAL_SAVE_SIZE = 0x76390; @@ -322,5 +322,58 @@ public static class FileHashRevision }); #endregion + + #region REVISION 1.6.0 + + private const int REV_160_MAIN_SAVE_SIZE = 0xB20750; + private const int REV_160_PERSONAL_SAVE_SIZE = 0x76390; + private const int REV_160_POSTBOX_SAVE_SIZE = REV_110_POSTBOX_SAVE_SIZE; + private const int REV_160_PHOTO_STUDIO_ISLAND_SIZE = REV_120_PHOTO_STUDIO_ISLAND_SIZE; + private const int REV_160_PROFILE_SIZE = REV_110_PROFILE_SIZE; + + public static readonly FileHashInfo REV_160 = new FileHashInfo(new[] + { + new FileHashDetails("main.dat", REV_160_MAIN_SAVE_SIZE, new[] + { + new FileHashRegion(0x000110, 0x1e215c), + new FileHashRegion(0x1e2270, 0x32403c), + new FileHashRegion(0x5063c0, 0x03693c), + new FileHashRegion(0x53cd00, 0x04029c), + new FileHashRegion(0x57d0b0, 0x03693c), + new FileHashRegion(0x5b39f0, 0x04029c), + new FileHashRegion(0x5f3da0, 0x03693c), + new FileHashRegion(0x62a6e0, 0x04029c), + new FileHashRegion(0x66aa90, 0x03693c), + new FileHashRegion(0x6a13d0, 0x04029c), + new FileHashRegion(0x6e1780, 0x03693c), + new FileHashRegion(0x7180c0, 0x04029c), + new FileHashRegion(0x758470, 0x03693c), + new FileHashRegion(0x78edb0, 0x04029c), + new FileHashRegion(0x7cf160, 0x03693c), + new FileHashRegion(0x805aa0, 0x04029c), + new FileHashRegion(0x845e50, 0x03693c), + new FileHashRegion(0x87c790, 0x04029c), + new FileHashRegion(0x8bca30, 0x268eac) + }), + new FileHashDetails("personal.dat", REV_160_PERSONAL_SAVE_SIZE, new[] + { + new FileHashRegion(0x00110, 0x3693c), + new FileHashRegion(0x36a50, 0x4029c) + }), + new FileHashDetails("postbox.dat", REV_160_POSTBOX_SAVE_SIZE, new[] + { + new FileHashRegion(0x000100, 0xB4448C) + }), + new FileHashDetails("photo_studio_island.dat", REV_160_PHOTO_STUDIO_ISLAND_SIZE, new[] + { + new FileHashRegion(0x000100, 0x2C8BC) + }), + new FileHashDetails("profile.dat", REV_160_PROFILE_SIZE, new[] + { + new FileHashRegion(0x000100, 0x6945C) + }), + }); + + #endregion } } diff --git a/NHSE.Core/Save/Meta/RevisionChecker.cs b/NHSE.Core/Save/Meta/RevisionChecker.cs index 520305e..6aab3ab 100644 --- a/NHSE.Core/Save/Meta/RevisionChecker.cs +++ b/NHSE.Core/Save/Meta/RevisionChecker.cs @@ -17,6 +17,7 @@ public static class RevisionChecker new SaveFileSizes(0xACED80, 0x6D6D0, 0x2C9C0, 0xB44590, 0x69560), // 1.3.0 new SaveFileSizes(0xB05790, 0x74420, 0x2C9C0, 0xB44590, 0x69560), // 1.4.0 new SaveFileSizes(0xB20750, 0x76390, 0x2C9C0, 0xB44590, 0x69560), // 1.5.0 + new SaveFileSizes(0xB258E0, 0x76CF0, 0x2C9C0, 0xB44590, 0x69560), // 1.6.0 }; private static readonly FileHeaderInfo[] RevisionInfo = @@ -36,6 +37,7 @@ public static class RevisionChecker new FileHeaderInfo { Major = 0x50001, Minor = 0x5000B, HeaderRevision = 0, Unk1 = 2, SaveRevision = 12, Unk2 = 2 }, // 1.4.2 new FileHeaderInfo { Major = 0x60001, Minor = 0x6000C, HeaderRevision = 0, Unk1 = 2, SaveRevision = 13, Unk2 = 2 }, // 1.5.0 new FileHeaderInfo { Major = 0x60001, Minor = 0x6000C, HeaderRevision = 0, Unk1 = 2, SaveRevision = 14, Unk2 = 2 }, // 1.5.1 + new FileHeaderInfo { Major = 0x70001, Minor = 0x70006, HeaderRevision = 0, Unk1 = 2, SaveRevision = 15, Unk2 = 2 }, // 1.6.0 }; public static readonly IReadOnlyList SizeInfo = new[] @@ -55,6 +57,7 @@ public static class RevisionChecker SizesByRevision[4], // 1.4.2 SizesByRevision[5], // 1.5.0 SizesByRevision[5], // 1.5.1 + SizesByRevision[6], // 1.6.0 }; public static readonly IReadOnlyList HashInfo = new[] @@ -74,6 +77,7 @@ public static class RevisionChecker FileHashRevision.REV_140, // 1.4.2 FileHashRevision.REV_150, // 1.5.0 FileHashRevision.REV_150, // 1.5.1 + FileHashRevision.REV_160, // 1.6.0 }; public static bool IsRevisionKnown(this FileHeaderInfo info) => info.GetKnownRevisionIndex() >= 0; diff --git a/NHSE.Core/Save/Offsets/MainSaveOffsets.cs b/NHSE.Core/Save/Offsets/MainSaveOffsets.cs index 3e87637..d6b6e81 100644 --- a/NHSE.Core/Save/Offsets/MainSaveOffsets.cs +++ b/NHSE.Core/Save/Offsets/MainSaveOffsets.cs @@ -67,6 +67,7 @@ public static MainSaveOffsets GetOffsets(FileHeaderInfo Info) 12 => new MainSaveOffsets14(), 13 => new MainSaveOffsets15(), 14 => new MainSaveOffsets15(), + 15 => new MainSaveOffsets16(), _ => throw new IndexOutOfRangeException("Unknown revision!" + Environment.NewLine + Info), }; } diff --git a/NHSE.Core/Save/Offsets/MainSaveOffsets16.cs b/NHSE.Core/Save/Offsets/MainSaveOffsets16.cs new file mode 100644 index 0000000..de34c6a --- /dev/null +++ b/NHSE.Core/Save/Offsets/MainSaveOffsets16.cs @@ -0,0 +1,53 @@ +namespace NHSE.Core +{ + /// + /// + /// + public class MainSaveOffsets16 : MainSaveOffsets + { + #region GSaveLand + public const int GSaveLandStart = 0x110; + public override int Animal => GSaveLandStart + 0x10; + + public override int LandMyDesign => GSaveLandStart + 0x1e2600; + public override int PatternsPRO => LandMyDesign + (PatternCount * DesignPattern.SIZE); + public override int PatternFlag => PatternsPRO + (PatternCount * DesignPatternPRO.SIZE); + public override int PatternTailor => PatternFlag + DesignPattern.SIZE; + + public const int GSaveWeather = GSaveLandStart + 0x1e23B0; + public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere + public override int WeatherRandSeed => GSaveWeather + 0x18; + + public override int EventFlagLand => GSaveLandStart + 0x20c40c; + + // GSaveMainField + public const int GSaveMainFieldStart = GSaveLandStart + 0x20cc0c; + public override int FieldItem => GSaveMainFieldStart + 0x00000; + public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; + public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; + public override int OutsideField => GSaveMainFieldStart + 0xCF998; + public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; + + public override int PlayerHouseList => GSaveLandStart + 0x2e7638; + public override int NpcHouseList => GSaveLandStart + 0x419638; + + public const int GSaveShop = GSaveLandStart + 0x41a880; + public override int ShopKabu => GSaveShop + 0x2be0; // part of shop; tailor increased size + public override int Museum => GSaveLandStart + 0x41d9d4; + public override int Visitor => GSaveLandStart + 0x420dd8; + public override int SaveFg => GSaveLandStart + 0x421008; + public override int BulletinBoard => GSaveLandStart + 0x421950; + public override int AirportThemeColor => GSaveLandStart + 0x502558; + #endregion + + #region GSaveLandOther + public const int GSaveLandOtherStart = 0x5062b0; + + public override int LostItemBox => GSaveLandOtherStart + 0x61a4f0; + public override int LastSavedTime => GSaveLandOtherStart + 0x61ed88; + #endregion + + public override int VillagerSize => Villager2.SIZE; + public override IVillager ReadVillager(byte[] data) => new Villager2(data); + } +} diff --git a/NHSE.Core/Save/Offsets/PersonalOffsets.cs b/NHSE.Core/Save/Offsets/PersonalOffsets.cs index 6bb743d..bd184e0 100644 --- a/NHSE.Core/Save/Offsets/PersonalOffsets.cs +++ b/NHSE.Core/Save/Offsets/PersonalOffsets.cs @@ -59,6 +59,7 @@ public static PersonalOffsets GetOffsets(FileHeaderInfo Info) 12 => new PersonalOffsets14(), 13 => new PersonalOffsets15(), 14 => new PersonalOffsets15(), + 15 => new PersonalOffsets16(), _ => throw new IndexOutOfRangeException("Unknown revision!" + Environment.NewLine + Info), }; } diff --git a/NHSE.Core/Save/Offsets/PersonalOffsets16.cs b/NHSE.Core/Save/Offsets/PersonalOffsets16.cs new file mode 100644 index 0000000..7820a35 --- /dev/null +++ b/NHSE.Core/Save/Offsets/PersonalOffsets16.cs @@ -0,0 +1,44 @@ +namespace NHSE.Core +{ + /// + /// + /// + public sealed class PersonalOffsets16 : PersonalOffsets + { + private const int Player = 0x110; + + public override int PersonalId => Player + 0xAFA8; + public override int EventFlagsPlayer => Player + 0xAFE0; + + private const int GSaveLifeSupport = Player + 0xBFE0; + public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement + + public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles + public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned + public override int Birthday => Player + 0x1228c; + + public override int ProfileMain => Player + 0x122a0; + public override int ProfilePhoto => ProfileMain + 0x14; + public override int ProfileBirthday => ProfileMain + 0x23058; + public override int ProfileFruit => ProfileMain + 0x2305C; + public override int ProfileTimestamp => ProfileMain + 0x230CC; + public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; + + // end player + + private const int PlayerOther = 0x36a50; + + public override int Pockets1 => PlayerOther + 0x10; + public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; + public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; + public override int ItemChest => PlayerOther + 0x18C; + public override int ItemCollectBit => PlayerOther + 0xA058; + public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; + public override int Manpu => PlayerOther + 0xAF7C; + public override int Bank => PlayerOther + 0x35244; + public override int Recipes => Bank + 0x10; + + public override int MaxRecipeID => 0x2E1; + public override int MaxRemakeBitFlag => 0x7D0 * 32; + } +}