diff --git a/moddingSuite.Test/BaseTests.cs b/moddingSuite.BL.Test/BaseTests.cs similarity index 78% rename from moddingSuite.Test/BaseTests.cs rename to moddingSuite.BL.Test/BaseTests.cs index fabd400..cf77698 100644 --- a/moddingSuite.Test/BaseTests.cs +++ b/moddingSuite.BL.Test/BaseTests.cs @@ -1,9 +1,4 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace moddingSuite.Test { @@ -13,5 +8,6 @@ public abstract class BaseTests protected string RedDragonGameDataPath => TestContext.Properties["reddragonData"] as string; protected string AirLandGameDataPath => TestContext.Properties["airlandData"] as string; protected string AirLandUserDataPath => TestContext.Properties["airlandUserPath"] as string; + protected string RedDragonLinuxGameDataPath => TestContext.Properties["linuxReddragonData"] as string; } } diff --git a/moddingSuite.Test/EdataManagerTest.cs b/moddingSuite.BL.Test/EdataManagerTest.cs similarity index 88% rename from moddingSuite.Test/EdataManagerTest.cs rename to moddingSuite.BL.Test/EdataManagerTest.cs index 9da71ce..5f3cce7 100644 --- a/moddingSuite.Test/EdataManagerTest.cs +++ b/moddingSuite.BL.Test/EdataManagerTest.cs @@ -1,63 +1,65 @@ -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using moddingSuite.BL; -using System.IO; +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using moddingSuite.BL; +using moddingSuite.Model.Edata; +using System.IO; using System.Linq; - -namespace moddingSuite.Test -{ - [TestClass] - public class EdataManagerTest: BaseTests - { - + +namespace moddingSuite.Test +{ + [TestClass] + public class EdataManagerTest: BaseTests + { + [DataTestMethod] [DataRow("/48574/Data")] [DataRow("/48574/DataMap")] - [DataRow("/48574/NDF_NotFinal")] - [DataRow("/48574/NDF_Win")] - [DataRow("/48574/ZZ_1")] - [DataRow("/48574/ZZ_2")] - [DataRow("/48574/ZZ_3a")] - [DataRow("/48574/ZZ_3b")] - [DataRow("/48574/ZZ_4")] - [DataRow("/48574/ZZ_NotFinal")] - [DataRow("/48574/ZZ_Win")] - [DataRow("/49125/NDF_Win")] - [DataRow("/49964/NDF_Win")] - public void CanParseRedDragonHeader(string path) - { - var sut = new EdataManager($"{RedDragonGameDataPath}{path}.dat"); - sut.ParseEdataFile(); - sut.Files.Should().NotBeEmpty(); + [DataRow("/48574/NDF_NotFinal")] + [DataRow("/48574/NDF_Win")] + [DataRow("/48574/ZZ_1")] + [DataRow("/48574/ZZ_2")] + [DataRow("/48574/ZZ_3a")] + [DataRow("/48574/ZZ_3b")] + [DataRow("/48574/ZZ_4")] + [DataRow("/48574/ZZ_NotFinal")] + [DataRow("/48574/ZZ_Win")] + [DataRow("/49125/NDF_Win")] + [DataRow("/49964/NDF_Win")] + public void CanParseRedDragonHeader(string path) + { + var sut = new EdataManager($"{RedDragonGameDataPath}{path}.dat"); + sut.ParseEdataFile(); + sut.Files.Should().NotBeEmpty(); } [DataTestMethod] - [DataRow("/49125/NDF_Win")] - [DataRow("/49964/NDF_Win")] - [DataRow("/48574/NDF_Win")] - public void CanReadRawData(string path) - { - var manager = new EdataManager($"{RedDragonGameDataPath}{path}.dat"); - manager.ParseEdataFile(); - - var config = manager.Files.First(f => f.Path == @"pc\ndf\nonpatchable\config.ndfbin"); - var bytes = manager.GetRawData(config); - bytes.Should().NotBeEmpty(); + [DataRow("/49125/NDF_Win")] + [DataRow("/49964/NDF_Win")] + [DataRow("/48574/NDF_Win")] + public void CanReadRawData(string path) + { + var manager = new EdataManager($"{RedDragonGameDataPath}{path}.dat"); + manager.ParseEdataFile(); + + var config = manager.Files.First(f => f.Path == EdataManager.KnownLocation.Config); + config.FileType.Should().Be(EdataFileType.Ndfbin); + var bytes = manager.GetRawData(config); + bytes.Should().NotBeEmpty(); } [TestMethod] - public void CanParseAirLandBattleHeader() - { - var files = Directory.EnumerateFiles(AirLandGameDataPath, "*.dat", SearchOption.AllDirectories); - var count = 0; + public void CanParseAirLandBattleHeader() + { + var files = Directory.EnumerateFiles(AirLandGameDataPath, "*.dat", SearchOption.AllDirectories); + var count = 0; foreach(var file in files) { var sut = new EdataManager(file); sut.ParseEdataFile(); sut.Header.Magic.Should().BeGreaterThan(0); count++; - } - count.Should().BeGreaterThan(0); - } - } -} + } + count.Should().BeGreaterThan(0); + } + } +} diff --git a/moddingSuite.BL.Test/TradManagerTest.cs b/moddingSuite.BL.Test/TradManagerTest.cs new file mode 100644 index 0000000..ad57409 --- /dev/null +++ b/moddingSuite.BL.Test/TradManagerTest.cs @@ -0,0 +1,49 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using moddingSuite.BL; +using moddingSuite.Model.Edata; +using System.IO; +using System.Linq; + +namespace moddingSuite.Test +{ + [TestClass] + public class TradManagerTest: BaseTests + { + [DataTestMethod] + [DataRow("/48574/ZZ_Win")] + public void CanParseWindowsReadRawData(string path) + { + var manager = new EdataManager($"{RedDragonGameDataPath}{path}.dat"); + AssertAntiRadar(manager, StringType.Default); + } + + private static void AssertAntiRadar(EdataManager manager, StringType stringType) + { + AssertUnites("DC02000000000000", "Anti-Radar", manager, stringType); + } + + private static void AssertUnites(string hashView, string content, EdataManager manager, StringType stringType) + { + manager.ParseEdataFile(); + + var unites = manager.Files.First(f => f.Path == EdataManager.KnownLocation.Unites); + unites.FileType.Should().Be(EdataFileType.Dictionary); + var bytes = manager.GetRawData(unites); + bytes.Should().NotBeEmpty(); + + var tradManager = new TradManager(bytes, stringType); + tradManager.Entries.Should().NotBeEmpty(); + var antiRadar = tradManager.Entries.First(t => t.HashView == hashView); + antiRadar.Content.Should().Be(content); + } + + [DataTestMethod] + [DataRow("/430000319/ZZ_Linux")] + public void CanParseLinuxReadRawData(string path) + { + var manager = new EdataManager($"{RedDragonLinuxGameDataPath}{path}.dat"); + AssertAntiRadar(manager, StringType.Utf32); + } + } +} diff --git a/moddingSuite.BL.Test/UtilsTests.cs b/moddingSuite.BL.Test/UtilsTests.cs new file mode 100644 index 0000000..366de8d --- /dev/null +++ b/moddingSuite.BL.Test/UtilsTests.cs @@ -0,0 +1,21 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using moddingSuite.BL.Utils; + +namespace moddingSuite.BL.Test +{ + [TestClass] + public class UtilsTests + { + + [DataTestMethod] + [DataRow("K4", "4505000000000000")] + public void TestHash(string name, string expectedHashView) + { + var hash = StdUtils.CreateLocalisationHash(name, name.Length); + + var newHashView = StdUtils.ByteArrayToBigEndianHexByteString(hash); + newHashView.Should().Be(expectedHashView); + } + } +} diff --git a/moddingSuite.BL.Test/moddingSuite.BL.Test.csproj b/moddingSuite.BL.Test/moddingSuite.BL.Test.csproj new file mode 100644 index 0000000..296fcb7 --- /dev/null +++ b/moddingSuite.BL.Test/moddingSuite.BL.Test.csproj @@ -0,0 +1,24 @@ + + + + net472;net5.0 + + false + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + diff --git a/moddingSuite/BL/EdataManager.cs b/moddingSuite.BL/EdataManager.cs similarity index 93% rename from moddingSuite/BL/EdataManager.cs rename to moddingSuite.BL/EdataManager.cs index 9b9b237..4ab4f02 100644 --- a/moddingSuite/BL/EdataManager.cs +++ b/moddingSuite.BL/EdataManager.cs @@ -6,20 +6,39 @@ using System.Security.Cryptography; using System.Text; using moddingSuite.Model.Edata; -using moddingSuite.Util; using System.Runtime.InteropServices; using moddingSuite.ViewModel.Base; +using BLUtils = moddingSuite.BL.Utils.StdUtils; namespace moddingSuite.BL -{ +{ + + public enum OSPlatform + { + Generic, + Windows, + Linux + } + /// /// Thanks to Giovanni Condello. He created the "WargameEE DAT unpacker" which is the base for my EdataManager. /// TODO: implement virtual packages. /// public class EdataManager : ViewModelBase - { + { + + public static class KnownLocation + { + + public const string Unites = @"pc\localisation\us\localisation\unites.dic"; + public const string Config = @"pc\ndf\nonpatchable\config.ndfbin"; + + } + public static readonly byte[] EdataMagic = { 0x65, 0x64, 0x61, 0x74 }; + public OSPlatform Platform { get; private set; } + /// /// Creates a new Instance of a EdataManager. /// @@ -27,6 +46,16 @@ public class EdataManager : ViewModelBase public EdataManager(string filePath) { FilePath = filePath; + Platform = DetectOSSpecificString(FilePath); + } + + private static OSPlatform DetectOSSpecificString(string filePath) + { + var name = Path.GetFileNameWithoutExtension(filePath); + if (name == "ZZ_Linux") return OSPlatform.Linux; + else if (name == "ZZ_Win") return OSPlatform.Windows; + else return OSPlatform.Generic; + } static EdataManager() @@ -123,7 +152,7 @@ protected EdataHeader ReadEdataHeader() using (var fs = File.Open(FilePath, FileMode.Open)) fs.Read(buffer, 0, buffer.Length); - header = Utils.ByteArrayToStructure(buffer); + header = Utils.StdUtils.ByteArrayToStructure(buffer); if (header.Version > 2) throw new NotSupportedException(string.Format("Edata version {0} not supported", header.Version)); @@ -171,7 +200,7 @@ protected ObservableCollection ReadEdatV2Dictionary() fileStream.Read(checkSum, 0, checkSum.Length); file.Checksum = checkSum; - file.Name = Utils.ReadString(fileStream); + file.Name = BLUtils.ReadString(fileStream); file.Path = MergePath(dirs, file.Name); if (file.Name.Length % 2 == 0) @@ -202,7 +231,7 @@ protected ObservableCollection ReadEdatV2Dictionary() else if (endings.Count > 0) endings.Add(endings.Last()); - dir.Name = Utils.ReadString(fileStream); + dir.Name = BLUtils.ReadString(fileStream); if (dir.Name.Length % 2 == 0) fileStream.Seek(1, SeekOrigin.Current); @@ -251,7 +280,7 @@ protected ObservableCollection ReadEdatV1Dictionary() //file.Checksum = checkSum; fileStream.Seek(1, SeekOrigin.Current); //instead, skip 1 byte - as in WEE DAT unpacker - file.Name = Utils.ReadString(fileStream); + file.Name = Utils.StdUtils.ReadString(fileStream); file.Path = MergePath(dirs, file.Name); if ((file.Name.Length + 1) % 2 == 0) @@ -282,7 +311,7 @@ protected ObservableCollection ReadEdatV1Dictionary() else if (endings.Count > 0) endings.Add(endings.Last()); - dir.Name = Utils.ReadString(fileStream); + dir.Name = BLUtils.ReadString(fileStream); if ((dir.Name.Length + 1) % 2 == 1) fileStream.Seek(1, SeekOrigin.Current); @@ -397,7 +426,7 @@ protected string ReplaceRebuildV2(EdataContentFile oldFile, byte[] newContent) byte[] checkSum = curFile.Checksum; newFile.Write(checkSum, 0, checkSum.Length); - string name = Utils.ReadString(newFile); + string name = BLUtils.ReadString(newFile); if ((name.Length + 1) % 2 == 1) newFile.Seek(1, SeekOrigin.Current); @@ -407,7 +436,7 @@ protected string ReplaceRebuildV2(EdataContentFile oldFile, byte[] newContent) else if (fileGroupId > 0) { newFile.Seek(4, SeekOrigin.Current); - string name = Utils.ReadString(newFile); + string name = BLUtils.ReadString(newFile); if ((name.Length + 1) % 2 == 1) newFile.Seek(1, SeekOrigin.Current); @@ -501,7 +530,7 @@ protected string ReplaceRebuildV1(EdataContentFile oldFile, byte[] newContent) newFile.Seek(1, SeekOrigin.Current); - string name = Utils.ReadString(newFile); + string name = BLUtils.ReadString(newFile); if ((name.Length + 1) % 2 == 0) newFile.Seek(1, SeekOrigin.Current); @@ -511,7 +540,7 @@ protected string ReplaceRebuildV1(EdataContentFile oldFile, byte[] newContent) else if (fileGroupId > 0) { newFile.Seek(4, SeekOrigin.Current); - string name = Utils.ReadString(newFile); + string name = BLUtils.ReadString(newFile); if ((name.Length + 1) % 2 == 1) newFile.Seek(1, SeekOrigin.Current); @@ -604,11 +633,11 @@ public static EdataFileType GetFileTypeFromHeaderData(byte[] headerData) Array.Copy(headerData, tmp, knownHeader.Value.Length); //headerData = tmp; - if (Utils.ByteArrayCompare(tmp, knownHeader.Value)) + if (BLUtils.ByteArrayCompare(tmp, knownHeader.Value)) return knownHeader.Key; } else - if (Utils.ByteArrayCompare(headerData, knownHeader.Value)) + if (BLUtils.ByteArrayCompare(headerData, knownHeader.Value)) return knownHeader.Key; } diff --git a/moddingSuite/Model/Common/Md5Hash.cs b/moddingSuite.BL/Model/Common/Md5Hash.cs similarity index 100% rename from moddingSuite/Model/Common/Md5Hash.cs rename to moddingSuite.BL/Model/Common/Md5Hash.cs diff --git a/moddingSuite/Model/Edata/EdataContentFile.cs b/moddingSuite.BL/Model/Edata/EdataContentFile.cs similarity index 100% rename from moddingSuite/Model/Edata/EdataContentFile.cs rename to moddingSuite.BL/Model/Edata/EdataContentFile.cs diff --git a/moddingSuite/Model/Edata/EdataDir.cs b/moddingSuite.BL/Model/Edata/EdataDir.cs similarity index 100% rename from moddingSuite/Model/Edata/EdataDir.cs rename to moddingSuite.BL/Model/Edata/EdataDir.cs diff --git a/moddingSuite/Model/Edata/EdataEntity.cs b/moddingSuite.BL/Model/Edata/EdataEntity.cs similarity index 100% rename from moddingSuite/Model/Edata/EdataEntity.cs rename to moddingSuite.BL/Model/Edata/EdataEntity.cs diff --git a/moddingSuite/Model/Edata/EdataFileType.cs b/moddingSuite.BL/Model/Edata/EdataFileType.cs similarity index 100% rename from moddingSuite/Model/Edata/EdataFileType.cs rename to moddingSuite.BL/Model/Edata/EdataFileType.cs diff --git a/moddingSuite/Model/Edata/EdataHeader.cs b/moddingSuite.BL/Model/Edata/EdataHeader.cs similarity index 100% rename from moddingSuite/Model/Edata/EdataHeader.cs rename to moddingSuite.BL/Model/Edata/EdataHeader.cs diff --git a/moddingSuite/Model/Trad/TradEntry.cs b/moddingSuite.BL/Model/Trad/TradEntry.cs similarity index 70% rename from moddingSuite/Model/Trad/TradEntry.cs rename to moddingSuite.BL/Model/Trad/TradEntry.cs index c72e9ba..0259520 100644 --- a/moddingSuite/Model/Trad/TradEntry.cs +++ b/moddingSuite.BL/Model/Trad/TradEntry.cs @@ -1,6 +1,9 @@ -using moddingSuite.Util; +using moddingSuite.BL.Utils; using moddingSuite.ViewModel.Base; -using moddingSuite.ViewModel.Trad; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; namespace moddingSuite.Model.Trad { @@ -15,6 +18,10 @@ public class TradEntry : ViewModelBase private bool _userCreated = false; + private readonly static HashSet s_allowedChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + .ToCharArray() + .ToHashSet(); + public string HashView { get { return _hashView; } @@ -32,7 +39,7 @@ public byte[] Hash { _hash = value; - HashView = Utils.ByteArrayToBigEndianHexByteString(_hash); + HashView = StdUtils.ByteArrayToBigEndianHexByteString(_hash); OnPropertyChanged(() => Hash); } @@ -76,7 +83,7 @@ public string Content _content = value; if (UserCreated) - TradFileViewModel.CalculateHash(this); + CalculateHash(this); OnPropertyChanged(() => Content); } @@ -91,5 +98,18 @@ public bool UserCreated OnPropertyChanged(() => UserCreated); } } + + public static void CalculateHash(TradEntry item) + { + var wordToHash = new StringBuilder(); + + foreach (char t in item.Content) + if (s_allowedChars.Contains(t)) + wordToHash.Append(t); + + var word = wordToHash.ToString(); + + item.Hash = StdUtils.CreateLocalisationHash(word, word.Length); + } } } \ No newline at end of file diff --git a/moddingSuite/BL/TradManager.cs b/moddingSuite.BL/TradManager.cs similarity index 76% rename from moddingSuite/BL/TradManager.cs rename to moddingSuite.BL/TradManager.cs index fde0c35..0a21346 100644 --- a/moddingSuite/BL/TradManager.cs +++ b/moddingSuite.BL/TradManager.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; +using System.Diagnostics; using System.IO; using System.Linq; using System.Text; @@ -9,14 +10,35 @@ namespace moddingSuite.BL { + public enum StringType + { + Default, + Utf32 + } + public class TradManager { private ObservableCollection _entries = new ObservableCollection(); + private readonly StringType _stringType; + private readonly Encoding _encoder; private const ulong GlyphHash = (ulong)0x1 << 63; + private int _totalRead; - public TradManager(byte[] data) + public StringType StringType => _stringType; + public TradManager(byte[] data, StringType stringType) { + _stringType = stringType; + + if (_stringType == StringType.Utf32) + { + /* Linux file support */ + _encoder = Encoding.UTF32; + } else + { + _encoder = Encoding.Unicode; + } + _totalRead = 0; ParseTradFile(data); _entries.CollectionChanged += EntriesCollectionChanged; @@ -35,7 +57,7 @@ private void EntriesCollectionChanged(object sender, NotifyCollectionChangedEven ((TradEntry)tradEntry).UserCreated = true; } - protected void ParseTradFile(byte[] data) + private void ParseTradFile(byte[] data) { using (var ms = new MemoryStream(data)) { @@ -43,24 +65,26 @@ protected void ParseTradFile(byte[] data) Entries = ReadDictionary(entryCount, ms); GetEntryContents(ms); + Debug.Assert(ms.Capacity == _totalRead); } } - protected void GetEntryContents(MemoryStream ms) + private void GetEntryContents(MemoryStream ms) { + int charSize = _stringType == StringType.Utf32 ? 4 : 2; + foreach (TradEntry entry in Entries) { ms.Seek(entry.OffsetCont, SeekOrigin.Begin); - var buffer = new byte[entry.ContLen * 2]; - - ms.Read(buffer, 0, buffer.Length); + var buffer = new byte[entry.ContLen * charSize]; - entry.Content = Encoding.Unicode.GetString(buffer); + _totalRead += ms.Read(buffer, 0, buffer.Length); + entry.Content = _encoder.GetString(buffer); } } - protected ObservableCollection ReadDictionary(uint entryCount, MemoryStream ms) + private ObservableCollection ReadDictionary(uint entryCount, MemoryStream ms) { var entries = new ObservableCollection(); @@ -72,13 +96,13 @@ protected ObservableCollection ReadDictionary(uint entryCount, Memory var hashBuffer = new byte[8]; - ms.Read(hashBuffer, 0, hashBuffer.Length); + _totalRead += ms.Read(hashBuffer, 0, hashBuffer.Length); entry.Hash = hashBuffer; - ms.Read(buffer, 0, buffer.Length); + _totalRead += ms.Read(buffer, 0, buffer.Length); entry.OffsetCont = BitConverter.ToUInt32(buffer, 0); - ms.Read(buffer, 0, buffer.Length); + _totalRead += ms.Read(buffer, 0, buffer.Length); entry.ContLen = BitConverter.ToUInt32(buffer, 0); entries.Add(entry); @@ -87,16 +111,16 @@ protected ObservableCollection ReadDictionary(uint entryCount, Memory return entries; } - protected uint ReadHeader(MemoryStream ms) + private uint ReadHeader(MemoryStream ms) { var buffer = new byte[4]; - ms.Read(buffer, 0, buffer.Length); + _totalRead += ms.Read(buffer, 0, buffer.Length); if (Encoding.ASCII.GetString(buffer) != "TRAD") throw new ArgumentException("No valid Eugen Systems TRAD (*.dic) file."); - ms.Read(buffer, 0, buffer.Length); + _totalRead += ms.Read(buffer, 0, buffer.Length); return BitConverter.ToUInt32(buffer, 0); } @@ -144,7 +168,7 @@ public byte[] BuildTradFile() foreach (TradEntry entry in orderedEntried) { entry.OffsetCont = (uint)ms.Position; - buffer = Encoding.Unicode.GetBytes(entry.Content); + buffer = _encoder.GetBytes(entry.Content); ms.Write(buffer, 0, buffer.Length); } diff --git a/moddingSuite.BL/Utils/StdUtils.cs b/moddingSuite.BL/Utils/StdUtils.cs new file mode 100644 index 0000000..8d8d1e2 --- /dev/null +++ b/moddingSuite.BL/Utils/StdUtils.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; + +namespace moddingSuite.BL.Utils +{ + public static class StdUtils + { + public static string ByteArrayToBigEndianHexByteString(byte[] data) + { + if (data == null) + return string.Empty; + + var stringBuilderb = new StringBuilder(); + + stringBuilderb.Append(string.Empty); + + foreach (var b in data) + stringBuilderb.Append(string.Format("{0:X2}", b)); + + return stringBuilderb.ToString(); + } + + public static T ByteArrayToStructure(byte[] bytes) where T : struct + { + GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); + var stuff = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); + handle.Free(); + + return stuff; + } + + public static string ReadString(Stream fs) + { + var b = new StringBuilder(); + int c; + + do + { + c = fs.ReadByte(); + b.Append((char)c); + } while (c != '\0'); + + return StripString(b.ToString()); + } + + public static string StripString(string s) + { + return s.Split('\0')[0].TrimEnd(); + } + + public static bool ByteArrayCompare(ReadOnlySpan a1, ReadOnlySpan a2) + { + return a1.SequenceEqual(a2); + } + + + public static int RoundToNextDivBy4(int number) + { + while (number % 4 != 0) + number++; + + return number; + } + + public static void Swap(T a, T b) + { + T temp = a; + a = b; + b = temp; + } + + public static bool IsValueType(object obj) + { + return obj != null && obj.GetType().IsValueType; + } + + public static byte[] StructToBytes(object str) + { + if (!IsValueType(str)) + throw new ArgumentException("str"); + + int size = Marshal.SizeOf(str); + byte[] arr = new byte[size]; + IntPtr ptr = Marshal.AllocHGlobal(size); + + Marshal.StructureToPtr(str, ptr, true); + Marshal.Copy(ptr, arr, 0, size); + Marshal.FreeHGlobal(ptr); + + return arr; + } + + public static byte[] CreateLocalisationHash(string text, int maxSize = 8) + { + long hash = 0; + for (int i = 0; i < maxSize; ++i) + { + int value; + ushort chr = text[i]; + + if (chr == 0) + break; + + if ('0' <= chr && chr <= '9') + value = 1 + chr - '0'; + else if ('A' <= chr && chr <= 'Z') + value = 2 + '9' - '0' + chr - 'A'; + else if (chr == '_') + value = 3 + '9' - '0' + 'Z' - 'A'; + else if ('a' <= chr && chr <= 'z') + value = 4 + '9' - '0' + 'Z' - 'A' + chr - 'a'; + else + throw new InvalidDataException(""); + + hash = (hash << 6) | value; + } + + return BitConverter.GetBytes(hash); + } + } +} diff --git a/moddingSuite/ViewModel/Base/ViewModelBase.cs b/moddingSuite.BL/ViewModelBase.cs similarity index 100% rename from moddingSuite/ViewModel/Base/ViewModelBase.cs rename to moddingSuite.BL/ViewModelBase.cs diff --git a/moddingSuite.BL/moddingSuite.BL.csproj b/moddingSuite.BL/moddingSuite.BL.csproj new file mode 100644 index 0000000..4c53717 --- /dev/null +++ b/moddingSuite.BL/moddingSuite.BL.csproj @@ -0,0 +1,9 @@ + + + + net472;net5.0 + + + + + diff --git a/moddingSuite.Test/UnitTest1.cs b/moddingSuite.Test/UnitTest1.cs index 9c02c80..df6a8bc 100644 --- a/moddingSuite.Test/UnitTest1.cs +++ b/moddingSuite.Test/UnitTest1.cs @@ -129,16 +129,6 @@ public void TestMeshReader() mreader.Read(fs); } - [TestMethod] - public void TestHash() - { - const string toHash = "Leopard2A6"; - - var hash = Utils.CreateLocalisationHash(toHash, toHash.Length); - - Console.WriteLine("{0}", Utils.ByteArrayToBigEndianHexByteString(hash)); - } - //[TestMethod] public void ExportAreaVerteces() { diff --git a/moddingSuite.Test/moddingSuite.Test.csproj b/moddingSuite.Test/moddingSuite.Test.csproj index 177879f..f967f3f 100644 --- a/moddingSuite.Test/moddingSuite.Test.csproj +++ b/moddingSuite.Test/moddingSuite.Test.csproj @@ -13,6 +13,7 @@ + \ No newline at end of file diff --git a/moddingSuite.sln b/moddingSuite.sln index 6b2f361..35d3988 100644 --- a/moddingSuite.sln +++ b/moddingSuite.sln @@ -10,11 +10,16 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{66C08E0F-9595-4099-B2BC-9D0BD7162BBA}" ProjectSection(SolutionItems) = preProject .gitignore = .gitignore + NdfDecompiler.dgml = NdfDecompiler.dgml README.md = README.md EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "tgvExporter", "tgvExporter\tgvExporter.csproj", "{24E89F60-73BD-4AF3-A27F-06ED5AC496AA}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "moddingSuite.BL", "moddingSuite.BL\moddingSuite.BL.csproj", "{5719A530-3B69-4A61-9FE8-B2CD106ACA2F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "moddingSuite.BL.Test", "moddingSuite.BL.Test\moddingSuite.BL.Test.csproj", "{87F3A5AE-DF8F-4AD4-BFA8-8C99048A9347}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -33,6 +38,14 @@ Global {24E89F60-73BD-4AF3-A27F-06ED5AC496AA}.Debug|Any CPU.Build.0 = Debug|Any CPU {24E89F60-73BD-4AF3-A27F-06ED5AC496AA}.Release|Any CPU.ActiveCfg = Release|Any CPU {24E89F60-73BD-4AF3-A27F-06ED5AC496AA}.Release|Any CPU.Build.0 = Release|Any CPU + {5719A530-3B69-4A61-9FE8-B2CD106ACA2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5719A530-3B69-4A61-9FE8-B2CD106ACA2F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5719A530-3B69-4A61-9FE8-B2CD106ACA2F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5719A530-3B69-4A61-9FE8-B2CD106ACA2F}.Release|Any CPU.Build.0 = Release|Any CPU + {87F3A5AE-DF8F-4AD4-BFA8-8C99048A9347}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {87F3A5AE-DF8F-4AD4-BFA8-8C99048A9347}.Debug|Any CPU.Build.0 = Debug|Any CPU + {87F3A5AE-DF8F-4AD4-BFA8-8C99048A9347}.Release|Any CPU.ActiveCfg = Release|Any CPU + {87F3A5AE-DF8F-4AD4-BFA8-8C99048A9347}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/moddingSuite/BL/ImageService/BlockDXT/BlockDXT1.cs b/moddingSuite/BL/ImageService/BlockDXT/BlockDXT1.cs index 00482d8..ed97d94 100644 --- a/moddingSuite/BL/ImageService/BlockDXT/BlockDXT1.cs +++ b/moddingSuite/BL/ImageService/BlockDXT/BlockDXT1.cs @@ -1,4 +1,5 @@ -using moddingSuite.Util; +using moddingSuite.BL.Utils; +using moddingSuite.Util; using System; using System.Collections.Generic; using System.Linq; @@ -203,14 +204,14 @@ public void setIndices(int[] idx) /// Flip DXT1 block vertically. public void flip4() { - Utils.Swap(row(0), row(3)); - Utils.Swap(row(1), row(2)); + StdUtils.Swap(row(0), row(3)); + StdUtils.Swap(row(1), row(2)); } /// Flip half DXT1 block vertically. public void flip2() { - Utils.Swap(row(0), row(1)); + StdUtils.Swap(row(0), row(1)); } } } diff --git a/moddingSuite/BL/ImageService/RawImage.cs b/moddingSuite/BL/ImageService/RawImage.cs index 9942bd3..efac837 100644 --- a/moddingSuite/BL/ImageService/RawImage.cs +++ b/moddingSuite/BL/ImageService/RawImage.cs @@ -1,4 +1,5 @@ -using moddingSuite.Util; +using moddingSuite.BL.Utils; +using moddingSuite.Util; using System; using System.Collections.Generic; using System.Linq; @@ -79,7 +80,7 @@ public byte[] GetRawData() var ret = new List(); foreach (var col in Data) - ret.AddRange(Utils.StructToBytes(col)); + ret.AddRange(StdUtils.StructToBytes(col)); return ret.ToArray(); } diff --git a/moddingSuite/BL/Mesh/MeshReader.cs b/moddingSuite/BL/Mesh/MeshReader.cs index 28dc270..345b434 100644 --- a/moddingSuite/BL/Mesh/MeshReader.cs +++ b/moddingSuite/BL/Mesh/MeshReader.cs @@ -11,7 +11,8 @@ using moddingSuite.Model.Mesh; using System.Runtime.InteropServices; using moddingSuite.Util; - +using moddingSuite.BL.Utils; + namespace moddingSuite.BL.Mesh { public class MeshReader @@ -198,7 +199,7 @@ protected ObservableCollection ReadMeshDictionary(Stream s, Mes s.Read(buffer, 0, buffer.Length); file.HierarchicalAseModelSkeletonIndex = BitConverter.ToUInt16(buffer, 0); - file.Name = Utils.ReadString(s); + file.Name = StdUtils.ReadString(s); file.Path = MergePath(dirs, file.Name); if (file.Name.Length % 2 == 0) @@ -224,7 +225,7 @@ protected ObservableCollection ReadMeshDictionary(Stream s, Mes else if (endings.Count > 0) endings.Add(endings.Last()); - dir.Name = Utils.ReadString(s); + dir.Name = StdUtils.ReadString(s); if (dir.Name.Length % 2 == 0) s.Seek(1, SeekOrigin.Current); diff --git a/moddingSuite/BL/Scenario/ScenarioReader.cs b/moddingSuite/BL/Scenario/ScenarioReader.cs index c423bf8..80ba5af 100644 --- a/moddingSuite/BL/Scenario/ScenarioReader.cs +++ b/moddingSuite/BL/Scenario/ScenarioReader.cs @@ -10,7 +10,8 @@ using moddingSuite.Util; using moddingSuite.Model; using moddingSuite.Model.Settings; - +using moddingSuite.BL.Utils; +using moddingSuite.Util; namespace moddingSuite.BL.Scenario { @@ -29,7 +30,7 @@ public ScenarioFile Read(Stream s) var buffer = new byte[10]; s.Read(buffer, 0, buffer.Length); - if (!Utils.ByteArrayCompare(Encoding.ASCII.GetBytes("SCENARIO\r\n"), buffer)) + if (!StdUtils.ByteArrayCompare(Encoding.ASCII.GetBytes("SCENARIO\r\n"), buffer)) throw new InvalidDataException("Wrong scenario header magic!"); buffer = new byte[16]; @@ -118,7 +119,7 @@ protected Area ReadArea(Stream ms) ms.Read(buffer, 0, buffer.Length); int idStrLen = BitConverter.ToInt32(buffer, 0); - var idStrBuffer = new byte[Utils.RoundToNextDivBy4(idStrLen)]; + var idStrBuffer = new byte[StdUtils.RoundToNextDivBy4(idStrLen)]; ms.Read(idStrBuffer, 0, idStrBuffer.Length); currentZone.Name = Encoding.UTF8.GetString(idStrBuffer).TrimEnd('\0'); diff --git a/moddingSuite/BL/Scenario/ScenarioWriter.cs b/moddingSuite/BL/Scenario/ScenarioWriter.cs index c89b50b..dc5b35a 100644 --- a/moddingSuite/BL/Scenario/ScenarioWriter.cs +++ b/moddingSuite/BL/Scenario/ScenarioWriter.cs @@ -5,6 +5,7 @@ using System.Security.Cryptography; using System.Text; using moddingSuite.BL.Ndf; +using moddingSuite.BL.Utils; using moddingSuite.Model.Scenario; using moddingSuite.Util; @@ -33,7 +34,7 @@ public byte[] Write(ScenarioFile file) foreach (var contentFile in file.ContentFiles) { - int padding = Utils.RoundToNextDivBy4(contentFile.Length) - contentFile.Length; + int padding = StdUtils.RoundToNextDivBy4(contentFile.Length) - contentFile.Length; scenarioData.AddRange(BitConverter.GetBytes(contentFile.Length + padding)); scenarioData.AddRange(contentFile); @@ -77,7 +78,7 @@ protected byte[] CreateAreaSubFile(AreaFile file) ms.Write(BitConverter.GetBytes(area.Name.Length), 0, 4); var nameBuffer = Encoding.UTF8.GetBytes(area.Name); ms.Write(nameBuffer, 0, nameBuffer.Length); - ms.Seek(Util.Utils.RoundToNextDivBy4(nameBuffer.Length) - nameBuffer.Length, SeekOrigin.Current); + ms.Seek(StdUtils.RoundToNextDivBy4(nameBuffer.Length) - nameBuffer.Length, SeekOrigin.Current); ms.WriteAreaMagic(); ms.Write(BitConverter.GetBytes((float)area.AttachmentPoint.X), 0, 4); diff --git a/moddingSuite/BL/TGV/TgvBitmapReader.cs b/moddingSuite/BL/TGV/TgvBitmapReader.cs index 6b15b32..8b3ac26 100644 --- a/moddingSuite/BL/TGV/TgvBitmapReader.cs +++ b/moddingSuite/BL/TGV/TgvBitmapReader.cs @@ -5,7 +5,8 @@ using System.IO; using moddingSuite.Util; using System.Runtime.InteropServices; - +using moddingSuite.BL.Utils; + namespace moddingSuite.BL.TGV { public class TgvBitmapReader @@ -69,7 +70,7 @@ private static void ReadBlock(ColorBlock rgba, Stream ms) ms.Read(blockBuffer, 0, blockBuffer.Length); - var blockdxt5 = Utils.ByteArrayToStructure(blockBuffer); + var blockdxt5 = StdUtils.ByteArrayToStructure(blockBuffer); blockdxt5.decodeBlock(ref rgba); } diff --git a/moddingSuite/BL/TGV/TgvDDSReader.cs b/moddingSuite/BL/TGV/TgvDDSReader.cs index 32761b8..6b5c73f 100644 --- a/moddingSuite/BL/TGV/TgvDDSReader.cs +++ b/moddingSuite/BL/TGV/TgvDDSReader.cs @@ -1,9 +1,9 @@ -using System; +using moddingSuite.BL.DDS; +using moddingSuite.BL.Utils; +using moddingSuite.Model.Textures; +using System; using System.IO; using System.Runtime.InteropServices; -using moddingSuite.BL.DDS; -using moddingSuite.Model.Textures; -using moddingSuite.Util; namespace moddingSuite.BL.TGV { @@ -26,7 +26,7 @@ public TgvFile ReadDDS(byte[] input) buffer = new byte[Marshal.SizeOf(typeof(DDS.DDS.Header))]; ms.Read(buffer, 0, buffer.Length); - var header = Utils.ByteArrayToStructure(buffer); + var header = StdUtils.ByteArrayToStructure(buffer); int mipSize = contentSize; diff --git a/moddingSuite/BL/TGV/TgvDDSWriter.cs b/moddingSuite/BL/TGV/TgvDDSWriter.cs index 4d6755b..e1e085e 100644 --- a/moddingSuite/BL/TGV/TgvDDSWriter.cs +++ b/moddingSuite/BL/TGV/TgvDDSWriter.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Linq; +using moddingSuite.BL.Utils; using moddingSuite.Model.Textures; using moddingSuite.Util; @@ -61,7 +62,7 @@ protected byte[] CreateDDSHeader(TgvFile file) hd.PixelFormat = ddpf; - return Utils.StructToBytes(hd); + return StdUtils.StructToBytes(hd); } } } \ No newline at end of file diff --git a/moddingSuite/BL/TGV/TgvReader.cs b/moddingSuite/BL/TGV/TgvReader.cs index ae4d45c..c2d81b8 100644 --- a/moddingSuite/BL/TGV/TgvReader.cs +++ b/moddingSuite/BL/TGV/TgvReader.cs @@ -1,5 +1,6 @@ using moddingSuite.BL.Compressing; using moddingSuite.BL.DDS; +using moddingSuite.BL.Utils; using moddingSuite.Model.Textures; using moddingSuite.Util; using System; @@ -45,7 +46,7 @@ public TgvFile Read(Stream ms) ms.Read(buffer, 0, buffer.Length); file.PixelFormatStr = Encoding.ASCII.GetString(buffer); - ms.Seek(Utils.RoundToNextDivBy4(pixelFormatLen) - pixelFormatLen, SeekOrigin.Current); + ms.Seek(StdUtils.RoundToNextDivBy4(pixelFormatLen) - pixelFormatLen, SeekOrigin.Current); buffer = new byte[16]; ms.Read(buffer, 0, buffer.Length); @@ -179,7 +180,7 @@ private TgvMipMap ReadMip(Stream ms, TgvFile file, int id) buffer = new byte[4]; ms.Read(buffer, 0, buffer.Length); - if (!Utils.ByteArrayCompare(buffer, zipo)) + if (!StdUtils.ByteArrayCompare(buffer, zipo)) throw new InvalidDataException("Mipmap has to start with \"ZIPO\"!"); ms.Read(buffer, 0, buffer.Length); @@ -192,7 +193,7 @@ private TgvMipMap ReadMip(Stream ms, TgvFile file, int id) ms.Read(buffer, 0, buffer.Length); - ms.Seek(Utils.RoundToNextDivBy4((int)mipMap.Size)-mipMap.Size, SeekOrigin.Current); + ms.Seek(StdUtils.RoundToNextDivBy4((int)mipMap.Size)-mipMap.Size, SeekOrigin.Current); if (file.IsCompressed) buffer = Compressor.Decomp(buffer); diff --git a/moddingSuite/BL/TGV/TgvWriter.cs b/moddingSuite/BL/TGV/TgvWriter.cs index bc79b7a..be1fa96 100644 --- a/moddingSuite/BL/TGV/TgvWriter.cs +++ b/moddingSuite/BL/TGV/TgvWriter.cs @@ -1,5 +1,6 @@ using moddingSuite.BL.Compressing; using moddingSuite.BL.DDS; +using moddingSuite.BL.Utils; using moddingSuite.Model.Textures; using moddingSuite.Util; using System; @@ -48,7 +49,7 @@ public void Write(Stream destStream, TgvFile sourceFile, byte[] sourceChecksum, buffer = Encoding.ASCII.GetBytes(sourceFile.PixelFormatStr); destStream.Write(buffer, 0, buffer.Length); - destStream.Seek(Utils.RoundToNextDivBy4(fmtLen) - fmtLen, SeekOrigin.Current); + destStream.Seek(StdUtils.RoundToNextDivBy4(fmtLen) - fmtLen, SeekOrigin.Current); destStream.Write(sourceChecksum, 0, sourceChecksum.Length); diff --git a/moddingSuite/Model/Ndfbin/NdfPropertyValue.cs b/moddingSuite/Model/Ndfbin/NdfPropertyValue.cs index 371a739..e15ea85 100644 --- a/moddingSuite/Model/Ndfbin/NdfPropertyValue.cs +++ b/moddingSuite/Model/Ndfbin/NdfPropertyValue.cs @@ -11,7 +11,8 @@ using moddingSuite.ViewModel.Base; using moddingSuite.ViewModel.Ndf; using System.Diagnostics; - +using moddingSuite.BL.Utils; + namespace moddingSuite.Model.Ndfbin { public class NdfPropertyValue : ViewModelBase, IValueHolder, IEditableObject @@ -180,7 +181,7 @@ public void EndEdit() var newVal = Value.GetBytes(); - if (newVal != null && _oldVal != null && Utils.ByteArrayCompare(newVal, _oldVal)) + if (newVal != null && _oldVal != null && StdUtils.ByteArrayCompare(newVal, _oldVal)) return; ChangeEntryBase change = null; diff --git a/moddingSuite/Model/Ndfbin/Types/AllTypes/NdfColor128.cs b/moddingSuite/Model/Ndfbin/Types/AllTypes/NdfColor128.cs index 0365fff..1a5872d 100644 --- a/moddingSuite/Model/Ndfbin/Types/AllTypes/NdfColor128.cs +++ b/moddingSuite/Model/Ndfbin/Types/AllTypes/NdfColor128.cs @@ -1,5 +1,5 @@ using System; -using moddingSuite.Util; +using moddingSuite.BL.Utils; namespace moddingSuite.Model.Ndfbin.Types.AllTypes { @@ -26,7 +26,7 @@ public override byte[] GetBytes() public override string ToString() { - return string.Format("Vec4: {0}", Utils.ByteArrayToBigEndianHexByteString(Value)); + return string.Format("Vec4: {0}", StdUtils.ByteArrayToBigEndianHexByteString(Value)); } diff --git a/moddingSuite/Model/Ndfbin/Types/AllTypes/NdfHash.cs b/moddingSuite/Model/Ndfbin/Types/AllTypes/NdfHash.cs index 4b9c45e..7a07a4b 100644 --- a/moddingSuite/Model/Ndfbin/Types/AllTypes/NdfHash.cs +++ b/moddingSuite/Model/Ndfbin/Types/AllTypes/NdfHash.cs @@ -3,7 +3,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using moddingSuite.Util; +using moddingSuite.BL.Utils; namespace moddingSuite.Model.Ndfbin.Types.AllTypes { @@ -36,7 +36,7 @@ public override byte[] GetNdfText() public override string ToString() { - return Utils.ByteArrayToBigEndianHexByteString(Value); + return StdUtils.ByteArrayToBigEndianHexByteString(Value); } } } diff --git a/moddingSuite/Model/Ndfbin/Types/AllTypes/NdfLocalisationHash.cs b/moddingSuite/Model/Ndfbin/Types/AllTypes/NdfLocalisationHash.cs index a1ea3c1..03156ca 100644 --- a/moddingSuite/Model/Ndfbin/Types/AllTypes/NdfLocalisationHash.cs +++ b/moddingSuite/Model/Ndfbin/Types/AllTypes/NdfLocalisationHash.cs @@ -1,6 +1,6 @@ using System; -using moddingSuite.Util; - +using moddingSuite.BL.Utils; + namespace moddingSuite.Model.Ndfbin.Types.AllTypes { public class NdfLocalisationHash : NdfFlatValueWrapper @@ -27,7 +27,7 @@ public override byte[] GetBytes() public override string ToString() { - return Utils.ByteArrayToBigEndianHexByteString(Value); + return StdUtils.ByteArrayToBigEndianHexByteString(Value); } public override byte[] GetNdfText() diff --git a/moddingSuite/Model/Ndfbin/Types/AllTypes/NdfUnkown.cs b/moddingSuite/Model/Ndfbin/Types/AllTypes/NdfUnkown.cs index 71a9156..0044b3b 100644 --- a/moddingSuite/Model/Ndfbin/Types/AllTypes/NdfUnkown.cs +++ b/moddingSuite/Model/Ndfbin/Types/AllTypes/NdfUnkown.cs @@ -1,6 +1,6 @@ using System; -using moddingSuite.Util; - +using moddingSuite.BL.Utils; + namespace moddingSuite.Model.Ndfbin.Types.AllTypes { public class NdfUnkown : NdfFlatValueWrapper @@ -22,7 +22,7 @@ public override byte[] GetNdfText() public override string ToString() { - return string.Format("{0}", Utils.ByteArrayToBigEndianHexByteString((byte[]) Value)); + return string.Format("{0}", StdUtils.ByteArrayToBigEndianHexByteString((byte[]) Value)); } } } \ No newline at end of file diff --git a/moddingSuite/Util/Utils.cs b/moddingSuite/Util/Utils.cs index 310685a..afaa661 100644 --- a/moddingSuite/Util/Utils.cs +++ b/moddingSuite/Util/Utils.cs @@ -8,25 +8,6 @@ namespace moddingSuite.Util { public static class Utils { - public static string ReadString(Stream fs) - { - var b = new StringBuilder(); - int c; - - do - { - c = fs.ReadByte(); - b.Append((char)c); - } while (c != '\0'); - - return StripString(b.ToString()); - } - - public static string StripString(string s) - { - return s.Split('\0')[0].TrimEnd(); - } - public static string Int32ToBigEndianHexByteString(Int32 i) { byte[] bytes = BitConverter.GetBytes(i); @@ -36,21 +17,6 @@ public static string Int32ToBigEndianHexByteString(Int32 i) return String.Format(format, bytes[0], bytes[1], bytes[2], bytes[3]); } - public static string ByteArrayToBigEndianHexByteString(byte[] data) - { - if (data == null) - return string.Empty; - - var stringBuilderb = new StringBuilder(); - - stringBuilderb.Append(string.Empty); - - foreach (var b in data) - stringBuilderb.Append(string.Format("{0:X2}", b)); - - return stringBuilderb.ToString(); - } - public static byte[] StringToByteArrayFastest(string hex) { if (hex.Length % 2 == 1) @@ -75,16 +41,6 @@ public static int GetHexVal(char hex) return val - (val < 58 ? 48 : (val < 97 ? 55 : 87)); } - [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] - private static extern int memcmp(byte[] b1, byte[] b2, long count); - - public static bool ByteArrayCompare(byte[] b1, byte[] b2) - { - // Validate buffers are the same length. - // This also ensures that the count does not exceed the length of either buffer. - return b1.Length == b2.Length && memcmp(b1, b2, b1.Length) == 0; - } - public static void SaveDebug(string fileName, byte[] contentData) { var path = SettingsManager.Load().SavePath; @@ -108,78 +64,5 @@ public static string GenerateCoupon(int length, Random random) return result.ToString(); } - - public static byte[] CreateLocalisationHash(string text, int maxSize = 8) - { - long hash = 0; - for (int i = 0; i < maxSize; ++i) - { - int value; - ushort chr = text[i]; - - if (chr == 0) - break; - - if ('0' <= chr && chr <= '9') - value = 1 + chr - '0'; - else if ('A' <= chr && chr <= 'Z') - value = 2 + '9' - '0' + chr - 'A'; - else if (chr == '_') - value = 3 + '9' - '0' + 'Z' - 'A'; - else if ('a' <= chr && chr <= 'z') - value = 4 + '9' - '0' + 'Z' - 'A' + chr - 'a'; - else - throw new InvalidDataException(""); - - hash = (hash << 6) | value; - } - - return BitConverter.GetBytes(hash); - } - - public static bool IsValueType(object obj) - { - return obj != null && obj.GetType().IsValueType; - } - - public static byte[] StructToBytes(object str) - { - if (!IsValueType(str)) - throw new ArgumentException("str"); - - int size = Marshal.SizeOf(str); - byte[] arr = new byte[size]; - IntPtr ptr = Marshal.AllocHGlobal(size); - - Marshal.StructureToPtr(str, ptr, true); - Marshal.Copy(ptr, arr, 0, size); - Marshal.FreeHGlobal(ptr); - - return arr; - } - - public static T ByteArrayToStructure(byte[] bytes) where T : struct - { - GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); - var stuff = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); - handle.Free(); - - return stuff; - } - - public static int RoundToNextDivBy4(int number) - { - while (number % 4 != 0) - number++; - - return number; - } - - public static void Swap(T a, T b) - { - T temp = a; - a = b; - b = temp; - } } } \ No newline at end of file diff --git a/moddingSuite/View/Edata/EdataFileView.xaml b/moddingSuite/View/Edata/EdataFileView.xaml index 50f7e59..a0d51c3 100644 --- a/moddingSuite/View/Edata/EdataFileView.xaml +++ b/moddingSuite/View/Edata/EdataFileView.xaml @@ -1,98 +1,104 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/moddingSuite/View/Extension/LocalisationHashValueConverter.cs b/moddingSuite/View/Extension/LocalisationHashValueConverter.cs index 1d206f2..74b29f7 100644 --- a/moddingSuite/View/Extension/LocalisationHashValueConverter.cs +++ b/moddingSuite/View/Extension/LocalisationHashValueConverter.cs @@ -1,6 +1,7 @@ using System; using System.Globalization; using System.Windows.Data; +using moddingSuite.BL.Utils; using moddingSuite.Util; namespace moddingSuite.View.Extension @@ -11,7 +12,7 @@ public class LocalisationHashValueConverter : IValueConverter public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - return Utils.ByteArrayToBigEndianHexByteString((byte[]) value); + return StdUtils.ByteArrayToBigEndianHexByteString((byte[]) value); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) diff --git a/moddingSuite/ViewModel/Edata/EdataFileViewModel.cs b/moddingSuite/ViewModel/Edata/EdataFileViewModel.cs index 3eff442..5a99747 100644 --- a/moddingSuite/ViewModel/Edata/EdataFileViewModel.cs +++ b/moddingSuite/ViewModel/Edata/EdataFileViewModel.cs @@ -9,6 +9,7 @@ namespace moddingSuite.ViewModel.Edata { + public class EdataFileViewModel : ViewModelBase { private ObservableCollection _files; @@ -19,6 +20,8 @@ public class EdataFileViewModel : ViewModelBase public EdataManager EdataManager { get; protected set; } + public OSPlatform Platform => EdataManager.Platform; + public ICommand CloseCommand { get; set; } public ICommand DetailsCommand { get; set; } diff --git a/moddingSuite/ViewModel/Trad/TradFileViewModel.cs b/moddingSuite/ViewModel/Trad/TradFileViewModel.cs index 1fd5e17..47032b8 100644 --- a/moddingSuite/ViewModel/Trad/TradFileViewModel.cs +++ b/moddingSuite/ViewModel/Trad/TradFileViewModel.cs @@ -31,7 +31,9 @@ public TradFileViewModel(EdataContentFile owner, EdataFileViewModel contentFile) OwnerFile = owner; OwnerVm = contentFile; - Manager = new TradManager(OwnerVm.EdataManager.GetRawData(OwnerFile)); + var stringType = OwnerVm.Platform == OSPlatform.Linux ? StringType.Utf32 : StringType.Default; + + Manager = new TradManager(OwnerVm.EdataManager.GetRawData(OwnerFile), stringType); Entries = Manager.Entries; @@ -111,23 +113,7 @@ private void CreateHashExecute(object obj) if (item == null || !item.UserCreated) return; - CalculateHash(item); - } - - public static void CalculateHash(TradEntry item) - { - const string characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - var allowedChars = characters.ToCharArray().ToList(); - - var wordToHash = new StringBuilder(); - - foreach (char t in item.Content) - if (allowedChars.Contains(t)) - wordToHash.Append(t); - - var word = wordToHash.ToString(); - - item.Hash = Utils.CreateLocalisationHash(word, word.Length); + TradEntry.CalculateHash(item); } private void SaveCommandExecute(object obj) diff --git a/moddingSuite/moddingSuite.csproj b/moddingSuite/moddingSuite.csproj index e059e4e..3e82c54 100644 --- a/moddingSuite/moddingSuite.csproj +++ b/moddingSuite/moddingSuite.csproj @@ -265,13 +265,11 @@ - - - + $(NuGetPackageRoot)ironpython\3.4.0-alpha1\lib\net5.0\IronPython.dll @@ -292,4 +290,10 @@ + + + + + + \ No newline at end of file