diff --git a/Gen3Hex.sln b/HexManiacAdvance.sln similarity index 77% rename from Gen3Hex.sln rename to HexManiacAdvance.sln index 4cb0c123..46fbf6d2 100644 --- a/Gen3Hex.sln +++ b/HexManiacAdvance.sln @@ -3,11 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.28010.2016 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gen3Hex.WPF", "src\Gen3Hex.WPF\Gen3Hex.WPF.csproj", "{386DC8E2-BABC-475C-94B6-37B3986F5F4C}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HexManiac.WPF", "src\HexManiac.WPF\HexManiac.WPF.csproj", "{386DC8E2-BABC-475C-94B6-37B3986F5F4C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gen3Hex.Core", "src\Gen3Hex.Core\Gen3Hex.Core.csproj", "{B7B9D932-4271-493D-AADD-6CF147C91373}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HexManiac.Core", "src\HexManiac.Core\HexManiac.Core.csproj", "{B7B9D932-4271-493D-AADD-6CF147C91373}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gen3Hex.Tests", "src\Gen3Hex.Tests\Gen3Hex.Tests.csproj", "{B6A52732-E0F8-466D-8E29-664C797A21FA}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HexManiac.Tests", "src\HexManiac.Tests\HexManiac.Tests.csproj", "{B6A52732-E0F8-466D-8E29-664C797A21FA}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/Gen3Hex.Core/AssemblyInfo.cs b/src/Gen3Hex.Core/AssemblyInfo.cs deleted file mode 100644 index a5702ca0..00000000 --- a/src/Gen3Hex.Core/AssemblyInfo.cs +++ /dev/null @@ -1,3 +0,0 @@ -using System.Reflection; - -[assembly: AssemblyTitle("Gen3Hex.Core")] diff --git a/src/Gen3Hex.WPF/Resources/Snorlax.ico b/src/Gen3Hex.WPF/Resources/Snorlax.ico deleted file mode 100644 index 7df4fd8f..00000000 Binary files a/src/Gen3Hex.WPF/Resources/Snorlax.ico and /dev/null differ diff --git a/src/Gen3Hex.WPF/Resources/snorlax.png b/src/Gen3Hex.WPF/Resources/snorlax.png deleted file mode 100644 index 3492d6ff..00000000 Binary files a/src/Gen3Hex.WPF/Resources/snorlax.png and /dev/null differ diff --git a/src/HexManiac.Core/AssemblyInfo.cs b/src/HexManiac.Core/AssemblyInfo.cs new file mode 100644 index 00000000..60bfc7eb --- /dev/null +++ b/src/HexManiac.Core/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Reflection; + +[assembly: AssemblyTitle("HexManiac.Core")] diff --git a/src/Gen3Hex.Core/Gen3Hex.Core.csproj b/src/HexManiac.Core/HexManiac.Core.csproj similarity index 96% rename from src/Gen3Hex.Core/Gen3Hex.Core.csproj rename to src/HexManiac.Core/HexManiac.Core.csproj index 2c65069b..db489d2d 100644 --- a/src/Gen3Hex.Core/Gen3Hex.Core.csproj +++ b/src/HexManiac.Core/HexManiac.Core.csproj @@ -6,8 +6,8 @@ AnyCPU {B7B9D932-4271-493D-AADD-6CF147C91373} Library - HavenSoft.Gen3Hex.Core - Gen3Hex.Core + HavenSoft.HexManiac.Core + HexManiac.Core v4.7.2 512 true @@ -47,6 +47,7 @@ + diff --git a/src/Gen3Hex.Core/ICommandExtensions.cs b/src/HexManiac.Core/ICommandExtensions.cs similarity index 92% rename from src/Gen3Hex.Core/ICommandExtensions.cs rename to src/HexManiac.Core/ICommandExtensions.cs index 5e5281ce..c8595c0a 100644 --- a/src/Gen3Hex.Core/ICommandExtensions.cs +++ b/src/HexManiac.Core/ICommandExtensions.cs @@ -1,6 +1,6 @@ using System.Windows.Input; -namespace HavenSoft.Gen3Hex.Core { +namespace HavenSoft.HexManiac.Core { public static class ICommandExtensions { /// /// Runs execute on the command with a null parameter. diff --git a/src/Gen3Hex.Core/Models/AutoSearchModel.cs b/src/HexManiac.Core/Models/AutoSearchModel.cs similarity index 54% rename from src/Gen3Hex.Core/Models/AutoSearchModel.cs rename to src/HexManiac.Core/Models/AutoSearchModel.cs index 1eb2988a..e4b18b44 100644 --- a/src/Gen3Hex.Core/Models/AutoSearchModel.cs +++ b/src/HexManiac.Core/Models/AutoSearchModel.cs @@ -1,8 +1,8 @@ -using HavenSoft.Gen3Hex.Core.Models.Runs; +using HavenSoft.HexManiac.Core.Models.Runs; using System.Linq; -using static HavenSoft.Gen3Hex.Core.Models.Runs.ArrayRun; +using static HavenSoft.HexManiac.Core.Models.Runs.ArrayRun; -namespace HavenSoft.Gen3Hex.Core.Models { +namespace HavenSoft.HexManiac.Core.Models { public class AutoSearchModel : PokemonModel { public const string Ruby = "AXVE", @@ -11,19 +11,44 @@ namespace HavenSoft.Gen3Hex.Core.Models { FireRed = "BPRE", LeafGreen = "BPGE"; + private readonly string gameCode; + private readonly ModelDelta noChangeDelta = new NoDataChangeDeltaModel(); + + /// + /// The first 0x100 bytes of the GBA rom is always the header. + /// The next 0x100 bytes contains some tables and some startup code, but nothing interesting to point to. + /// Choosing 0x200 might prevent us from seeing an actual anchor, but it will also remove a bunch + /// of false positives and keep us from getting conflicts with the RomName (see DecodeHeader). + /// + public override int EarliestAllowedAnchor => 0x200; + public AutoSearchModel(byte[] data, StoredMetadata metadata = null) : base(data, metadata) { if (metadata != null) return; - var noChangeDelta = new NoDataChangeDeltaModel(); - - ClearFormat(noChangeDelta, -1, 0x101); // starting before the beginning to clear the anchor at the very start - - var gameCode = string.Concat(Enumerable.Range(0xAC, 4).Select(i => ((char)data[i]).ToString())); + gameCode = string.Concat(Enumerable.Range(0xAC, 4).Select(i => ((char)data[i]).ToString())); // in vanilla emerald, this pointer isn't four-byte aligned // it's at the very front of the ROM, so if there's no metadata we can be pretty sure that the pointer is still there if (gameCode == Emerald && data[0x1C3] == 0x08) ObserveRunWritten(noChangeDelta, new PointerRun(0x1C0)); + var gamesToDecode = new[] { Ruby, Sapphire, Emerald, FireRed, LeafGreen }; + if (gamesToDecode.Contains(gameCode)) { + DecodeHeader(); + DecodeNameArrays(); + } + } + + private void DecodeHeader() { + ObserveAnchorWritten(noChangeDelta, "GameTitle", new AsciiRun(0xA0, 12)); + ObserveAnchorWritten(noChangeDelta, "GameCode", new AsciiRun(0xAC, 4)); + ObserveAnchorWritten(noChangeDelta, "MakerCode", new AsciiRun(0xB0, 2)); + + if (gameCode != Ruby && gameCode != Sapphire) { + ObserveAnchorWritten(noChangeDelta, "RomName", new AsciiRun(0x108, 0x20)); + } + } + + private void DecodeNameArrays() { // pokenames if (TrySearch(this, "[name\"\"11]", out var pokenames)) { ObserveAnchorWritten(noChangeDelta, "pokenames", pokenames); diff --git a/src/Gen3Hex.Core/Models/Enums.cs b/src/HexManiac.Core/Models/Enums.cs similarity index 53% rename from src/Gen3Hex.Core/Models/Enums.cs rename to src/HexManiac.Core/Models/Enums.cs index 8e9a162d..cb830010 100644 --- a/src/Gen3Hex.Core/Models/Enums.cs +++ b/src/HexManiac.Core/Models/Enums.cs @@ -1,3 +1,3 @@ -namespace HavenSoft.Gen3Hex.Core.Models { +namespace HavenSoft.HexManiac.Core.Models { public enum Direction { Left, Right, Up, Down } } diff --git a/src/Gen3Hex.Core/Models/ErrorInfo.cs b/src/HexManiac.Core/Models/ErrorInfo.cs similarity index 93% rename from src/Gen3Hex.Core/Models/ErrorInfo.cs rename to src/HexManiac.Core/Models/ErrorInfo.cs index 2e80c0d0..3e4c56d0 100644 --- a/src/Gen3Hex.Core/Models/ErrorInfo.cs +++ b/src/HexManiac.Core/Models/ErrorInfo.cs @@ -1,6 +1,6 @@ using System; -namespace HavenSoft.Gen3Hex.Core.Models { +namespace HavenSoft.HexManiac.Core.Models { public class ErrorInfo : IEquatable { public static ErrorInfo NoError { get; } = new ErrorInfo(null); public bool HasError { get; } diff --git a/src/Gen3Hex.Core/Models/IDataModel.cs b/src/HexManiac.Core/Models/IDataModel.cs similarity index 98% rename from src/Gen3Hex.Core/Models/IDataModel.cs rename to src/HexManiac.Core/Models/IDataModel.cs index 24f10b1d..4d8cdf99 100644 --- a/src/Gen3Hex.Core/Models/IDataModel.cs +++ b/src/HexManiac.Core/Models/IDataModel.cs @@ -1,11 +1,11 @@ -using HavenSoft.Gen3Hex.Core.Models.Runs; -using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats; +using HavenSoft.HexManiac.Core.Models.Runs; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; using System; using System.Collections; using System.Collections.Generic; using System.Linq; -namespace HavenSoft.Gen3Hex.Core.Models { +namespace HavenSoft.HexManiac.Core.Models { public interface IDataModel : IReadOnlyList { byte[] RawData { get; } new byte this[int index] { get; set; } diff --git a/src/Gen3Hex.Core/Models/IFileSystem.cs b/src/HexManiac.Core/Models/IFileSystem.cs similarity index 98% rename from src/Gen3Hex.Core/Models/IFileSystem.cs rename to src/HexManiac.Core/Models/IFileSystem.cs index 0a314859..4b6717ac 100644 --- a/src/Gen3Hex.Core/Models/IFileSystem.cs +++ b/src/HexManiac.Core/Models/IFileSystem.cs @@ -1,6 +1,6 @@ using System; -namespace HavenSoft.Gen3Hex.Core.Models { +namespace HavenSoft.HexManiac.Core.Models { public interface IFileSystem { string CopyText { get; set; } diff --git a/src/Gen3Hex.Core/Models/LoadedFile.cs b/src/HexManiac.Core/Models/LoadedFile.cs similarity index 82% rename from src/Gen3Hex.Core/Models/LoadedFile.cs rename to src/HexManiac.Core/Models/LoadedFile.cs index 89c221cf..3b7659b6 100644 --- a/src/Gen3Hex.Core/Models/LoadedFile.cs +++ b/src/HexManiac.Core/Models/LoadedFile.cs @@ -1,4 +1,4 @@ -namespace HavenSoft.Gen3Hex.Core.Models { +namespace HavenSoft.HexManiac.Core.Models { public class LoadedFile { public string Name { get; } diff --git a/src/Gen3Hex.Core/Models/ModelDelta.cs b/src/HexManiac.Core/Models/ModelDelta.cs similarity index 98% rename from src/Gen3Hex.Core/Models/ModelDelta.cs rename to src/HexManiac.Core/Models/ModelDelta.cs index 8463ae74..e8cd0e1e 100644 --- a/src/Gen3Hex.Core/Models/ModelDelta.cs +++ b/src/HexManiac.Core/Models/ModelDelta.cs @@ -1,8 +1,8 @@ -using HavenSoft.Gen3Hex.Core.Models.Runs; +using HavenSoft.HexManiac.Core.Models.Runs; using System.Collections.Generic; using System.Linq; -namespace HavenSoft.Gen3Hex.Core.Models { +namespace HavenSoft.HexManiac.Core.Models { /// /// Represents a single conceptual change in the loaded data, including /// editing data, adding / removing formats / format names, diff --git a/src/Gen3Hex.Core/Models/PCSString.cs b/src/HexManiac.Core/Models/PCSString.cs similarity index 99% rename from src/Gen3Hex.Core/Models/PCSString.cs rename to src/HexManiac.Core/Models/PCSString.cs index ee186ea7..d65ad04a 100644 --- a/src/Gen3Hex.Core/Models/PCSString.cs +++ b/src/HexManiac.Core/Models/PCSString.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.Text; -namespace HavenSoft.Gen3Hex.Core.Models { +namespace HavenSoft.HexManiac.Core.Models { public class PCSString { public static IReadOnlyList PCS; public static IReadOnlyList Newlines; diff --git a/src/Gen3Hex.Core/Models/Point.cs b/src/HexManiac.Core/Models/Point.cs similarity index 91% rename from src/Gen3Hex.Core/Models/Point.cs rename to src/HexManiac.Core/Models/Point.cs index bf89dae9..a6d06379 100644 --- a/src/Gen3Hex.Core/Models/Point.cs +++ b/src/HexManiac.Core/Models/Point.cs @@ -1,6 +1,6 @@ using System; -namespace HavenSoft.Gen3Hex.Core.Models { +namespace HavenSoft.HexManiac.Core.Models { public struct Point : IEquatable { public int X { get; } public int Y { get; } diff --git a/src/Gen3Hex.Core/Models/PokemonModel.cs b/src/HexManiac.Core/Models/PokemonModel.cs similarity index 90% rename from src/Gen3Hex.Core/Models/PokemonModel.cs rename to src/HexManiac.Core/Models/PokemonModel.cs index 3b0355ae..a5622344 100644 --- a/src/Gen3Hex.Core/Models/PokemonModel.cs +++ b/src/HexManiac.Core/Models/PokemonModel.cs @@ -1,15 +1,16 @@ -using HavenSoft.Gen3Hex.Core.Models.Runs; -using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats; +using HavenSoft.HexManiac.Core.Models.Runs; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; -using static HavenSoft.Gen3Hex.Core.Models.Runs.ArrayRun; -using static HavenSoft.Gen3Hex.Core.Models.Runs.BaseRun; -using static HavenSoft.Gen3Hex.Core.Models.Runs.PCSRun; +using static HavenSoft.HexManiac.Core.Models.Runs.ArrayRun; +using static HavenSoft.HexManiac.Core.Models.Runs.AsciiRun; +using static HavenSoft.HexManiac.Core.Models.Runs.BaseRun; +using static HavenSoft.HexManiac.Core.Models.Runs.PCSRun; -namespace HavenSoft.Gen3Hex.Core.Models { +namespace HavenSoft.HexManiac.Core.Models { public class PokemonModel : BaseModel { // list of runs, in sorted address order. Includes no names private readonly List runs = new List(); @@ -24,6 +25,8 @@ namespace HavenSoft.Gen3Hex.Core.Models { private readonly Dictionary> unmappedNameToSources = new Dictionary>(); private readonly Dictionary sourceToUnmappedName = new Dictionary(); + public virtual int EarliestAllowedAnchor => 0; + #region Constructor public PokemonModel(byte[] data, StoredMetadata metadata = null) : base(data) { @@ -50,13 +53,34 @@ namespace HavenSoft.Gen3Hex.Core.Models { } } + /// + /// Finds pointers based on Heuristics. + /// This is definitely wrong, but it's pretty good. + /// private void SearchForPointers(Dictionary> pointersForDestination, SortedList destinationForSource) { + // pointers must be 4-byte aligned for (int i = 0; i < RawData.Length - 3; i += 4) { + + // pointers must end in 08 or 09 if (RawData[i + 3] != 0x08 && RawData[i + 3] != 0x09) continue; + + // pointers must point to locations that are 4-byte aligned if (RawData[i] % 4 != 0) continue; var source = i; var destination = ReadPointer(i); + + // pointers must point into the data if (destination >= RawData.Length) continue; + + // pointers must not point at the header + if (destination < EarliestAllowedAnchor) continue; + + // pointers must point at something useful, not just a bunch of FF + bool pointsToManyFF = true; + for (int j = 0; j < 4 && pointsToManyFF && destination + j < RawData.Length; j++) pointsToManyFF = RawData[destination + j] == 0xFF; + if (pointsToManyFF) continue; + + // we found a pointer! if (!pointersForDestination.ContainsKey(destination)) pointersForDestination[destination] = new List(); pointersForDestination[destination].Add(source); destinationForSource.Add(source, destination); @@ -279,6 +303,8 @@ namespace HavenSoft.Gen3Hex.Core.Models { ClearFormat(changeToken, run.Start, run.Length); } + var existingRun = (index >= 0 && index < runs.Count) ? runs[index] : null; + if (anchorForAddress.TryGetValue(location, out string oldAnchorName)) { anchorForAddress.Remove(location); addressForAnchor.Remove(oldAnchorName); @@ -296,7 +322,8 @@ namespace HavenSoft.Gen3Hex.Core.Models { changeToken.AddName(location, anchorName); } - var sources = GetSourcesPointingToNewAnchor(changeToken, anchorName); + var seakPointers = existingRun?.PointerSources == null || existingRun?.Start != location; + var sources = GetSourcesPointingToNewAnchor(changeToken, anchorName, seakPointers); var newRun = run.MergeAnchor(sources); ObserveRunWritten(changeToken, newRun); } @@ -585,13 +612,17 @@ namespace HavenSoft.Gen3Hex.Core.Models { private static (string, string) SplitNameAndFormat(string text) { var name = text.Substring(1).Trim(); string format = string.Empty; + int split = -1; if (name.Contains(ArrayStart)) { - var split = name.IndexOf(ArrayStart); - format = name.Substring(split); - name = name.Substring(0, split); + split = name.IndexOf(ArrayStart); } else if (name.Contains(StringDelimeter)) { - var split = name.IndexOf(StringDelimeter); + split = name.IndexOf(StringDelimeter); + } else if (name.Contains(StreamDelimeter)) { + split = name.IndexOf(StreamDelimeter); + } + + if (split != -1) { format = name.Substring(split); name = name.Substring(0, split); } @@ -610,6 +641,12 @@ namespace HavenSoft.Gen3Hex.Core.Models { return new ErrorInfo($"Format was specified as a string, but a string would overlap the next anchor."); } run = new PCSRun(dataIndex, length); + } else if (format.StartsWith(StreamDelimeter + "asc" + StreamDelimeter)) { + if (int.TryParse(format.Substring(5), out var length)) { + run = new AsciiRun(dataIndex, length); + } else { + return new ErrorInfo($"Ascii runs must include a length."); + } } else if (TryParse(model, format, dataIndex, null, out var arrayRun)) { run = arrayRun; } else if (format != string.Empty) { @@ -621,7 +658,7 @@ namespace HavenSoft.Gen3Hex.Core.Models { private static ErrorInfo ValidateAnchorNameAndFormat(IDataModel model, IFormattedRun runToWrite, string name, string format, int dataIndex) { var existingRun = model.GetNextRun(dataIndex); - var nextRun = existingRun.Start > dataIndex ? existingRun : model.GetNextRun(existingRun.Start + existingRun.Length); + var nextRun = existingRun.Start > dataIndex ? existingRun : model.GetNextRun(existingRun.Start + Math.Max(existingRun.Length, 1)); if (name.ToLower() == "null") { return new ErrorInfo("'null' is a reserved word and cannot be used as an anchor name."); @@ -664,9 +701,15 @@ namespace HavenSoft.Gen3Hex.Core.Models { /// /// The list of sources that point at the new anchor /// - private IReadOnlyList GetSourcesPointingToNewAnchor(ModelDelta changeToken, string anchorName) { + private IReadOnlyList GetSourcesPointingToNewAnchor(ModelDelta changeToken, string anchorName, bool seakPointers) { if (!addressForAnchor.TryGetValue(anchorName, out int location)) return new List(); // new anchor is unnamed, so nothing points to it yet - if (!unmappedNameToSources.TryGetValue(anchorName, out var sources)) return new List(); // no pointer was waiting for this anchor to be created + + if (!unmappedNameToSources.TryGetValue(anchorName, out var sources)) { + // no pointer was waiting for this anchor to be created + // but the user thinks there's something pointing here + if (seakPointers) return SearchForPointersToAnchor(changeToken, location); + return new List(); + } foreach (var source in sources) { var index = BinarySearch(source); @@ -681,6 +724,27 @@ namespace HavenSoft.Gen3Hex.Core.Models { return sources; } + private IReadOnlyList SearchForPointersToAnchor(ModelDelta changeToken, int address) { + var results = new List(); + + for (int i = 3; i < RawData.Length; i++) { + if (RawData[i] != 0x08 && RawData[i] != 0x09) continue; + int destination = ReadPointer(i - 3); + if (destination != address) continue; + var index = BinarySearch(i-3); + if (index >= 0) continue; + index = ~index; + if (index < runs.Count && runs[index].Start <= i) continue; + if (index > 0 && runs[index - 1].Start + runs[index - 1].Length > i - 3) continue; + var newRun = new PointerRun(i - 3); + runs.Insert(index, newRun); + changeToken.AddRun(newRun); + results.Add(i - 3); + } + + return results; + } + private IFormattedRun MoveRun(ModelDelta changeToken, IFormattedRun run, int newStart) { // repoint foreach (var source in run.PointerSources) { @@ -740,6 +804,9 @@ namespace HavenSoft.Gen3Hex.Core.Models { return true; } + // if an existing run starts exactly at start, return that index + // otherwise, return a number such that ~index would be inserted into the list at the correct index + // so ~index - 1 is the previous run, and ~index is the next run private int BinarySearch(int start) { var index = runs.BinarySearch(new CompareFormattedRun(start), FormattedRunComparer.Instance); return index; diff --git a/src/Gen3Hex.Core/Models/Runs/ArrayRun.cs b/src/HexManiac.Core/Models/Runs/ArrayRun.cs similarity index 99% rename from src/Gen3Hex.Core/Models/Runs/ArrayRun.cs rename to src/HexManiac.Core/Models/Runs/ArrayRun.cs index a90fe03a..7592374d 100644 --- a/src/Gen3Hex.Core/Models/Runs/ArrayRun.cs +++ b/src/HexManiac.Core/Models/Runs/ArrayRun.cs @@ -1,10 +1,10 @@ -using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; using System; using System.Collections.Generic; using System.Linq; using System.Text; -namespace HavenSoft.Gen3Hex.Core.Models.Runs { +namespace HavenSoft.HexManiac.Core.Models.Runs { public enum ElementContentType { Unknown, PCS, diff --git a/src/HexManiac.Core/Models/Runs/AsciiRun.cs b/src/HexManiac.Core/Models/Runs/AsciiRun.cs new file mode 100644 index 00000000..5de5782e --- /dev/null +++ b/src/HexManiac.Core/Models/Runs/AsciiRun.cs @@ -0,0 +1,22 @@ +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; +using System.Collections.Generic; + +namespace HavenSoft.HexManiac.Core.Models.Runs { + public class AsciiRun : BaseRun { + public const char StreamDelimeter = '`'; + + public override int Length { get; } + + public override string FormatString => "`asc`" + Length; + + public AsciiRun(int start, int length, IReadOnlyList pointerSources = null) : base(start, pointerSources) => Length = length; + + public override IDataFormat CreateDataFormat(IDataModel data, int index) { + return new Ascii(Start, index - Start, (char)data[index]); + } + + protected override IFormattedRun Clone(IReadOnlyList newPointerSources) { + return new AsciiRun(Start, Length, newPointerSources); + } + } +} diff --git a/src/Gen3Hex.Core/Models/Runs/IFormattedRun.cs b/src/HexManiac.Core/Models/Runs/IFormattedRun.cs similarity index 96% rename from src/Gen3Hex.Core/Models/Runs/IFormattedRun.cs rename to src/HexManiac.Core/Models/Runs/IFormattedRun.cs index cfc66f3c..bc29cc00 100644 --- a/src/Gen3Hex.Core/Models/Runs/IFormattedRun.cs +++ b/src/HexManiac.Core/Models/Runs/IFormattedRun.cs @@ -1,9 +1,9 @@ -using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; using System; using System.Collections.Generic; using System.Linq; -namespace HavenSoft.Gen3Hex.Core.Models.Runs { +namespace HavenSoft.HexManiac.Core.Models.Runs { public interface IFormattedRun { int Start { get; } int Length { get; } diff --git a/src/Gen3Hex.Core/Models/Runs/PCSRun.cs b/src/HexManiac.Core/Models/Runs/PCSRun.cs similarity index 94% rename from src/Gen3Hex.Core/Models/Runs/PCSRun.cs rename to src/HexManiac.Core/Models/Runs/PCSRun.cs index 0e273409..04945521 100644 --- a/src/Gen3Hex.Core/Models/Runs/PCSRun.cs +++ b/src/HexManiac.Core/Models/Runs/PCSRun.cs @@ -1,7 +1,7 @@ -using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; using System.Collections.Generic; -namespace HavenSoft.Gen3Hex.Core.Models.Runs { +namespace HavenSoft.HexManiac.Core.Models.Runs { public class PCSRun : BaseRun { public const char StringDelimeter = '"'; diff --git a/src/Gen3Hex.Core/Models/Runs/PointerRun.cs b/src/HexManiac.Core/Models/Runs/PointerRun.cs similarity index 88% rename from src/Gen3Hex.Core/Models/Runs/PointerRun.cs rename to src/HexManiac.Core/Models/Runs/PointerRun.cs index 49dce8fb..7fcb89db 100644 --- a/src/Gen3Hex.Core/Models/Runs/PointerRun.cs +++ b/src/HexManiac.Core/Models/Runs/PointerRun.cs @@ -1,7 +1,7 @@ -using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; using System.Collections.Generic; -namespace HavenSoft.Gen3Hex.Core.Models.Runs { +namespace HavenSoft.HexManiac.Core.Models.Runs { public class PointerRun : BaseRun { public const char PointerStart = '<'; public const char PointerEnd = '>'; diff --git a/src/Gen3Hex.Core/Models/SearchByte.cs b/src/HexManiac.Core/Models/SearchByte.cs similarity index 96% rename from src/Gen3Hex.Core/Models/SearchByte.cs rename to src/HexManiac.Core/Models/SearchByte.cs index d91d0c13..bb6818e2 100644 --- a/src/Gen3Hex.Core/Models/SearchByte.cs +++ b/src/HexManiac.Core/Models/SearchByte.cs @@ -2,7 +2,7 @@ using System.Diagnostics; using System.Linq; -namespace HavenSoft.Gen3Hex.Core.Models { +namespace HavenSoft.HexManiac.Core.Models { public interface ISearchByte { bool Match(byte value); } diff --git a/src/Gen3Hex.Core/Models/StoredMetadata.cs b/src/HexManiac.Core/Models/StoredMetadata.cs similarity index 98% rename from src/Gen3Hex.Core/Models/StoredMetadata.cs rename to src/HexManiac.Core/Models/StoredMetadata.cs index 0081d4b5..7adb18d5 100644 --- a/src/Gen3Hex.Core/Models/StoredMetadata.cs +++ b/src/HexManiac.Core/Models/StoredMetadata.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; -namespace HavenSoft.Gen3Hex.Core.Models { +namespace HavenSoft.HexManiac.Core.Models { public class StoredMetadata { public IReadOnlyList NamedAnchors { get; } public IReadOnlyList UnmappedPointers { get; } diff --git a/src/Gen3Hex.Core/NumericExtensions.cs b/src/HexManiac.Core/NumericExtensions.cs similarity index 92% rename from src/Gen3Hex.Core/NumericExtensions.cs rename to src/HexManiac.Core/NumericExtensions.cs index 416ea6e5..51613354 100644 --- a/src/Gen3Hex.Core/NumericExtensions.cs +++ b/src/HexManiac.Core/NumericExtensions.cs @@ -1,6 +1,6 @@ using System; -namespace HavenSoft.Gen3Hex.Core { +namespace HavenSoft.HexManiac.Core { public static class NumericExtensions { public static T LimitToRange(this T value, T lower, T upper) where T : IComparable { if (upper.CompareTo(lower) < 0) throw new ArgumentException($"upper value {upper} is less than lower value {lower}"); diff --git a/src/Gen3Hex.Core/ViewModels/ChangeHistory.cs b/src/HexManiac.Core/ViewModels/ChangeHistory.cs similarity index 99% rename from src/Gen3Hex.Core/ViewModels/ChangeHistory.cs rename to src/HexManiac.Core/ViewModels/ChangeHistory.cs index 6bdaf3da..3aa2ed73 100644 --- a/src/Gen3Hex.Core/ViewModels/ChangeHistory.cs +++ b/src/HexManiac.Core/ViewModels/ChangeHistory.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Windows.Input; -namespace HavenSoft.Gen3Hex.Core.ViewModels { +namespace HavenSoft.HexManiac.Core.ViewModels { /// /// Represents a history of changes that can undo / redo. /// The change can be reperesented by any class with an empty constructor. diff --git a/src/Gen3Hex.Core/ViewModels/ChildViewPort.cs b/src/HexManiac.Core/ViewModels/ChildViewPort.cs similarity index 82% rename from src/Gen3Hex.Core/ViewModels/ChildViewPort.cs rename to src/HexManiac.Core/ViewModels/ChildViewPort.cs index ee516e46..e5a30903 100644 --- a/src/Gen3Hex.Core/ViewModels/ChildViewPort.cs +++ b/src/HexManiac.Core/ViewModels/ChildViewPort.cs @@ -1,6 +1,6 @@ -using HavenSoft.Gen3Hex.Core.Models; +using HavenSoft.HexManiac.Core.Models; -namespace HavenSoft.Gen3Hex.Core.ViewModels { +namespace HavenSoft.HexManiac.Core.ViewModels { /// /// exactly replaces a ViewPort, except that it also has a known parent view /// diff --git a/src/Gen3Hex.Core/ViewModels/DataFormats.cs b/src/HexManiac.Core/ViewModels/DataFormats.cs similarity index 90% rename from src/Gen3Hex.Core/ViewModels/DataFormats.cs rename to src/HexManiac.Core/ViewModels/DataFormats.cs index 757c48d3..46ca3281 100644 --- a/src/Gen3Hex.Core/ViewModels/DataFormats.cs +++ b/src/HexManiac.Core/ViewModels/DataFormats.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; -namespace HavenSoft.Gen3Hex.Core.ViewModels.DataFormats { +namespace HavenSoft.HexManiac.Core.ViewModels.DataFormats { public interface IDataFormat : IEquatable { void Visit(IDataFormatVisitor visitor, byte data); } @@ -19,6 +19,7 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels.DataFormats { void Visit(PCS pcs, byte data); void Visit(EscapedPCS pcs, byte data); void Visit(ErrorPCS pcs, byte data); + void Visit(Ascii ascii, byte data); } /// @@ -154,4 +155,19 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels.DataFormats { public void Visit(IDataFormatVisitor visitor, byte data) => visitor.Visit(this, data); } + + public class Ascii : IDataFormat { + public int Source { get; } + public int Position { get; } + public char ThisCharacter { get; } + + public Ascii(int source, int position, char value) => (Source, Position, ThisCharacter) = (source, position, value); + + public bool Equals(IDataFormat other) { + if (!(other is Ascii ascii)) return false; + return ascii.Source == Source && ascii.Position == Position && ascii.ThisCharacter == ThisCharacter; + } + + public void Visit(IDataFormatVisitor visitor, byte data) => visitor.Visit(this, data); + } } diff --git a/src/Gen3Hex.Core/ViewModels/EditorViewModel.cs b/src/HexManiac.Core/ViewModels/EditorViewModel.cs similarity index 98% rename from src/Gen3Hex.Core/ViewModels/EditorViewModel.cs rename to src/HexManiac.Core/ViewModels/EditorViewModel.cs index 75a4fab4..26f43f62 100644 --- a/src/Gen3Hex.Core/ViewModels/EditorViewModel.cs +++ b/src/HexManiac.Core/ViewModels/EditorViewModel.cs @@ -1,4 +1,4 @@ -using HavenSoft.Gen3Hex.Core.Models; +using HavenSoft.HexManiac.Core.Models; using System; using System.Collections; using System.Collections.Generic; @@ -6,10 +6,11 @@ using System.Collections.Specialized; using System.ComponentModel; using System.Linq; using System.Windows.Input; -using static HavenSoft.Gen3Hex.Core.ICommandExtensions; +using static HavenSoft.HexManiac.Core.ICommandExtensions; -namespace HavenSoft.Gen3Hex.Core.ViewModels { +namespace HavenSoft.HexManiac.Core.ViewModels { public class EditorViewModel : ViewModelCore, IEnumerable, INotifyCollectionChanged { + private const int MaxReasonableResults = 200; // limit for performance reasons private readonly IFileSystem fileSystem; private readonly List tabs; @@ -43,7 +44,6 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels { toggleMatrix = new StubCommand(); private readonly Dictionary, EventHandler> forwardExecuteChangeNotifications; - private (IViewPort tab, int)[] recentFindResults = new (IViewPort, int)[0]; private int currentFindResultIndex; @@ -374,6 +374,11 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels { return; } + if (results.Count > MaxReasonableResults) { + ErrorMessage = $"Found {results.Count} results: please refine your search."; + return; + } + var newTab = new SearchResultsViewPort(search); foreach (var (tab, offset) in results) { newTab.Add(tab.CreateChildView(offset)); diff --git a/src/Gen3Hex.Core/ViewModels/GotoControlViewModel.cs b/src/HexManiac.Core/ViewModels/GotoControlViewModel.cs similarity index 97% rename from src/Gen3Hex.Core/ViewModels/GotoControlViewModel.cs rename to src/HexManiac.Core/ViewModels/GotoControlViewModel.cs index 42f04184..c49a21e2 100644 --- a/src/Gen3Hex.Core/ViewModels/GotoControlViewModel.cs +++ b/src/HexManiac.Core/ViewModels/GotoControlViewModel.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using System.Linq; using System.Windows.Input; -using static HavenSoft.Gen3Hex.Core.ICommandExtensions; +using static HavenSoft.HexManiac.Core.ICommandExtensions; -namespace HavenSoft.Gen3Hex.Core.ViewModels { +namespace HavenSoft.HexManiac.Core.ViewModels { public class GotoControlViewModel : ViewModelCore { private readonly IViewPort viewPort; diff --git a/src/Gen3Hex.Core/ViewModels/HexElement.cs b/src/HexManiac.Core/ViewModels/HexElement.cs similarity index 74% rename from src/Gen3Hex.Core/ViewModels/HexElement.cs rename to src/HexManiac.Core/ViewModels/HexElement.cs index 2f3303ff..23e60287 100644 --- a/src/Gen3Hex.Core/ViewModels/HexElement.cs +++ b/src/HexManiac.Core/ViewModels/HexElement.cs @@ -1,6 +1,6 @@ -using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; -namespace HavenSoft.Gen3Hex.Core.ViewModels { +namespace HavenSoft.HexManiac.Core.ViewModels { public class HexElement { public static readonly HexElement Undefined = new HexElement(0, DataFormats.Undefined.Instance); public byte Value { get; } diff --git a/src/Gen3Hex.Core/ViewModels/IChildViewPort.cs b/src/HexManiac.Core/ViewModels/IChildViewPort.cs similarity index 63% rename from src/Gen3Hex.Core/ViewModels/IChildViewPort.cs rename to src/HexManiac.Core/ViewModels/IChildViewPort.cs index 143bc694..bd52317e 100644 --- a/src/Gen3Hex.Core/ViewModels/IChildViewPort.cs +++ b/src/HexManiac.Core/ViewModels/IChildViewPort.cs @@ -1,4 +1,4 @@ -namespace HavenSoft.Gen3Hex.Core.ViewModels { +namespace HavenSoft.HexManiac.Core.ViewModels { public interface IChildViewPort : IViewPort { IViewPort Parent { get; } } diff --git a/src/Gen3Hex.Core/ViewModels/ITabContent.cs b/src/HexManiac.Core/ViewModels/ITabContent.cs similarity index 95% rename from src/Gen3Hex.Core/ViewModels/ITabContent.cs rename to src/HexManiac.Core/ViewModels/ITabContent.cs index 654cc25e..6d3d671a 100644 --- a/src/Gen3Hex.Core/ViewModels/ITabContent.cs +++ b/src/HexManiac.Core/ViewModels/ITabContent.cs @@ -2,7 +2,7 @@ using System.ComponentModel; using System.Windows.Input; -namespace HavenSoft.Gen3Hex.Core.ViewModels { +namespace HavenSoft.HexManiac.Core.ViewModels { /// /// Each command expects an IFileSystem as its Command Parameter. /// diff --git a/src/Gen3Hex.Core/ViewModels/IViewPort.cs b/src/HexManiac.Core/ViewModels/IViewPort.cs similarity index 89% rename from src/Gen3Hex.Core/ViewModels/IViewPort.cs rename to src/HexManiac.Core/ViewModels/IViewPort.cs index 4b750fe4..a9574363 100644 --- a/src/Gen3Hex.Core/ViewModels/IViewPort.cs +++ b/src/HexManiac.Core/ViewModels/IViewPort.cs @@ -1,11 +1,11 @@ -using HavenSoft.Gen3Hex.Core.Models; -using HavenSoft.Gen3Hex.Core.ViewModels.Tools; +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.ViewModels.Tools; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Windows.Input; -namespace HavenSoft.Gen3Hex.Core.ViewModels { +namespace HavenSoft.HexManiac.Core.ViewModels { public interface IViewPort : ITabContent, INotifyCollectionChanged { string FileName { get; } // Name is dispayed in a tab. FileName lets us know when to call 'ConsiderReload' diff --git a/src/Gen3Hex.Core/ViewModels/ScrollRegion.cs b/src/HexManiac.Core/ViewModels/ScrollRegion.cs similarity index 98% rename from src/Gen3Hex.Core/ViewModels/ScrollRegion.cs rename to src/HexManiac.Core/ViewModels/ScrollRegion.cs index 5f235d7c..ad4dbff5 100644 --- a/src/Gen3Hex.Core/ViewModels/ScrollRegion.cs +++ b/src/HexManiac.Core/ViewModels/ScrollRegion.cs @@ -1,10 +1,10 @@ -using HavenSoft.Gen3Hex.Core.Models; +using HavenSoft.HexManiac.Core.Models; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Windows.Input; -namespace HavenSoft.Gen3Hex.Core.ViewModels { +namespace HavenSoft.HexManiac.Core.ViewModels { public class ScrollRegion : ViewModelCore { public static readonly IReadOnlyDictionary DirectionToDif = new Dictionary { { Direction.Up, new Point( 0,-1) }, diff --git a/src/Gen3Hex.Core/ViewModels/SearchResultsViewPort.cs b/src/HexManiac.Core/ViewModels/SearchResultsViewPort.cs similarity index 98% rename from src/Gen3Hex.Core/ViewModels/SearchResultsViewPort.cs rename to src/HexManiac.Core/ViewModels/SearchResultsViewPort.cs index 960e42b9..92888afe 100644 --- a/src/Gen3Hex.Core/ViewModels/SearchResultsViewPort.cs +++ b/src/HexManiac.Core/ViewModels/SearchResultsViewPort.cs @@ -1,5 +1,5 @@ -using HavenSoft.Gen3Hex.Core.Models; -using HavenSoft.Gen3Hex.Core.ViewModels.Tools; +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.ViewModels.Tools; using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -7,7 +7,7 @@ using System.Collections.Specialized; using System.Linq; using System.Windows.Input; -namespace HavenSoft.Gen3Hex.Core.ViewModels { +namespace HavenSoft.HexManiac.Core.ViewModels { public class SearchResultsViewPort : ViewModelCore, IViewPort { private readonly StubCommand scroll, close; private readonly List children = new List(); diff --git a/src/Gen3Hex.Core/ViewModels/Selection.cs b/src/HexManiac.Core/ViewModels/Selection.cs similarity index 94% rename from src/Gen3Hex.Core/ViewModels/Selection.cs rename to src/HexManiac.Core/ViewModels/Selection.cs index 7cec1042..0bf84a2c 100644 --- a/src/Gen3Hex.Core/ViewModels/Selection.cs +++ b/src/HexManiac.Core/ViewModels/Selection.cs @@ -1,13 +1,13 @@ -using HavenSoft.Gen3Hex.Core.Models; -using HavenSoft.Gen3Hex.Core.Models.Runs; -using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats; +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.Models.Runs; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Windows.Input; -namespace HavenSoft.Gen3Hex.Core.ViewModels { +namespace HavenSoft.HexManiac.Core.ViewModels { public class Selection : ViewModelCore { private readonly IDataModel model; @@ -97,7 +97,11 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels { if (anchor != Pointer.NULL) { GotoAddress(anchor); } else if (int.TryParse(address, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out int result)) { - GotoAddress(result); + if (result > Scroll.DataLength || result < 0) { + OnError?.Invoke(this, $"Address {result:X2} is not within the size of the data."); + } else { + GotoAddress(result); + } } else { OnError?.Invoke(this, $"Unable to goto address '{address}'"); } diff --git a/src/Gen3Hex.Core/ViewModels/Tools/IToolTrayViewModel.cs b/src/HexManiac.Core/ViewModels/Tools/IToolTrayViewModel.cs similarity index 97% rename from src/Gen3Hex.Core/ViewModels/Tools/IToolTrayViewModel.cs rename to src/HexManiac.Core/ViewModels/Tools/IToolTrayViewModel.cs index 17d53253..7a8496e5 100644 --- a/src/Gen3Hex.Core/ViewModels/Tools/IToolTrayViewModel.cs +++ b/src/HexManiac.Core/ViewModels/Tools/IToolTrayViewModel.cs @@ -1,4 +1,4 @@ -using HavenSoft.Gen3Hex.Core.Models; +using HavenSoft.HexManiac.Core.Models; using System; using System.Collections; using System.Collections.Generic; @@ -6,7 +6,7 @@ using System.ComponentModel; using System.Diagnostics; using System.Windows.Input; -namespace HavenSoft.Gen3Hex.Core.ViewModels.Tools { +namespace HavenSoft.HexManiac.Core.ViewModels.Tools { public interface IToolTrayViewModel : IReadOnlyList, INotifyPropertyChanged { int SelectedIndex { get; set; } diff --git a/src/Gen3Hex.Core/ViewModels/Tools/IToolViewModel.cs b/src/HexManiac.Core/ViewModels/Tools/IToolViewModel.cs similarity index 88% rename from src/Gen3Hex.Core/ViewModels/Tools/IToolViewModel.cs rename to src/HexManiac.Core/ViewModels/Tools/IToolViewModel.cs index fbeac238..bc0c197d 100644 --- a/src/Gen3Hex.Core/ViewModels/Tools/IToolViewModel.cs +++ b/src/HexManiac.Core/ViewModels/Tools/IToolViewModel.cs @@ -1,6 +1,6 @@ using System.ComponentModel; -namespace HavenSoft.Gen3Hex.Core.ViewModels.Tools { +namespace HavenSoft.HexManiac.Core.ViewModels.Tools { public interface IToolViewModel : INotifyPropertyChanged { string Name { get; } } diff --git a/src/Gen3Hex.Core/ViewModels/Tools/PCSTool.cs b/src/HexManiac.Core/ViewModels/Tools/PCSTool.cs similarity index 97% rename from src/Gen3Hex.Core/ViewModels/Tools/PCSTool.cs rename to src/HexManiac.Core/ViewModels/Tools/PCSTool.cs index c1ae110b..49c94d38 100644 --- a/src/Gen3Hex.Core/ViewModels/Tools/PCSTool.cs +++ b/src/HexManiac.Core/ViewModels/Tools/PCSTool.cs @@ -1,10 +1,10 @@ -using HavenSoft.Gen3Hex.Core.Models; -using HavenSoft.Gen3Hex.Core.Models.Runs; -using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats; +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.Models.Runs; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; using System; using System.Text; -namespace HavenSoft.Gen3Hex.Core.ViewModels.Tools { +namespace HavenSoft.HexManiac.Core.ViewModels.Tools { public class PCSTool : ViewModelCore, IToolViewModel { private readonly IDataModel model; private readonly Selection selection; diff --git a/src/Gen3Hex.Core/ViewModels/ViewModelCore.cs b/src/HexManiac.Core/ViewModels/ViewModelCore.cs similarity index 97% rename from src/Gen3Hex.Core/ViewModels/ViewModelCore.cs rename to src/HexManiac.Core/ViewModels/ViewModelCore.cs index b5116d17..208bfa24 100644 --- a/src/Gen3Hex.Core/ViewModels/ViewModelCore.cs +++ b/src/HexManiac.Core/ViewModels/ViewModelCore.cs @@ -2,7 +2,7 @@ using System.ComponentModel; using System.Runtime.CompilerServices; -namespace HavenSoft.Gen3Hex.Core.ViewModels { +namespace HavenSoft.HexManiac.Core.ViewModels { public class ViewModelCore : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; diff --git a/src/Gen3Hex.Core/ViewModels/ViewPort.cs b/src/HexManiac.Core/ViewModels/ViewPort.cs similarity index 95% rename from src/Gen3Hex.Core/ViewModels/ViewPort.cs rename to src/HexManiac.Core/ViewModels/ViewPort.cs index 994dc09b..daa99670 100644 --- a/src/Gen3Hex.Core/ViewModels/ViewPort.cs +++ b/src/HexManiac.Core/ViewModels/ViewPort.cs @@ -1,7 +1,7 @@ -using HavenSoft.Gen3Hex.Core.Models; -using HavenSoft.Gen3Hex.Core.Models.Runs; -using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats; -using HavenSoft.Gen3Hex.Core.ViewModels.Tools; +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.Models.Runs; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; +using HavenSoft.HexManiac.Core.ViewModels.Tools; using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -12,13 +12,14 @@ using System.Globalization; using System.IO; using System.Linq; using System.Windows.Input; -using static HavenSoft.Gen3Hex.Core.ICommandExtensions; -using static HavenSoft.Gen3Hex.Core.Models.Runs.ArrayRun; -using static HavenSoft.Gen3Hex.Core.Models.Runs.BaseRun; -using static HavenSoft.Gen3Hex.Core.Models.Runs.PCSRun; -using static HavenSoft.Gen3Hex.Core.Models.Runs.PointerRun; +using static HavenSoft.HexManiac.Core.ICommandExtensions; +using static HavenSoft.HexManiac.Core.Models.Runs.ArrayRun; +using static HavenSoft.HexManiac.Core.Models.Runs.AsciiRun; +using static HavenSoft.HexManiac.Core.Models.Runs.BaseRun; +using static HavenSoft.HexManiac.Core.Models.Runs.PCSRun; +using static HavenSoft.HexManiac.Core.Models.Runs.PointerRun; -namespace HavenSoft.Gen3Hex.Core.ViewModels { +namespace HavenSoft.HexManiac.Core.ViewModels { /// /// A range of visible data that should be displayed. /// @@ -327,6 +328,12 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels { public bool IsSelected(Point point) => selection.IsSelected(point); + public void ClearFormat(Point point) { + var dataIndex = scroll.ViewPointToDataIndex(point); + Model.ClearFormat(history.CurrentChange, dataIndex, 1); + RefreshBackingData(); + } + public void Edit(string input) { exitEditEarly = false; using (Tools.DeferUpdates) { @@ -674,6 +681,10 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels { return AllHexCharacters.Contains(input); } + if (innerFormat is Ascii) { + return true; + } + if (input == PointerStart) { // pointer edits are 4 bytes long if(!TryCoerceSelectionToStartOfPointer(ref point, ref element)) PrepareForMultiSpaceEdit(point, 4); @@ -682,7 +693,7 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels { } else if (underEdit.CurrentText.StartsWith(PointerStart.ToString())) { return char.IsLetterOrDigit(input) || input == PointerEnd; } else if (underEdit.CurrentText.StartsWith(AnchorStart.ToString())) { - return char.IsLetterOrDigit(input) || char.IsWhiteSpace(input) || input == ArrayStart || input == ArrayEnd || input == StringDelimeter; + return char.IsLetterOrDigit(input) || char.IsWhiteSpace(input) || input == ArrayStart || input == ArrayEnd || input == StringDelimeter || input == StreamDelimeter; } else if (underEdit.OriginalFormat is Anchor anchorFormat && anchorFormat.OriginalFormat is PCS) { if (input == StringDelimeter) return true; // if this is the start of a string (as noted by the anchor), crop off the leading " before trying to convert to a byte @@ -764,10 +775,13 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels { return true; } - PCS stringFormat = null; - if (underEdit.OriginalFormat is Anchor anchorFormat) stringFormat = anchorFormat.OriginalFormat as PCS; - stringFormat = stringFormat ?? underEdit.OriginalFormat as PCS; - if (stringFormat != null) { + var originalFormat = underEdit.OriginalFormat; + if (originalFormat is Anchor) originalFormat = ((Anchor)originalFormat).OriginalFormat; + if (originalFormat is Ascii) { + CompleteAsciiEdit(point, underEdit.CurrentText); + return true; + } + if (originalFormat is PCS stringFormat) { var currentText = underEdit.CurrentText; if (currentText.StartsWith(StringDelimeter.ToString())) currentText = currentText.Substring(1); if (stringFormat.Position != 0 && underEdit.CurrentText == StringDelimeter.ToString()) { @@ -790,6 +804,17 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels { return true; } + private void CompleteAsciiEdit(Point point, string currentText) { + var memoryLocation = scroll.ViewPointToDataIndex(point); + var editFormat = (UnderEdit)currentView[point.X, point.Y].Format; + var asciiFormat = (Ascii)editFormat.OriginalFormat; + var content = (byte)currentText[0]; + + history.CurrentChange.ChangeData(Model, memoryLocation, content); + currentView[point.X, point.Y] = new HexElement(content, new Ascii(asciiFormat.Source, asciiFormat.Position, currentText[0])); + SilentScroll(memoryLocation + 1); + } + private void CompleteArrayExtension(ArrayRun arrayRun) { var newRun = (ArrayRun)Model.RelocateForExpansion(history.CurrentChange, arrayRun, arrayRun.Length + arrayRun.ElementLength); if (newRun != arrayRun) { @@ -1079,6 +1104,8 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels { public void Visit(EscapedPCS pcs, byte data) => Visit((None)null, data); public void Visit(ErrorPCS pcs, byte data) => Visit((None)null, data); + + public void Visit(Ascii ascii, byte data) => Result = ((char)data).ToString(); } /// @@ -1115,6 +1142,8 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels { public void Visit(EscapedPCS pcs, byte data) => currentChange.ChangeData(buffer, index, 0xFF); public void Visit(ErrorPCS pcs, byte data) => currentChange.ChangeData(buffer, index, 0xFF); + + public void Visit(Ascii ascii, byte data) => currentChange.ChangeData(buffer, index, 0xFF); } } } diff --git a/src/Gen3Hex.Core/packages.config b/src/HexManiac.Core/packages.config similarity index 100% rename from src/Gen3Hex.Core/packages.config rename to src/HexManiac.Core/packages.config diff --git a/src/Gen3Hex.Tests/ArrayRunTests.cs b/src/HexManiac.Tests/ArrayRunTests.cs similarity index 98% rename from src/Gen3Hex.Tests/ArrayRunTests.cs rename to src/HexManiac.Tests/ArrayRunTests.cs index a283e9a6..1045112d 100644 --- a/src/Gen3Hex.Tests/ArrayRunTests.cs +++ b/src/HexManiac.Tests/ArrayRunTests.cs @@ -1,15 +1,15 @@ -using HavenSoft.Gen3Hex.Core; -using HavenSoft.Gen3Hex.Core.Models; -using HavenSoft.Gen3Hex.Core.Models.Runs; -using HavenSoft.Gen3Hex.Core.ViewModels; -using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats; +using HavenSoft.HexManiac.Core; +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.Models.Runs; +using HavenSoft.HexManiac.Core.ViewModels; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; using System; using System.Collections.Generic; using System.Linq; using System.Text; using Xunit; -namespace HavenSoft.Gen3Hex.Tests { +namespace HavenSoft.HexManiac.Tests { public class ArrayRunTests { [Fact] public void CanParseStringArrayRun() { diff --git a/src/HexManiac.Tests/AsciiRunTests.cs b/src/HexManiac.Tests/AsciiRunTests.cs new file mode 100644 index 00000000..b70cd3bd --- /dev/null +++ b/src/HexManiac.Tests/AsciiRunTests.cs @@ -0,0 +1,46 @@ +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.Models.Runs; +using HavenSoft.HexManiac.Core.ViewModels; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; +using Xunit; + +namespace HavenSoft.HexManiac.Tests { + public class AsciiRunTests { + [Fact] + public void CanCreateAsciiRun() { + var buffer = new byte[0x200]; + var model = new PokemonModel(buffer); + model[0x10] = (byte)'a'; + model[0x11] = (byte)'b'; + model[0x12] = (byte)'c'; + model[0x13] = (byte)'d'; + + var viewPort = new ViewPort(new LoadedFile("file.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + viewPort.SelectionStart = new Point(0, 1); + viewPort.Edit("^data`asc`4 "); + + var format = (Ascii)viewPort[1, 1].Format; + Assert.Equal('b', format.ThisCharacter); + } + + [Fact] + public void CanEditAsciiRun() { + var buffer = new byte[0x200]; + var model = new PokemonModel(buffer); + model[0x10] = (byte)'a'; + model[0x11] = (byte)'b'; + model[0x12] = (byte)'c'; + model[0x13] = (byte)'d'; + + model.ObserveRunWritten(new ModelDelta(), new AsciiRun(0x10, 4)); + + var viewPort = new ViewPort(new LoadedFile("file.txt", buffer), model) { Width = 0x10, Height = 0x10 }; + viewPort.SelectionStart = new Point(1, 1); + viewPort.Edit("3"); + + var format = (Ascii)viewPort[1, 1].Format; + Assert.Equal('3', format.ThisCharacter); + Assert.Equal(new Point(2, 1), viewPort.SelectionStart); + } + } +} diff --git a/src/Gen3Hex.Tests/ChangeHistoryTests.cs b/src/HexManiac.Tests/ChangeHistoryTests.cs similarity index 97% rename from src/Gen3Hex.Tests/ChangeHistoryTests.cs rename to src/HexManiac.Tests/ChangeHistoryTests.cs index 3e9fb4a4..f214e7d5 100644 --- a/src/Gen3Hex.Tests/ChangeHistoryTests.cs +++ b/src/HexManiac.Tests/ChangeHistoryTests.cs @@ -1,13 +1,13 @@ -using HavenSoft.Gen3Hex.Core; -using HavenSoft.Gen3Hex.Core.Models; -using HavenSoft.Gen3Hex.Core.ViewModels; -using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats; +using HavenSoft.HexManiac.Core; +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.ViewModels; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; using System; using System.Collections.Generic; using System.Linq; using Xunit; -namespace HavenSoft.Gen3Hex.Tests { +namespace HavenSoft.HexManiac.Tests { public class ChangeHistoryTests { private readonly ChangeHistory> history; diff --git a/src/Gen3Hex.Tests/FindTests.cs b/src/HexManiac.Tests/FindTests.cs similarity index 98% rename from src/Gen3Hex.Tests/FindTests.cs rename to src/HexManiac.Tests/FindTests.cs index ed2336f4..f289c541 100644 --- a/src/Gen3Hex.Tests/FindTests.cs +++ b/src/HexManiac.Tests/FindTests.cs @@ -1,11 +1,11 @@ -using HavenSoft.Gen3Hex.Core.Models; -using HavenSoft.Gen3Hex.Core.ViewModels; +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.ViewModels; using System.Collections.ObjectModel; using System.Linq; using System.Windows.Input; using Xunit; -namespace HavenSoft.Gen3Hex.Tests { +namespace HavenSoft.HexManiac.Tests { public class FindTests { [Fact] public void FindCanFindSingle() { diff --git a/src/Gen3Hex.Tests/GeneralAppTests.cs b/src/HexManiac.Tests/GeneralAppTests.cs similarity index 98% rename from src/Gen3Hex.Tests/GeneralAppTests.cs rename to src/HexManiac.Tests/GeneralAppTests.cs index 1704d5cd..c0ece589 100644 --- a/src/Gen3Hex.Tests/GeneralAppTests.cs +++ b/src/HexManiac.Tests/GeneralAppTests.cs @@ -1,11 +1,11 @@ -using HavenSoft.Gen3Hex.Core; -using HavenSoft.Gen3Hex.Core.Models; -using HavenSoft.Gen3Hex.Core.ViewModels; +using HavenSoft.HexManiac.Core; +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.ViewModels; using System; using System.Windows.Input; using Xunit; -namespace HavenSoft.Gen3Hex.Tests { +namespace HavenSoft.HexManiac.Tests { public class GeneralAppTests { private readonly EditorViewModel editor; private readonly StubFileSystem fileSystem; diff --git a/src/Gen3Hex.Tests/Gen3Hex.Tests.csproj b/src/HexManiac.Tests/HexManiac.Tests.csproj similarity index 93% rename from src/Gen3Hex.Tests/Gen3Hex.Tests.csproj rename to src/HexManiac.Tests/HexManiac.Tests.csproj index 5dfb03e6..8d3e6223 100644 --- a/src/Gen3Hex.Tests/Gen3Hex.Tests.csproj +++ b/src/HexManiac.Tests/HexManiac.Tests.csproj @@ -8,8 +8,8 @@ AnyCPU {B6A52732-E0F8-466D-8E29-664C797A21FA} Library - HavenSoft.Gen3Hex.Tests - Gen3Hex.Tests + HavenSoft.HexManiac.Tests + HexManiac.Tests v4.7.2 512 {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} @@ -55,11 +55,12 @@ - + StubDataModel.cs + @@ -82,9 +83,9 @@ - + {b7b9d932-4271-493d-aadd-6cf147c91373} - Gen3Hex.Core + HexManiac.Core @@ -102,7 +103,7 @@ if not exist $(SolutionDir)artifacts\$(AssemblyName)\codegen mkdir $(SolutionDir)artifacts\$(AssemblyName)\codegen -$(SolutionDir)packages\HavenSoft.AutoImplement.1.1.1\AutoImplement $(SolutionDir)artifacts\Gen3Hex.Core\bin\$(ConfigurationName)\Gen3Hex.Core.dll ITabContent IFileSystem IViewPort IDataModel +$(SolutionDir)packages\HavenSoft.AutoImplement.1.1.1\AutoImplement $(SolutionDir)artifacts\HexManiac.Core\bin\$(ConfigurationName)\HexManiac.Core.dll ITabContent IFileSystem IViewPort IDataModel move /Y StubTabContent.cs $(SolutionDir)artifacts\$(AssemblyName)\codegen move /Y StubFileSystem.cs $(SolutionDir)artifacts\$(AssemblyName)\codegen move /Y StubViewPort.cs $(SolutionDir)artifacts\$(AssemblyName)\codegen diff --git a/src/Gen3Hex.Tests/NavigationTests.cs b/src/HexManiac.Tests/NavigationTests.cs similarity index 98% rename from src/Gen3Hex.Tests/NavigationTests.cs rename to src/HexManiac.Tests/NavigationTests.cs index 89a5b427..bf0820bb 100644 --- a/src/Gen3Hex.Tests/NavigationTests.cs +++ b/src/HexManiac.Tests/NavigationTests.cs @@ -1,11 +1,11 @@ -using HavenSoft.Gen3Hex.Core; -using HavenSoft.Gen3Hex.Core.Models; -using HavenSoft.Gen3Hex.Core.ViewModels; +using HavenSoft.HexManiac.Core; +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.ViewModels; using System.Collections.Generic; using System.Windows.Input; using Xunit; -namespace HavenSoft.Gen3Hex.Tests { +namespace HavenSoft.HexManiac.Tests { public class NavigationTests { [Fact] public void AddressesAreCorrect() { diff --git a/src/Gen3Hex.Tests/PointerModelTests.cs b/src/HexManiac.Tests/PointerModelTests.cs similarity index 93% rename from src/Gen3Hex.Tests/PointerModelTests.cs rename to src/HexManiac.Tests/PointerModelTests.cs index c4520076..2fb12737 100644 --- a/src/Gen3Hex.Tests/PointerModelTests.cs +++ b/src/HexManiac.Tests/PointerModelTests.cs @@ -1,14 +1,14 @@ -using HavenSoft.Gen3Hex.Core; -using HavenSoft.Gen3Hex.Core.Models; -using HavenSoft.Gen3Hex.Core.Models.Runs; -using HavenSoft.Gen3Hex.Core.ViewModels; -using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats; +using HavenSoft.HexManiac.Core; +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.Models.Runs; +using HavenSoft.HexManiac.Core.ViewModels; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; using System; using System.Collections.Generic; using System.Linq; using Xunit; -namespace HavenSoft.Gen3Hex.Tests { +namespace HavenSoft.HexManiac.Tests { public class PointerModelTests { [Fact] public void PointerModelFindsNoPointersInRandomData() { @@ -695,5 +695,34 @@ namespace HavenSoft.Gen3Hex.Tests { } } } + + [Fact] + public void AddingAnchorShouldSearchForPointersToThatLocation() { + var data = new byte[0x200]; + var model = new PokemonModel(data); + var change = new ModelDelta(); + model.WritePointer(change, 0x23, 0x050); // a pointer that isn't 4-byte aligned, pointing to data that is + model.WritePointer(change, 0x10, 0x087); // a pointer that is 4-byte aligned, but pointing to something that isn't + model.WritePointer(change, 2, 0xA2); // a pointer that isn't 4-byte aligned, pointing to something not 4-byte aligned + var viewPort = new ViewPort(new LoadedFile("test.txt", data), model) { Width = 0x10, Height = 0x10 }; + + // got to 50 and write an anchor + viewPort.SelectionStart = new Point(0x0, 0x5); + viewPort.Edit("^test1 "); + Assert.IsType(viewPort[0x3, 0x2].Format); + Assert.Single(((Anchor)viewPort[0x0, 0x5].Format).Sources); + + // go to 87 and write an anchor + viewPort.SelectionStart = new Point(0x7, 0x8); + viewPort.Edit("^test2 "); + Assert.IsType(viewPort[0x0, 0x1].Format); + Assert.Single(((Anchor)viewPort[0x7, 0x8].Format).Sources); + + // go to A2 and write an anchor + viewPort.SelectionStart = new Point(0x2, 0xA); + viewPort.Edit("^test3 "); + Assert.IsType(viewPort[0x2, 0x0].Format); + Assert.Single(((Anchor)viewPort[0x2, 0xA].Format).Sources); + } } } diff --git a/src/Gen3Hex.Tests/StringModelTests.cs b/src/HexManiac.Tests/StringModelTests.cs similarity index 98% rename from src/Gen3Hex.Tests/StringModelTests.cs rename to src/HexManiac.Tests/StringModelTests.cs index 4d38d70d..8db5f276 100644 --- a/src/Gen3Hex.Tests/StringModelTests.cs +++ b/src/HexManiac.Tests/StringModelTests.cs @@ -1,14 +1,14 @@ -using HavenSoft.Gen3Hex.Core; -using HavenSoft.Gen3Hex.Core.Models; -using HavenSoft.Gen3Hex.Core.Models.Runs; -using HavenSoft.Gen3Hex.Core.ViewModels; -using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats; +using HavenSoft.HexManiac.Core; +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.Models.Runs; +using HavenSoft.HexManiac.Core.ViewModels; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; using System; using System.Collections.Generic; using System.Linq; using Xunit; -namespace HavenSoft.Gen3Hex.Tests { +namespace HavenSoft.HexManiac.Tests { public class StringModelTests { [Fact] public void CanRecognizeString() { diff --git a/src/Gen3Hex.Tests/ToolTests.cs b/src/HexManiac.Tests/ToolTests.cs similarity index 95% rename from src/Gen3Hex.Tests/ToolTests.cs rename to src/HexManiac.Tests/ToolTests.cs index 8e4f9a6d..7b9c3ab1 100644 --- a/src/Gen3Hex.Tests/ToolTests.cs +++ b/src/HexManiac.Tests/ToolTests.cs @@ -1,15 +1,15 @@ -using HavenSoft.Gen3Hex.Core; -using HavenSoft.Gen3Hex.Core.Models; -using HavenSoft.Gen3Hex.Core.Models.Runs; -using HavenSoft.Gen3Hex.Core.ViewModels; -using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats; -using HavenSoft.Gen3Hex.Core.ViewModels.Tools; +using HavenSoft.HexManiac.Core; +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.Models.Runs; +using HavenSoft.HexManiac.Core.ViewModels; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; +using HavenSoft.HexManiac.Core.ViewModels.Tools; using System.Collections.Generic; using System.Globalization; using System.Linq; using Xunit; -namespace HavenSoft.Gen3Hex.Tests { +namespace HavenSoft.HexManiac.Tests { public class ToolTests { [Fact] public void ViewPortHasTools() { diff --git a/src/Gen3Hex.Tests/ViewPortCursorTests.cs b/src/HexManiac.Tests/ViewPortCursorTests.cs similarity index 98% rename from src/Gen3Hex.Tests/ViewPortCursorTests.cs rename to src/HexManiac.Tests/ViewPortCursorTests.cs index 2cb1a088..f9c9734b 100644 --- a/src/Gen3Hex.Tests/ViewPortCursorTests.cs +++ b/src/HexManiac.Tests/ViewPortCursorTests.cs @@ -1,8 +1,8 @@ -using HavenSoft.Gen3Hex.Core.Models; -using HavenSoft.Gen3Hex.Core.ViewModels; +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.ViewModels; using Xunit; -namespace HavenSoft.Gen3Hex.Tests { +namespace HavenSoft.HexManiac.Tests { public class ViewPortCursorTests { [Fact] public void CursorCanMoveAllFourDirections() { diff --git a/src/Gen3Hex.Tests/ViewPortEditTests.cs b/src/HexManiac.Tests/ViewPortEditTests.cs similarity index 98% rename from src/Gen3Hex.Tests/ViewPortEditTests.cs rename to src/HexManiac.Tests/ViewPortEditTests.cs index 5218287e..9c837c8c 100644 --- a/src/Gen3Hex.Tests/ViewPortEditTests.cs +++ b/src/HexManiac.Tests/ViewPortEditTests.cs @@ -1,12 +1,12 @@ -using HavenSoft.Gen3Hex.Core; -using HavenSoft.Gen3Hex.Core.Models; -using HavenSoft.Gen3Hex.Core.ViewModels; -using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats; +using HavenSoft.HexManiac.Core; +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.ViewModels; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; using System; using System.Linq; using Xunit; -namespace HavenSoft.Gen3Hex.Tests { +namespace HavenSoft.HexManiac.Tests { public class ViewPortEditTests { [Fact] public void CanEditData() { diff --git a/src/Gen3Hex.Tests/ViewPortSaveTests.cs b/src/HexManiac.Tests/ViewPortSaveTests.cs similarity index 98% rename from src/Gen3Hex.Tests/ViewPortSaveTests.cs rename to src/HexManiac.Tests/ViewPortSaveTests.cs index 1dd469de..827072c3 100644 --- a/src/Gen3Hex.Tests/ViewPortSaveTests.cs +++ b/src/HexManiac.Tests/ViewPortSaveTests.cs @@ -1,13 +1,13 @@ -using HavenSoft.Gen3Hex.Core; -using HavenSoft.Gen3Hex.Core.Models; -using HavenSoft.Gen3Hex.Core.ViewModels; -using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats; +using HavenSoft.HexManiac.Core; +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.ViewModels; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; using System.Collections.Generic; using System.IO; using System.Linq; using Xunit; -namespace HavenSoft.Gen3Hex.Tests { +namespace HavenSoft.HexManiac.Tests { public class ViewPortSaveTests { private readonly StubFileSystem fileSystem; diff --git a/src/Gen3Hex.Tests/ViewPortScrollTests.cs b/src/HexManiac.Tests/ViewPortScrollTests.cs similarity index 98% rename from src/Gen3Hex.Tests/ViewPortScrollTests.cs rename to src/HexManiac.Tests/ViewPortScrollTests.cs index 42a4f938..b8b6f05b 100644 --- a/src/Gen3Hex.Tests/ViewPortScrollTests.cs +++ b/src/HexManiac.Tests/ViewPortScrollTests.cs @@ -1,11 +1,11 @@ -using HavenSoft.Gen3Hex.Core.Models; -using HavenSoft.Gen3Hex.Core.ViewModels; +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.ViewModels; using System.Collections.Generic; using Xunit; [assembly: System.Reflection.AssemblyTitle("HexTests")] -namespace HavenSoft.Gen3Hex.Tests { +namespace HavenSoft.HexManiac.Tests { public class ViewPortTests { [Fact] public void ViewPortNotifiesOnSizeChange() { diff --git a/src/Gen3Hex.Tests/packages.config b/src/HexManiac.Tests/packages.config similarity index 100% rename from src/Gen3Hex.Tests/packages.config rename to src/HexManiac.Tests/packages.config diff --git a/src/Gen3Hex.WPF/Controls/HexContent.cs b/src/HexManiac.WPF/Controls/HexContent.cs similarity index 95% rename from src/Gen3Hex.WPF/Controls/HexContent.cs rename to src/HexManiac.WPF/Controls/HexContent.cs index 3a3ece4e..31075e2f 100644 --- a/src/Gen3Hex.WPF/Controls/HexContent.cs +++ b/src/HexManiac.WPF/Controls/HexContent.cs @@ -1,8 +1,8 @@ -using HavenSoft.Gen3Hex.Core; -using HavenSoft.Gen3Hex.Core.Models; -using HavenSoft.Gen3Hex.Core.ViewModels; -using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats; -using HavenSoft.Gen3Hex.WPF.Implementations; +using HavenSoft.HexManiac.Core; +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.ViewModels; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; +using HavenSoft.HexManiac.WPF.Implementations; using System; using System.Collections.Generic; using System.Collections.Specialized; @@ -14,10 +14,10 @@ using System.Windows.Controls.Primitives; using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; -using ModelPoint = HavenSoft.Gen3Hex.Core.Models.Point; +using ModelPoint = HavenSoft.HexManiac.Core.Models.Point; using ScreenPoint = System.Windows.Point; -namespace HavenSoft.Gen3Hex.WPF.Controls { +namespace HavenSoft.HexManiac.WPF.Controls { public class HexContent : FrameworkElement { public const double CellWidth = 30, CellHeight = 20; @@ -202,6 +202,7 @@ namespace HavenSoft.Gen3Hex.WPF.Controls { } if (format is PCS pcs) children.AddRange(GetStringChildren(p)); if (format is Pointer pointer) children.AddRange(GetPointerChildren(p)); + if (!(format is None || format is Undefined)) children.AddRange(GetClearFormattingChildren(p)); } else { children.AddRange(GetSearchChildren(p)); } @@ -354,6 +355,15 @@ namespace HavenSoft.Gen3Hex.WPF.Controls { yield return CreateFollowLinkButton("Open in main tab", p); } + private IEnumerable GetClearFormattingChildren(ModelPoint p) { + yield return new Button { + Content = new TextBlock { Text = "Clear Format" }, + }.SetEvent(ButtonBase.ClickEvent, (sender, e) => { + ((ViewPort)ViewPort).ClearFormat(p); + recentMenu.IsOpen = false; + }); + } + private Button CreateFollowLinkButton(string message, ModelPoint p) { return new Button { Content = new StackPanel { diff --git a/src/Gen3Hex.WPF/Controls/IntegerToBooleanViaMatchConverter.cs b/src/HexManiac.WPF/Controls/IntegerToBooleanViaMatchConverter.cs similarity index 93% rename from src/Gen3Hex.WPF/Controls/IntegerToBooleanViaMatchConverter.cs rename to src/HexManiac.WPF/Controls/IntegerToBooleanViaMatchConverter.cs index 881cdc4f..3be2ce12 100644 --- a/src/Gen3Hex.WPF/Controls/IntegerToBooleanViaMatchConverter.cs +++ b/src/HexManiac.WPF/Controls/IntegerToBooleanViaMatchConverter.cs @@ -2,7 +2,7 @@ using System.Globalization; using System.Windows.Data; -namespace HavenSoft.Gen3Hex.WPF.Controls { +namespace HavenSoft.HexManiac.WPF.Controls { public class IntegerToBooleanViaMatchConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var a = value as int?; diff --git a/src/Gen3Hex.WPF/Controls/IntegerToHexConverter.cs b/src/HexManiac.WPF/Controls/IntegerToHexConverter.cs similarity index 93% rename from src/Gen3Hex.WPF/Controls/IntegerToHexConverter.cs rename to src/HexManiac.WPF/Controls/IntegerToHexConverter.cs index deb411a0..dc22cc74 100644 --- a/src/Gen3Hex.WPF/Controls/IntegerToHexConverter.cs +++ b/src/HexManiac.WPF/Controls/IntegerToHexConverter.cs @@ -2,7 +2,7 @@ using System.Globalization; using System.Windows.Data; -namespace HavenSoft.Gen3Hex.WPF.Controls { +namespace HavenSoft.HexManiac.WPF.Controls { public class IntegerToHexConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is int number) return number.ToString("X6"); diff --git a/src/HexManiac.WPF/Controls/StartScreen.xaml b/src/HexManiac.WPF/Controls/StartScreen.xaml new file mode 100644 index 00000000..d94f9f8b --- /dev/null +++ b/src/HexManiac.WPF/Controls/StartScreen.xaml @@ -0,0 +1,51 @@ + + + + + + + Drag-n-Drop to open a file. + + + + + + + + + + <pointer> + ^Anchor + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/HexManiac.WPF/Controls/StartScreen.xaml.cs b/src/HexManiac.WPF/Controls/StartScreen.xaml.cs new file mode 100644 index 00000000..88ba3465 --- /dev/null +++ b/src/HexManiac.WPF/Controls/StartScreen.xaml.cs @@ -0,0 +1,13 @@ +using System.Diagnostics; +using System.Windows.Input; + +namespace HavenSoft.HexManiac.WPF.Controls { + public partial class StartScreen { + public StartScreen() => InitializeComponent(); + + private void PointerHelp(object sender, MouseButtonEventArgs e) { + Process.Start(new ProcessStartInfo("https://github.com/haven1433/HexManiacAdvance/wiki/Pointers-and-Anchors")); + e.Handled = true; + } + } +} diff --git a/src/Gen3Hex.WPF/Gen3Hex.WPF.csproj b/src/HexManiac.WPF/HexManiac.WPF.csproj similarity index 86% rename from src/Gen3Hex.WPF/Gen3Hex.WPF.csproj rename to src/HexManiac.WPF/HexManiac.WPF.csproj index 630b17b3..9fbc118f 100644 --- a/src/Gen3Hex.WPF/Gen3Hex.WPF.csproj +++ b/src/HexManiac.WPF/HexManiac.WPF.csproj @@ -6,8 +6,8 @@ AnyCPU {386DC8E2-BABC-475C-94B6-37B3986F5F4C} WinExe - HavenSoft.Gen3Hex.WPF - Gen3Hex + HavenSoft.HexManiac.WPF + HexManiacAdvance v4.7.2 512 {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} @@ -32,7 +32,7 @@ TRACE - Resources\Snorlax.ico + Resources\AppIcon.ico @@ -54,6 +54,10 @@ MSBuild:Compile Designer + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -68,6 +72,9 @@ + + StartScreen.xaml + AboutWindow.xaml @@ -95,14 +102,16 @@ - + {b7b9d932-4271-493d-aadd-6cf147c91373} - Gen3Hex.Core + HexManiac.Core - - + + + + \ No newline at end of file diff --git a/src/Gen3Hex.WPF/Implementations/FormatDrawer.cs b/src/HexManiac.WPF/Implementations/FormatDrawer.cs similarity index 89% rename from src/Gen3Hex.WPF/Implementations/FormatDrawer.cs rename to src/HexManiac.WPF/Implementations/FormatDrawer.cs index 10636818..be113c2a 100644 --- a/src/Gen3Hex.WPF/Implementations/FormatDrawer.cs +++ b/src/HexManiac.WPF/Implementations/FormatDrawer.cs @@ -1,12 +1,12 @@ -using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats; -using HavenSoft.Gen3Hex.WPF.Controls; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; +using HavenSoft.HexManiac.WPF.Controls; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Windows; using System.Windows.Media; -namespace HavenSoft.Gen3Hex.WPF.Implementations { +namespace HavenSoft.HexManiac.WPF.Implementations { public class FormatDrawer : IDataFormatVisitor { public static int FontSize = 16; @@ -21,7 +21,7 @@ namespace HavenSoft.Gen3Hex.WPF.Implementations { public bool MouseIsOverCurrentFormat { get; set; } - public HavenSoft.Gen3Hex.Core.Models.Point Position { get; set; } + public HavenSoft.HexManiac.Core.Models.Point Position { get; set; } public FormatDrawer(DrawingContext drawingContext, int width, int height) => (context, modelWidth, modelHeight) = (drawingContext, width, height); @@ -77,7 +77,7 @@ namespace HavenSoft.Gen3Hex.WPF.Implementations { brush, 1.0); - if (dataFormat.Position < Position.X || Position.X - dataFormat.Position > modelWidth - 4) { + if (dataFormat.Position > Position.X || Position.X - dataFormat.Position > modelWidth - 4) { context.PushClip(rectangleGeometry); context.DrawText(text, new Point(CellTextOffset.X + xOffset, CellTextOffset.Y)); context.Pop(); @@ -131,6 +131,20 @@ namespace HavenSoft.Gen3Hex.WPF.Implementations { context.DrawText(text, CellTextOffset); } + public void Visit(Ascii ascii, byte data) { + var typeface = new Typeface("Consolas"); + var text = new FormattedText( + ascii.ThisCharacter.ToString(), + CultureInfo.CurrentCulture, + FlowDirection.LeftToRight, + typeface, + FontSize, + Solarized.Brushes.Violet, + 1.0); + + context.DrawText(text, CellTextOffset); + } + private void Underline(Brush brush, bool isStart, bool isEnd) { int startPoint = isStart ? 5 : 0; int endPoint = (int)HexContent.CellWidth - (isEnd ? 5 : 0); diff --git a/src/Gen3Hex.WPF/Implementations/WindowsFileSystem.cs b/src/HexManiac.WPF/Implementations/WindowsFileSystem.cs similarity index 97% rename from src/Gen3Hex.WPF/Implementations/WindowsFileSystem.cs rename to src/HexManiac.WPF/Implementations/WindowsFileSystem.cs index 6e4a4718..3e965298 100644 --- a/src/Gen3Hex.WPF/Implementations/WindowsFileSystem.cs +++ b/src/HexManiac.WPF/Implementations/WindowsFileSystem.cs @@ -1,4 +1,4 @@ -using HavenSoft.Gen3Hex.Core.Models; +using HavenSoft.HexManiac.Core.Models; using Microsoft.Win32; using System; using System.Collections.Generic; @@ -7,7 +7,7 @@ using System.Linq; using System.Windows; using System.Windows.Threading; -namespace HavenSoft.Gen3Hex.WPF.Implementations { +namespace HavenSoft.HexManiac.WPF.Implementations { public class WindowsFileSystem : IFileSystem { private readonly Dictionary> watchers = new Dictionary>(); private readonly Dictionary>> listeners = new Dictionary>>(); diff --git a/src/HexManiac.WPF/Resources/AppIcon.ico b/src/HexManiac.WPF/Resources/AppIcon.ico new file mode 100644 index 00000000..152a4a78 Binary files /dev/null and b/src/HexManiac.WPF/Resources/AppIcon.ico differ diff --git a/src/HexManiac.WPF/Resources/AppImage.png b/src/HexManiac.WPF/Resources/AppImage.png new file mode 100644 index 00000000..9a77d2e5 Binary files /dev/null and b/src/HexManiac.WPF/Resources/AppImage.png differ diff --git a/src/Gen3Hex.WPF/Resources/Icons.xaml b/src/HexManiac.WPF/Resources/Icons.xaml similarity index 74% rename from src/Gen3Hex.WPF/Resources/Icons.xaml rename to src/HexManiac.WPF/Resources/Icons.xaml index 4609077b..924c341d 100644 --- a/src/Gen3Hex.WPF/Resources/Icons.xaml +++ b/src/HexManiac.WPF/Resources/Icons.xaml @@ -4,14 +4,14 @@ This ItemsControl is meant to be used like a resource. Instead, access these icons using IconExtensions. --> - + d:DesignHeight="360" d:DesignWidth="360"> @@ -163,5 +163,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Gen3Hex.WPF/Resources/Icons.xaml.cs b/src/HexManiac.WPF/Resources/Icons.xaml.cs similarity index 61% rename from src/Gen3Hex.WPF/Resources/Icons.xaml.cs rename to src/HexManiac.WPF/Resources/Icons.xaml.cs index 808da7c3..a8084d7e 100644 --- a/src/Gen3Hex.WPF/Resources/Icons.xaml.cs +++ b/src/HexManiac.WPF/Resources/Icons.xaml.cs @@ -1,4 +1,4 @@ -namespace HavenSoft.Gen3Hex.WPF.Resources { +namespace HavenSoft.HexManiac.WPF.Resources { partial class Icons { public Icons() => InitializeComponent(); } diff --git a/src/Gen3Hex.WPF/Resources/MarkupExtensions.cs b/src/HexManiac.WPF/Resources/MarkupExtensions.cs similarity index 62% rename from src/Gen3Hex.WPF/Resources/MarkupExtensions.cs rename to src/HexManiac.WPF/Resources/MarkupExtensions.cs index c8761fef..fab0b6eb 100644 --- a/src/Gen3Hex.WPF/Resources/MarkupExtensions.cs +++ b/src/HexManiac.WPF/Resources/MarkupExtensions.cs @@ -1,16 +1,17 @@ using System; +using System.Globalization; using System.Windows; using System.Windows.Markup; using System.Windows.Media; -namespace HavenSoft.Gen3Hex.WPF.Resources { +namespace HavenSoft.HexManiac.WPF.Resources { /// /// {hs:RotateTransform 60, 0, 0} /// public class RotateTransformExtension : MarkupExtension { - readonly double Angle; - readonly double CenterX; - readonly double CenterY; + public double Angle { get; } + public double CenterX { get; } + public double CenterY { get; } public RotateTransformExtension(double angle, double centerX, double centerY) { Angle = angle; @@ -27,7 +28,7 @@ namespace HavenSoft.Gen3Hex.WPF.Resources { /// {hs:Geometry 'M0,0 L0,1 1,1 1,0 Z'} /// public class GeometryExtension : MarkupExtension { - readonly string Figures; + public string Figures { get; } public GeometryExtension(string figures) { Figures = figures; } @@ -36,6 +37,18 @@ namespace HavenSoft.Gen3Hex.WPF.Resources { } } + public class TextGeometryExtension : MarkupExtension { + public string Text { get; set; } + public Point Location { get; set; } + public int Size { get; set; } + public TextGeometryExtension() { } + public TextGeometryExtension(string text, int x, int y, int size) => (Text, Location, Size) = (text, new Point(x, y), size); + public override object ProvideValue(IServiceProvider serviceProvider) { + var formattedText = new FormattedText(Text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface("Calibri"), Size, Brushes.Black, 1); + return formattedText.BuildGeometry(Location); + } + } + /// /// Icons are taken from Icons.xaml /// Requires that there is an Icons instance stored at "Icons" in the app resources. @@ -45,7 +58,7 @@ namespace HavenSoft.Gen3Hex.WPF.Resources { /// {hs:Icons Save} /// public class IconExtension : MarkupExtension { - readonly string Name; + public string Name { get; } public IconExtension(string name) { Name = name; } diff --git a/src/Gen3Hex.WPF/Resources/Solarized.cs b/src/HexManiac.WPF/Resources/Solarized.cs similarity index 100% rename from src/Gen3Hex.WPF/Resources/Solarized.cs rename to src/HexManiac.WPF/Resources/Solarized.cs diff --git a/src/Gen3Hex.WPF/Windows/AboutWindow.xaml b/src/HexManiac.WPF/Windows/AboutWindow.xaml similarity index 70% rename from src/Gen3Hex.WPF/Windows/AboutWindow.xaml rename to src/HexManiac.WPF/Windows/AboutWindow.xaml index c141a130..007a2be6 100644 --- a/src/Gen3Hex.WPF/Windows/AboutWindow.xaml +++ b/src/HexManiac.WPF/Windows/AboutWindow.xaml @@ -1,24 +1,24 @@ - + Title="About Hex Maniac Advance" Height="300" Width="400"> - Gen3Hex is a non-profit open-source fan-made tool. + Hex Maniac Advance is a non-profit open-source fan-made tool. Only use it with legally purchased software. Pokemon is the property of Nintendo and GameFreak. Please support the official release. - - + + This is a prerelease debug version: please do not distribute! - MIT License + MIT License Solarized diff --git a/src/Gen3Hex.WPF/Windows/AboutWindow.xaml.cs b/src/HexManiac.WPF/Windows/AboutWindow.xaml.cs similarity index 93% rename from src/Gen3Hex.WPF/Windows/AboutWindow.xaml.cs rename to src/HexManiac.WPF/Windows/AboutWindow.xaml.cs index 89678294..02c89661 100644 --- a/src/Gen3Hex.WPF/Windows/AboutWindow.xaml.cs +++ b/src/HexManiac.WPF/Windows/AboutWindow.xaml.cs @@ -2,7 +2,7 @@ using System.Reflection; using System.Windows.Navigation; -namespace HavenSoft.Gen3Hex.WPF.Windows { +namespace HavenSoft.HexManiac.WPF.Windows { partial class AboutWindow { public AboutWindow() { InitializeComponent(); diff --git a/src/Gen3Hex.WPF/Windows/App.config b/src/HexManiac.WPF/Windows/App.config similarity index 100% rename from src/Gen3Hex.WPF/Windows/App.config rename to src/HexManiac.WPF/Windows/App.config diff --git a/src/Gen3Hex.WPF/Windows/App.xaml b/src/HexManiac.WPF/Windows/App.xaml similarity index 99% rename from src/Gen3Hex.WPF/Windows/App.xaml rename to src/HexManiac.WPF/Windows/App.xaml index 2cb51912..287edde3 100644 --- a/src/Gen3Hex.WPF/Windows/App.xaml +++ b/src/HexManiac.WPF/Windows/App.xaml @@ -1,7 +1,7 @@ - diff --git a/src/Gen3Hex.WPF/Windows/App.xaml.cs b/src/HexManiac.WPF/Windows/App.xaml.cs similarity index 88% rename from src/Gen3Hex.WPF/Windows/App.xaml.cs rename to src/HexManiac.WPF/Windows/App.xaml.cs index 91cf97ba..0fd292b5 100644 --- a/src/Gen3Hex.WPF/Windows/App.xaml.cs +++ b/src/HexManiac.WPF/Windows/App.xaml.cs @@ -1,13 +1,13 @@ -using HavenSoft.Gen3Hex.Core.Models; -using HavenSoft.Gen3Hex.Core.ViewModels; -using HavenSoft.Gen3Hex.WPF.Implementations; +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.ViewModels; +using HavenSoft.HexManiac.WPF.Implementations; using System.IO; using System.Reflection; using System.Windows; -[assembly: AssemblyTitle("Gen3Hex")] +[assembly: AssemblyTitle("HexManiacAdvance")] -namespace HavenSoft.Gen3Hex.WPF.Windows { +namespace HavenSoft.HexManiac.WPF.Windows { partial class App { protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); diff --git a/src/Gen3Hex.WPF/Windows/MainWindow.xaml b/src/HexManiac.WPF/Windows/MainWindow.xaml similarity index 57% rename from src/Gen3Hex.WPF/Windows/MainWindow.xaml rename to src/HexManiac.WPF/Windows/MainWindow.xaml index fa70c63b..abd6decf 100644 --- a/src/Gen3Hex.WPF/Windows/MainWindow.xaml +++ b/src/HexManiac.WPF/Windows/MainWindow.xaml @@ -1,14 +1,14 @@ - + Title="Hex Maniac Advance" Height="450" Width="870" AllowDrop="True" Background="{DynamicResource Background}"> @@ -219,147 +219,159 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Gen3Hex.WPF/Windows/MainWindow.xaml.cs b/src/HexManiac.WPF/Windows/MainWindow.xaml.cs similarity index 94% rename from src/Gen3Hex.WPF/Windows/MainWindow.xaml.cs rename to src/HexManiac.WPF/Windows/MainWindow.xaml.cs index d5347232..40a878ff 100644 --- a/src/Gen3Hex.WPF/Windows/MainWindow.xaml.cs +++ b/src/HexManiac.WPF/Windows/MainWindow.xaml.cs @@ -1,8 +1,8 @@ -using HavenSoft.Gen3Hex.Core; -using HavenSoft.Gen3Hex.Core.Models; -using HavenSoft.Gen3Hex.Core.ViewModels; -using HavenSoft.Gen3Hex.Core.ViewModels.Tools; -using HavenSoft.Gen3Hex.WPF.Controls; +using HavenSoft.HexManiac.Core; +using HavenSoft.HexManiac.Core.Models; +using HavenSoft.HexManiac.Core.ViewModels; +using HavenSoft.HexManiac.Core.ViewModels.Tools; +using HavenSoft.HexManiac.WPF.Controls; using System; using System.Collections.Generic; using System.ComponentModel; @@ -13,7 +13,7 @@ using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; -namespace HavenSoft.Gen3Hex.WPF.Windows { +namespace HavenSoft.HexManiac.WPF.Windows { partial class MainWindow { private readonly List deferredActions = new List(); @@ -119,8 +119,8 @@ namespace HavenSoft.Gen3Hex.WPF.Windows { if (ViewModel.Count == 0) Close(); } - private void WikiClick(object sender, EventArgs e) => System.Diagnostics.Process.Start("https://github.com/haven1433/gen3hex/wiki"); - private void ReportIssueClick(object sender, EventArgs e) => System.Diagnostics.Process.Start("https://github.com/haven1433/gen3hex/issues"); + private void WikiClick(object sender, EventArgs e) => System.Diagnostics.Process.Start("https://github.com/haven1433/HexManiacAdvance/wiki"); + private void ReportIssueClick(object sender, EventArgs e) => System.Diagnostics.Process.Start("https://github.com/haven1433/HexManiacAdvance/issues"); private void AboutClick(object sender, EventArgs e) => new AboutWindow().ShowDialog(); private void EditBoxVisibilityChanged(object sender, DependencyPropertyChangedEventArgs e) { diff --git a/src/Gen3Hex.WPF/app.config b/src/HexManiac.WPF/app.config similarity index 100% rename from src/Gen3Hex.WPF/app.config rename to src/HexManiac.WPF/app.config