don't auto-format script pointers in edge cases

* points to itself? Don't add the format
* points into existing data? Don't add the format
This commit is contained in:
haven1433
2023-03-07 07:29:37 -06:00
parent 36706bc740
commit 4959d8f8ca
3 changed files with 70 additions and 18 deletions

View File

@@ -28,6 +28,10 @@ namespace HavenSoft.HexManiac.Core {
return value;
}
public static bool InRange<T>(this T value, T min, T max) where T : IComparable<T> {
return min.CompareTo(value) <= 0 && value.CompareTo(max) < 0;
}
public static bool TryParseInt(this string str, out int result) {
if (str.StartsWith("0x") && int.TryParse(str.Substring(2), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out result)) return true;
if (int.TryParse(str, out result)) return true;

View File

@@ -229,24 +229,31 @@ namespace HavenSoft.HexManiac.Core.Models.Code {
}
} else {
var destination = model.ReadPointer(address + length);
if (destination >= 0 && destination < model.Count) {
if (model.GetNextRun(address + length) is PointerRun pointerRun && pointerRun.Start == address + length) {
// no need to clear/update
if (destination.InRange(0, model.Count) && !destination.InRange(address + length, address + length + 4)) {
var destinationRun = model.GetNextRun(destination);
if (destinationRun.Start < destination) {
// we're trying to point into already formatted data
// don't add the pointer source or destination
} else {
model.ClearFormat(token, address + length, 4);
model.ObserveRunWritten(token, new PointerRun(address + length));
}
if (arg.PointerType == ExpectedPointerType.Script) toProcess.Add(destination);
if (arg.PointerType == ExpectedPointerType.Text) {
WriteTextStream(model, token, destination, address + length);
} else if (arg.PointerType == ExpectedPointerType.Movement) {
WriteMovementStream(model, token, destination, address + length);
} else if (arg.PointerType == ExpectedPointerType.Mart) {
WriteMartStream(model, token, destination, address + length);
} else if (arg.PointerType == ExpectedPointerType.Decor) {
WriteDecorStream(model, token, destination, address + length);
} else if (arg.PointerType == ExpectedPointerType.SpriteTemplate) {
WriteSpriteTemplateStream(model, token, destination, address + length);
var pointerSource = model.GetNextRun(address + length);
if (pointerSource is PointerRun pointerRun && pointerRun.Start == address + length) {
// no need to clear/update
} else {
model.ClearFormat(token, address + length, 4);
model.ObserveRunWritten(token, new PointerRun(address + length));
}
if (arg.PointerType == ExpectedPointerType.Script) toProcess.Add(destination);
if (arg.PointerType == ExpectedPointerType.Text) {
WriteTextStream(model, token, destination, address + length);
} else if (arg.PointerType == ExpectedPointerType.Movement) {
WriteMovementStream(model, token, destination, address + length);
} else if (arg.PointerType == ExpectedPointerType.Mart) {
WriteMartStream(model, token, destination, address + length);
} else if (arg.PointerType == ExpectedPointerType.Decor) {
WriteDecorStream(model, token, destination, address + length);
} else if (arg.PointerType == ExpectedPointerType.SpriteTemplate) {
WriteSpriteTemplateStream(model, token, destination, address + length);
}
}
}
}

View File

@@ -706,7 +706,48 @@ label2:;goto <000050>;end";
Assert.Single(Messages);
}
// TODO trainer ai script change -> no auto repoint?
[Theory]
[InlineData("02")]
[InlineData("03")]
[InlineData("04")]
[InlineData("05")]
public void ScriptWithPointerToPointer_Format_NoPointerFormat(string destination) {
SetFullModel(0xFF);
$"06 00 {destination} 00 00 08 02".ToByteArray().WriteInto(Model.RawData, 0);
ViewPort.Edit("^script`xse`");
EventScript += " "; // force formatting
var run = Model.GetNextRun(1);
Assert.Equal(int.MaxValue, run.Start);
}
[Theory]
[InlineData("09")]
[InlineData("0A")]
[InlineData("0B")]
public void ScriptWithPointerToFuturePointer_Format_OnlySecondPointerKept(string destination) {
SetFullModel(0xFF);
$"06 00 {destination} 00 00 08 06 00 00 01 00 08 02".ToByteArray().WriteInto(Model.RawData, 0);
ViewPort.Edit("^script`xse`");
EventScript += " "; // force formatting
var run = Model.GetNextRun(1);
Assert.Equal(8, run.Start);
}
[Fact]
public void ScriptWithPointerIntoExistingData_Format_DoNotFormatPointer() {
SetFullModel(0xFF);
CreateTextTable("names", 0x100, "Adam", "Brad", "Carl", "Dave", "Eric", "Fred");
"06 00 02 01 00 08 02".ToByteArray().WriteInto(Model.RawData, 0);
ViewPort.Edit("@000 ^script`xse`");
EventScript += " "; // force formatting
Model.ResolveConflicts(); // no conflicts = pass
}
// TODO test that we get an error (not an exception) if we do auto on an unformatted pointer
}