From e65644a236db7e76d8caaf7655c0a9d991ca5b56 Mon Sep 17 00:00:00 2001 From: haven1433 Date: Sun, 5 Mar 2023 21:39:19 -0600 Subject: [PATCH] repoint scripts based on previous script size, not computed size from model --- src/HexManiac.Core/Core/Autos/StubDataModel.cs | 15 +++++++++++++++ src/HexManiac.Core/Models/IDataModel.cs | 3 +++ src/HexManiac.Core/Models/PokemonModel.cs | 17 +++++++++++++++++ src/HexManiac.Core/ViewModels/Tools/CodeTool.cs | 2 +- src/HexManiac.Tests/CodeToolTests.cs | 13 +++++++++++++ 5 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/HexManiac.Core/Core/Autos/StubDataModel.cs b/src/HexManiac.Core/Core/Autos/StubDataModel.cs index 3f170604..5638d892 100644 --- a/src/HexManiac.Core/Core/Autos/StubDataModel.cs +++ b/src/HexManiac.Core/Core/Autos/StubDataModel.cs @@ -163,12 +163,18 @@ namespace HavenSoft.HexManiac.Core.Models } public delegate T RelocateForExpansionDelegate_ModelDelta_T_int(ModelDelta changeToken, T run, int minimumLength) where T : Runs.IFormattedRun; + public delegate T RelocateForExpansionDelegate_ModelDelta_T_int_int(ModelDelta changeToken, T run, int currentLength, int desiredLength) where T : Runs.IFormattedRun; private readonly Dictionary RelocateForExpansionDelegates_ModelDelta_T_int = new Dictionary(new EnumerableEqualityComparer()); + private readonly Dictionary RelocateForExpansionDelegates_ModelDelta_T_int_int = new(new EnumerableEqualityComparer()); public void ImplementRelocateForExpansion(RelocateForExpansionDelegate_ModelDelta_T_int implementation) where T : Runs.IFormattedRun { var key = new Type[] { typeof(T) }; RelocateForExpansionDelegates_ModelDelta_T_int[key] = implementation; } + public void ImplementRelocateForExpansion(RelocateForExpansionDelegate_ModelDelta_T_int_int implementation)where T : Runs.IFormattedRun { + var key = new Type[] { typeof(T) }; + RelocateForExpansionDelegates_ModelDelta_T_int_int[key] = implementation; + } public T RelocateForExpansion(ModelDelta changeToken, T run, int minimumLength) where T : Runs.IFormattedRun { var key = new Type[] { typeof(T) }; @@ -182,6 +188,15 @@ namespace HavenSoft.HexManiac.Core.Models return default(T); } } + public T RelocateForExpansion(ModelDelta changeToken, T run, int currentLength, int desiredLength) where T : Runs.IFormattedRun { + var key = new Type[] { typeof(T) }; + object implementation; + if (RelocateForExpansionDelegates_ModelDelta_T_int_int.TryGetValue(key, out implementation)) { + return ((RelocateForExpansionDelegate_ModelDelta_T_int_int)implementation).Invoke(changeToken, run, currentLength, desiredLength); + } else { + return default(T); + } + } public Func FindFreeSpace { get; set; } diff --git a/src/HexManiac.Core/Models/IDataModel.cs b/src/HexManiac.Core/Models/IDataModel.cs index a8a43f77..83d9cd3a 100644 --- a/src/HexManiac.Core/Models/IDataModel.cs +++ b/src/HexManiac.Core/Models/IDataModel.cs @@ -78,6 +78,7 @@ namespace HavenSoft.HexManiac.Core.Models { IReadOnlyDictionary unmappedConstantsToRemove, IReadOnlyDictionary unmappedConstantsToAdd, IReadOnlyDictionary listsToRemove, IReadOnlyDictionary listsToAdd); T RelocateForExpansion(ModelDelta changeToken, T run, int minimumLength) where T : IFormattedRun; + T RelocateForExpansion(ModelDelta token, T run, int currentLength, int desiredLength) where T : IFormattedRun; int FindFreeSpace(int start, int length); void ClearAnchor(ModelDelta changeToken, int start, int length); void ClearFormat(ModelDelta changeToken, int start, int length); @@ -284,6 +285,7 @@ namespace HavenSoft.HexManiac.Core.Models { IReadOnlyDictionary listsToAdd); public abstract T RelocateForExpansion(ModelDelta changeToken, T run, int minimumLength) where T : IFormattedRun; + public abstract T RelocateForExpansion(ModelDelta token, T run, int currentLength, int desiredLength) where T : IFormattedRun; public abstract int FindFreeSpace(int start, int length); @@ -868,6 +870,7 @@ namespace HavenSoft.HexManiac.Core.Models { IReadOnlyDictionary unmappedConstantsToRemove, IReadOnlyDictionary unmappedConstantsToAdd, IReadOnlyDictionary listsToRemove, IReadOnlyDictionary listsToAdd) { } public override T RelocateForExpansion(ModelDelta changeToken, T run, int minimumLength) => throw new NotImplementedException(); + public override T RelocateForExpansion(ModelDelta changeToken, T run, int currentLength, int desiredLength) => throw new NotImplementedException(); public override int FindFreeSpace(int start, int length) => throw new NotImplementedException(); public override void ClearAnchor(ModelDelta changeToken, int start, int length) { } public override void ClearFormat(ModelDelta changeToken, int start, int length) { } diff --git a/src/HexManiac.Core/Models/PokemonModel.cs b/src/HexManiac.Core/Models/PokemonModel.cs index ecc69bee..630e837b 100644 --- a/src/HexManiac.Core/Models/PokemonModel.cs +++ b/src/HexManiac.Core/Models/PokemonModel.cs @@ -2,6 +2,7 @@ using HavenSoft.HexManiac.Core.Models.Runs; using HavenSoft.HexManiac.Core.Models.Runs.Factory; using HavenSoft.HexManiac.Core.Models.Runs.Sprites; +using HavenSoft.HexManiac.Core.ViewModels; using HavenSoft.HexManiac.Core.ViewModels.DataFormats; using HavenSoft.HexManiac.Core.ViewModels.Visitors; using System; @@ -1620,6 +1621,22 @@ namespace HavenSoft.HexManiac.Core.Models { } } + public override T RelocateForExpansion(ModelDelta token, T run, int currentLength, int desiredLength) { + if (currentLength < 1) currentLength = 1; + if (desiredLength <= currentLength) return run; + if (CanSafelyUse(run.Start + currentLength, run.Start + desiredLength)) return run; + + var freeSpace = FindFreeSpace(0x100, desiredLength); + lock (threadlock) { + if (freeSpace >= 0) { + return MoveRun(token, run, currentLength, freeSpace); + } else { + ExpandData(token, RawData.Length + desiredLength); + return MoveRun(token, run, currentLength, RawData.Length - desiredLength - 1); + } + } + } + public override int FindFreeSpace(int start, int minimumLength) { if (FreeSpaceStart != 0) start = FreeSpaceStart; if (start < EarliestAllowedAnchor) start = EarliestAllowedAnchor; diff --git a/src/HexManiac.Core/ViewModels/Tools/CodeTool.cs b/src/HexManiac.Core/ViewModels/Tools/CodeTool.cs index 1384e7e2..d0e722e2 100644 --- a/src/HexManiac.Core/ViewModels/Tools/CodeTool.cs +++ b/src/HexManiac.Core/ViewModels/Tools/CodeTool.cs @@ -406,7 +406,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools { } } else { if (run is NoInfoRun) run = Construct(run.Start, run.PointerSources); - run = model.RelocateForExpansion(history.CurrentChange, run, code.Length); + run = model.RelocateForExpansion(history.CurrentChange, run, body.CompiledLength, code.Length); if (start != run.Start) { ModelDataMoved?.Invoke(this, (start, run.Start)); start = run.Start; diff --git a/src/HexManiac.Tests/CodeToolTests.cs b/src/HexManiac.Tests/CodeToolTests.cs index 797e140f..d49164ca 100644 --- a/src/HexManiac.Tests/CodeToolTests.cs +++ b/src/HexManiac.Tests/CodeToolTests.cs @@ -693,6 +693,19 @@ label2:;goto <000050>;end"; Assert.IsType(Model.GetNextRun(0x100)); } + [Fact] + public void UnformattedScriptWithInnerAnchor_FormatThenExpand_Repoint() { + SetFullModel(0xFF); + "06 00 07 00 00 08 02 02".ToByteArray().WriteInto(Model.RawData, 0); + Model.ObserveAnchorWritten(Token, "parent", new XSERun(0)); + Tool.Mode = CodeMode.Script; + + EventScript += " "; + EventScript += ";end"; + + Assert.Single(Messages); + } + // TODO trainer ai script change -> no auto repoint? // TODO test that we get an error (not an exception) if we do auto on an unformatted pointer