diff --git a/src/HexManiac.Core/Models/IDataModel.cs b/src/HexManiac.Core/Models/IDataModel.cs index 699b0ff7..0225bfa5 100644 --- a/src/HexManiac.Core/Models/IDataModel.cs +++ b/src/HexManiac.Core/Models/IDataModel.cs @@ -13,6 +13,11 @@ namespace HavenSoft.HexManiac.Core.Models { bool HasChanged(int index); void ResetChanges(); + /// + /// Used during repointing + /// + int FreeSpaceStart { get; set; } + new byte this[int index] { get; set; } IReadOnlyList Arrays { get; } IReadOnlyList Streams { get; } @@ -76,6 +81,8 @@ namespace HavenSoft.HexManiac.Core.Models { public BaseModel(byte[] data) => RawData = data; + public int FreeSpaceStart { get; set; } + public virtual IReadOnlyList Arrays { get; } = new List(); public virtual IReadOnlyList Streams { get; } = new List(); public virtual IReadOnlyList Anchors { get; } = new List(); diff --git a/src/HexManiac.Core/Models/PokemonModel.cs b/src/HexManiac.Core/Models/PokemonModel.cs index 123e86ab..7006f212 100644 --- a/src/HexManiac.Core/Models/PokemonModel.cs +++ b/src/HexManiac.Core/Models/PokemonModel.cs @@ -58,6 +58,7 @@ namespace HavenSoft.HexManiac.Core.Models { WriteSpriteRuns(pointersForDestination); WriteStringRuns(pointersForDestination); ResolveConflicts(); + FreeSpaceStart = EarliestAllowedAnchor; if (metadata == null) return; @@ -88,6 +89,8 @@ namespace HavenSoft.HexManiac.Core.Models { } } + if (metadata.FreeSpaceSearch >= 0) FreeSpaceStart = metadata.FreeSpaceSearch; + ResolveConflicts(); } @@ -914,6 +917,8 @@ namespace HavenSoft.HexManiac.Core.Models { } public override int FindFreeSpace(int start, int minimumLength) { + start = FreeSpaceStart; + if (start < EarliestAllowedAnchor) start = EarliestAllowedAnchor; const int SpacerLength = 0x100; minimumLength += 0x140; // make sure there's plenty of room after, so that we're not in the middle of some other data set var runIndex = 0; @@ -940,6 +945,7 @@ namespace HavenSoft.HexManiac.Core.Models { // found a good spot! // move the run + FreeSpaceStart = start; return start; } @@ -1367,7 +1373,7 @@ namespace HavenSoft.HexManiac.Core.Models { lists.Add(new StoredList(name, members.ToList())); } - return new StoredMetadata(anchors, unmappedPointers, matchedWords, lists, metadataInfo); + return new StoredMetadata(anchors, unmappedPointers, matchedWords, lists, metadataInfo, FreeSpaceStart); } /// diff --git a/src/HexManiac.Core/Models/StoredMetadata.cs b/src/HexManiac.Core/Models/StoredMetadata.cs index 5c955479..753fb2fa 100644 --- a/src/HexManiac.Core/Models/StoredMetadata.cs +++ b/src/HexManiac.Core/Models/StoredMetadata.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Runtime.ExceptionServices; namespace HavenSoft.HexManiac.Core.Models { public class StoredMetadata { @@ -11,15 +12,17 @@ namespace HavenSoft.HexManiac.Core.Models { public IReadOnlyList MatchedWords { get; } public IReadOnlyList Lists { get; } public string Version { get; } + public int FreeSpaceSearch { get; } = -1; public bool IsEmpty => NamedAnchors.Count == 0 && UnmappedPointers.Count == 0; - public StoredMetadata(IReadOnlyList anchors, IReadOnlyList unmappedPointers, IReadOnlyList matchedWords, IReadOnlyList lists, IMetadataInfo generalInfo) { + public StoredMetadata(IReadOnlyList anchors, IReadOnlyList unmappedPointers, IReadOnlyList matchedWords, IReadOnlyList lists, IMetadataInfo generalInfo, int freeSpaceSearch) { NamedAnchors = anchors ?? new List(); UnmappedPointers = unmappedPointers ?? new List(); MatchedWords = matchedWords ?? new List(); Lists = lists ?? new List(); Version = generalInfo.VersionNumber; + FreeSpaceSearch = freeSpaceSearch; } public StoredMetadata(string[] lines) { @@ -65,6 +68,10 @@ namespace HavenSoft.HexManiac.Core.Models { Version = cleanLine.Split("'''")[1]; } + if (cleanLine.StartsWith("FreeSpaceSearch = '''")) { + if (int.TryParse(cleanLine.Split("'''")[1], out var fss)) FreeSpaceSearch = fss; + } + if (cleanLine.Contains('=') && int.TryParse(cleanLine.Split('=')[0].Trim(), out int currentItemIndex)) { if (currentItemChildren == null) currentItemChildren = new List(); while (currentItemChildren.Count < currentItemIndex) currentItemChildren.Add(null); @@ -98,6 +105,7 @@ namespace HavenSoft.HexManiac.Core.Models { "[General]" }; if (Version != null) lines.Add($"ApplicationVersion = '''{Version}'''"); + lines.Add($"FreeSpaceSearch = '''{FreeSpaceSearch}'''"); lines.Add(string.Empty); lines.Add("#################################"); diff --git a/src/HexManiac.Core/ViewModels/ViewPort.cs b/src/HexManiac.Core/ViewModels/ViewPort.cs index 6f98afd8..a92f2872 100644 --- a/src/HexManiac.Core/ViewModels/ViewPort.cs +++ b/src/HexManiac.Core/ViewModels/ViewPort.cs @@ -424,6 +424,14 @@ namespace HavenSoft.HexManiac.Core.ViewModels { #endregion + public int FreeSpaceStart { get => Model.FreeSpaceStart; set { + if (Model.FreeSpaceStart != value) { + Model.FreeSpaceStart = value; + NotifyPropertyChanged(); + } + } + } + private readonly ToolTray tools; public bool HasTools => true; public IToolTrayViewModel Tools => tools; @@ -896,10 +904,9 @@ namespace HavenSoft.HexManiac.Core.ViewModels { return false; } - var startSearch = (Model as PokemonModel)?.EarliestAllowedAnchor ?? 0; var length = FormatRunFactory.GetStrategy(pointerSegment.InnerFormat).LengthForNewRun(Model, pointer); - var insert = Model.FindFreeSpace(startSearch, length); + var insert = Model.FindFreeSpace(0, length); if (insert < 0) { insert = Model.Count; Model.ExpandData(CurrentChange, Model.Count + length); @@ -1970,6 +1977,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels { currentView = new HexElement[Width, Height]; RequestMenuClose?.Invoke(this, EventArgs.Empty); NotifyCollectionChanged(ResetArgs); + NotifyPropertyChanged(nameof(FreeSpaceStart)); } private void RefreshBackingDataFull() { diff --git a/src/HexManiac.WPF/Controls/TabView.xaml b/src/HexManiac.WPF/Controls/TabView.xaml index bc53ee1e..8871ccf9 100644 --- a/src/HexManiac.WPF/Controls/TabView.xaml +++ b/src/HexManiac.WPF/Controls/TabView.xaml @@ -14,10 +14,14 @@ - - + + + + + +