repoint scripts based on previous script size, not computed size from model

This commit is contained in:
haven1433
2023-03-05 21:39:19 -06:00
parent 10f177154c
commit e65644a236
5 changed files with 49 additions and 1 deletions

View File

@@ -163,12 +163,18 @@ namespace HavenSoft.HexManiac.Core.Models
}
public delegate T RelocateForExpansionDelegate_ModelDelta_T_int<T>(ModelDelta changeToken, T run, int minimumLength) where T : Runs.IFormattedRun;
public delegate T RelocateForExpansionDelegate_ModelDelta_T_int_int<T>(ModelDelta changeToken, T run, int currentLength, int desiredLength) where T : Runs.IFormattedRun;
private readonly Dictionary<Type[], object> RelocateForExpansionDelegates_ModelDelta_T_int = new Dictionary<Type[], object>(new EnumerableEqualityComparer<Type>());
private readonly Dictionary<Type[], object> RelocateForExpansionDelegates_ModelDelta_T_int_int = new(new EnumerableEqualityComparer<Type>());
public void ImplementRelocateForExpansion<T>(RelocateForExpansionDelegate_ModelDelta_T_int<T> implementation) where T : Runs.IFormattedRun
{
var key = new Type[] { typeof(T) };
RelocateForExpansionDelegates_ModelDelta_T_int[key] = implementation;
}
public void ImplementRelocateForExpansion<T>(RelocateForExpansionDelegate_ModelDelta_T_int_int<T> implementation)where T : Runs.IFormattedRun {
var key = new Type[] { typeof(T) };
RelocateForExpansionDelegates_ModelDelta_T_int_int[key] = implementation;
}
public T RelocateForExpansion<T>(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<T>(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<T>)implementation).Invoke(changeToken, run, currentLength, desiredLength);
} else {
return default(T);
}
}
public Func<int, int, int> FindFreeSpace { get; set; }

View File

@@ -78,6 +78,7 @@ namespace HavenSoft.HexManiac.Core.Models {
IReadOnlyDictionary<string, int> unmappedConstantsToRemove, IReadOnlyDictionary<string, int> unmappedConstantsToAdd,
IReadOnlyDictionary<string, ValidationList> listsToRemove, IReadOnlyDictionary<string, ValidationList> listsToAdd);
T RelocateForExpansion<T>(ModelDelta changeToken, T run, int minimumLength) where T : IFormattedRun;
T RelocateForExpansion<T>(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<string, ValidationList> listsToAdd);
public abstract T RelocateForExpansion<T>(ModelDelta changeToken, T run, int minimumLength) where T : IFormattedRun;
public abstract T RelocateForExpansion<T>(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<string, int> unmappedConstantsToRemove, IReadOnlyDictionary<string, int> unmappedConstantsToAdd,
IReadOnlyDictionary<string, ValidationList> listsToRemove, IReadOnlyDictionary<string, ValidationList> listsToAdd) { }
public override T RelocateForExpansion<T>(ModelDelta changeToken, T run, int minimumLength) => throw new NotImplementedException();
public override T RelocateForExpansion<T>(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) { }

View File

@@ -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<T>(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;

View File

@@ -406,7 +406,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools {
}
} else {
if (run is NoInfoRun) run = Construct<SERun>(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;

View File

@@ -693,6 +693,19 @@ label2:;goto <000050>;end";
Assert.IsType<TSERun>(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