From 7b0c9f06e8381cdf0aa111fbebde8259f34348d4 Mon Sep 17 00:00:00 2001 From: Benjamin Popp Date: Fri, 5 Jun 2020 08:32:24 -0500 Subject: [PATCH] Add Free Space selector Reasonable use case: user has multiple tools, some that can work with an expanded rom and some that cannot. They want to save what freespace they have below 1000000 for the weaker tools. So HMA needs to be able to put new data into a user-specified freespace (still being safe, of course). --- src/HexManiac.Core/Models/IDataModel.cs | 7 +++++++ src/HexManiac.Core/Models/PokemonModel.cs | 8 +++++++- src/HexManiac.Core/Models/StoredMetadata.cs | 10 +++++++++- src/HexManiac.Core/ViewModels/ViewPort.cs | 12 ++++++++++-- src/HexManiac.WPF/Controls/TabView.xaml | 8 ++++++-- 5 files changed, 39 insertions(+), 6 deletions(-) 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 @@ - - + + + + + +