diff --git a/NHSE.Core/Structures/Villager/Villager1.cs b/NHSE.Core/Structures/Villager/Villager1.cs index 99d1720..8b82d3a 100644 --- a/NHSE.Core/Structures/Villager/Villager1.cs +++ b/NHSE.Core/Structures/Villager/Villager1.cs @@ -3,6 +3,9 @@ namespace NHSE.Core { + /// + /// Villager object format starting from release thru update 1.4 + /// public sealed class Villager1 : IVillager { public const int SIZE = 0x12AB0; @@ -125,4 +128,4 @@ public void SetFriendshipAll(byte value = byte.MaxValue) } } } -} \ No newline at end of file +} diff --git a/NHSE.Core/Structures/Villager/Villager2.cs b/NHSE.Core/Structures/Villager/Villager2.cs index 9799bd4..f6b9013 100644 --- a/NHSE.Core/Structures/Villager/Villager2.cs +++ b/NHSE.Core/Structures/Villager/Villager2.cs @@ -3,6 +3,9 @@ namespace NHSE.Core { + /// + /// Villager object format starting with update 1.5 + /// public sealed class Villager2 : IVillager { public const int SIZE = 0x13230; // + 160*0xC (0x780) -- GSaveLightMemory increased size. @@ -125,4 +128,4 @@ public void SetFriendshipAll(byte value = byte.MaxValue) } } } -} \ No newline at end of file +} diff --git a/NHSE.Core/Structures/Villager/VillagerConverter.cs b/NHSE.Core/Structures/Villager/VillagerConverter.cs new file mode 100644 index 0000000..77c97b8 --- /dev/null +++ b/NHSE.Core/Structures/Villager/VillagerConverter.cs @@ -0,0 +1,77 @@ +using System; + +namespace NHSE.Core +{ + public static class VillagerConverter + { + public static bool IsCompatible(int size, int expect) + { + switch (expect) + { + case Villager1.SIZE: + case Villager2.SIZE: + return size == Villager1.SIZE || size == Villager2.SIZE; + + default: + return false; + } + } + + public static byte[] GetCompatible(byte[] data, int expect) + { + if (data.Length == expect) + return data; + + return expect switch + { + Villager1.SIZE when data.Length == Villager2.SIZE => Convert12(data), + Villager2.SIZE when data.Length == Villager1.SIZE => Convert21(data), + _ => data + }; + } + + public static byte[] Convert12(byte[] v1) + { + byte[] v2 = new byte[Villager2.SIZE]; + + // Copy pre-GSaveLightMemory[160] + Array.Copy(v1, 0, v2, 0, 0x2f84); + + // Copy each entry, with each adding 0xC empty bytes. + for (int i = 0; i < 160; i++) + { + var src = 0x2f84 + (0x14C * i); + var dest = 0x2f84 + (0x158 * i); + + Array.Copy(v1, src, v2, dest, 0x14C); + } + + // Copy after-GSaveLightMemory[160] + Array.Copy(v1, 0xff04, v2, 0x10684, v1.Length - 0xff04); + + return v2; + } + + public static byte[] Convert21(byte[] v2) + { + byte[] v1 = new byte[Villager1.SIZE]; + + // Copy pre-GSaveLightMemory[160] + Array.Copy(v2, 0, v1, 0, 0x2f84); + + // Copy each entry, with each skipping last 0xC bytes. + for (int i = 0; i < 160; i++) + { + var src = 0x2f84 + (0x14C * i); + var dest = 0x2f84 + (0x158 * i); + + Array.Copy(v2, dest, v1, src, 0x14C); + } + + // Copy after-GSaveLightMemory[160] + Array.Copy(v2, 0x10684, v1, 0xff04, v2.Length - 0x10684); + + return v1; + } + } +} diff --git a/NHSE.WinForms/Controls/VillagerEditor.cs b/NHSE.WinForms/Controls/VillagerEditor.cs index 7ee79a9..af28ae4 100644 --- a/NHSE.WinForms/Controls/VillagerEditor.cs +++ b/NHSE.WinForms/Controls/VillagerEditor.cs @@ -132,13 +132,20 @@ private void B_LoadVillager_Click(object sender, EventArgs e) var path = ofd.FileName; var expectLength = SAV.Offsets.VillagerSize; var fi = new FileInfo(path); - if (fi.Length != expectLength) + if (VillagerConverter.IsCompatible((int)fi.Length, expectLength)) { WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path); return; } var data = File.ReadAllBytes(ofd.FileName); + data = VillagerConverter.GetCompatible(data, expectLength); + if (data.Length != expectLength) + { + WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path); + return; + } + var v = SAV.Offsets.ReadVillager(data); var player0 = Origin; if (!v.IsOriginatedFrom(player0))