using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace OpenVIII { /// /// Loads strings from FF8 files /// public partial class Strings { #region Fields private static ConcurrentDictionary Files; private static object Filesloc = new object(); #endregion Fields #region Constructors public Strings() => Init(); #endregion Constructors #region Enums /// /// filenames of files with strings and id's for structs that hold the data. /// public enum FileID : uint { MNGRP = 0, AREAMES = 2, NAMEDIC = 3, KERNEL = 4, } #endregion Enums #region Methods public FF8String GetName(Characters c, Saves.Data d = null) => GetName(c.ToFacesID(), d); public FF8String GetName(GFs gf, Saves.Data d = null) => GetName(gf.ToFacesID(), d); public FF8String GetName(Faces.ID id, Saves.Data d = null) { if (d == null) d = Memory.State; switch (id) { case Faces.ID.Squall_Leonhart: return d.Squallsname ?? Read(FileID.MNGRP, 2, 92); case Faces.ID.Rinoa_Heartilly: return d.Rinoasname ?? Read(FileID.MNGRP, 2, 93); case Faces.ID.Angelo: return d.Angelosname ?? Read(FileID.MNGRP, 2, 94); case Faces.ID.Boko: return d.Bokosname ?? Read(FileID.MNGRP, 2, 135); case Faces.ID.Zell_Dincht: case Faces.ID.Irvine_Kinneas: case Faces.ID.Quistis_Trepe: case Faces.ID.Selphie_Tilmitt: case Faces.ID.Seifer_Almasy: case Faces.ID.Edea_Kramer: case Faces.ID.Laguna_Loire: case Faces.ID.Kiros_Seagill: case Faces.ID.Ward_Zabac: return Read(FileID.KERNEL, 6, (int)id); case Faces.ID.Quezacotl: case Faces.ID.Shiva: case Faces.ID.Ifrit: case Faces.ID.Siren: case Faces.ID.Brothers: case Faces.ID.Diablos: case Faces.ID.Carbuncle: case Faces.ID.Leviathan: case Faces.ID.Pandemona: case Faces.ID.Cerberus: case Faces.ID.Alexander: case Faces.ID.Doomtrain: case Faces.ID.Bahamut: case Faces.ID.Cactuar: case Faces.ID.Tonberry: case Faces.ID.Eden: return d.GFs[id.ToGFs()].Name ?? Read(FileID.MNGRP, 2, 95 + (int)(id.ToGFs())); case Faces.ID.Griever: return d.Grieversname ?? Read(FileID.MNGRP, 2, 135); case Faces.ID.MiniMog: return Read(FileID.KERNEL, 0, 72); // also in KERNEL, 12, 36 default: return new FF8String(); } } /// /// Remember to Close() if done using /// /// /// /// /// public FF8StringReference Read(FileID fileID, int sectionID, int stringID) => Files[fileID][(uint)sectionID, stringID]; public StringsBase this[FileID id] => Files[id]; private void Init() { lock (Filesloc) if (Files == null) { var tasks = new List>(); Files = new ConcurrentDictionary(); tasks.Add(Task.Run(() => Files.TryAdd(FileID.NAMEDIC, Namedic.Load()))); // areames and kernel require namedic //though there shouldn't be anything reading the strings till this is done processing //Task.WaitAll(tasks.ToArray()); tasks.Add(Task.Run(() => Files.TryAdd(FileID.MNGRP, Mngrp.Load()))); tasks.Add(Task.Run(() => Files.TryAdd(FileID.AREAMES, Areames.Load()))); tasks.Add(Task.Run(() => Files.TryAdd(FileID.KERNEL, Kernel.Load()))); Task.WaitAll(tasks.ToArray()); if (tasks.Any(x => !x.Result)) throw new ArgumentException($"{this}::Failed to add to dictionary..."); } } #endregion Methods } }