#region References using System; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.IO; using System.Runtime.InteropServices; using System.Text; #endregion namespace Ultima { public sealed class SpeechList { public static List Entries { get; set; } private static readonly byte[] m_Buffer = new byte[128]; static SpeechList() { Initialize(); } /// /// Loads speech.mul in /// public static void Initialize() { string path = Files.GetFilePath("speech.mul"); if (path == null) { Entries = new List(0); return; } Entries = new List(); using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { var buffer = new byte[fs.Length]; unsafe { int order = 0; fs.Read(buffer, 0, buffer.Length); fixed (byte* data = buffer) { byte* bindat = data; byte* bindatend = bindat + buffer.Length; while (bindat != bindatend) { var id = (short)((*bindat++ >> 8) | (*bindat++)); //Swapped Endian var length = (short)((*bindat++ >> 8) | (*bindat++)); if (length > 128) { length = 128; } for (int i = 0; i < length; ++i) { m_Buffer[i] = *bindat++; } string keyword = Encoding.UTF8.GetString(m_Buffer, 0, length); Entries.Add(new SpeechEntry(id, keyword, order)); ++order; } } } } } /// /// Saves speech.mul to /// /// public static void SaveSpeechList(string FileName) { Entries.Sort(new OrderComparer()); using (var fs = new FileStream(FileName, FileMode.Create, FileAccess.Write, FileShare.Write)) { using (var bin = new BinaryWriter(fs)) { foreach (SpeechEntry entry in Entries) { bin.Write(NativeMethods.SwapEndian(entry.ID)); byte[] utf8String = Encoding.UTF8.GetBytes(entry.KeyWord); var length = (short)utf8String.Length; bin.Write(NativeMethods.SwapEndian(length)); bin.Write(utf8String); } } } } public static void ExportToCSV(string FileName) { using (var Tex = new StreamWriter(new FileStream(FileName, FileMode.Create, FileAccess.ReadWrite), Encoding.Unicode)) { Tex.WriteLine("Order;ID;KeyWord"); foreach (SpeechEntry entry in Entries) { Tex.WriteLine(String.Format("{0};{1};{2}", entry.Order, entry.ID, entry.KeyWord)); } } } public static void ImportFromCSV(string FileName) { Entries = new List(0); if (!File.Exists(FileName)) { return; } using (var sr = new StreamReader(FileName)) { string line; while ((line = sr.ReadLine()) != null) { if ((line = line.Trim()).Length == 0 || line.StartsWith("#")) { continue; } if ((line.Contains("Order")) && (line.Contains("KeyWord"))) { continue; } try { string[] split = line.Split(';'); if (split.Length < 3) { continue; } int order = ConvertStringToInt(split[0]); int id = ConvertStringToInt(split[1]); string word = split[2]; word = word.Replace("\"", ""); Entries.Add(new SpeechEntry((short)id, word, order)); } catch { } } } } public static int ConvertStringToInt(string text) { int result; if (text.Contains("0x")) { string convert = text.Replace("0x", ""); int.TryParse(convert, NumberStyles.HexNumber, null, out result); } else { int.TryParse(text, NumberStyles.Integer, null, out result); } return result; } #region SortComparer public class IDComparer : IComparer { private readonly bool m_desc; public IDComparer(bool desc) { m_desc = desc; } public int Compare(SpeechEntry objA, SpeechEntry objB) { if (objA.ID == objB.ID) { return 0; } else if (m_desc) { return (objA.ID < objB.ID) ? 1 : -1; } else { return (objA.ID < objB.ID) ? -1 : 1; } } } public class KeyWordComparer : IComparer { private readonly bool m_desc; public KeyWordComparer(bool desc) { m_desc = desc; } public int Compare(SpeechEntry objA, SpeechEntry objB) { if (m_desc) { return String.Compare(objB.KeyWord, objA.KeyWord); } else { return String.Compare(objA.KeyWord, objB.KeyWord); } } } public class OrderComparer : IComparer { public int Compare(SpeechEntry objA, SpeechEntry objB) { if (objA.Order == objB.Order) { return 0; } else { return (objA.Order < objB.Order) ? -1 : 1; } } } #endregion } public sealed class SpeechEntry { public short ID { get; set; } public string KeyWord { get; set; } [Browsable(false)] public int Order { get; private set; } public SpeechEntry(short id, string keyword, int order) { ID = id; KeyWord = keyword; Order = order; } } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct SpeechMul { public short id; public short length; public byte[] keyword; } }