Archive.cs 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. using OpenVIII.Fields.Scripts.Instructions;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using System.IO;
  6. using System.Linq;
  7. namespace OpenVIII.Fields
  8. {
  9. public class Archive
  10. {
  11. #region Properties
  12. public string ArchiveName { get; set; }
  13. public Background Background { get; set; }
  14. public Cameras Cameras { get; set; }
  15. public EventEngine EventEngine { get; set; }
  16. public string FileName { get; set; }
  17. public Sections Flags { get; set; }
  18. public ushort ID { get; set; }
  19. public INF INF { get; set; }
  20. public List<Scripts.Jsm.GameObject> JSMObjects { get; set; }
  21. public FieldModes Mod { get; set; } = 0;
  22. public MrtRat MrtRat { get; set; }
  23. public MSK MSK { get; set; }
  24. public PMP PMP { get; set; }
  25. public IServices Services { get; set; }
  26. public SFX SFX { get; set; }
  27. public TDW TDW { get; set; }
  28. public WalkMesh WalkMesh { get; set; }
  29. #endregion Properties
  30. #region Methods
  31. public static Archive Load(ushort inputFieldID, Sections flags = Sections.ALL)
  32. {
  33. var r = new Archive();
  34. return !r.Init(inputFieldID, flags) ? null : r;
  35. }
  36. public void Draw()
  37. {
  38. switch (Mod)
  39. {
  40. case FieldModes.Init:
  41. break;
  42. case FieldModes.Disabled:
  43. break;
  44. case FieldModes.DebugRender:
  45. case FieldModes.NoJSM:
  46. Background.Draw();
  47. break;
  48. default:
  49. throw new ArgumentOutOfRangeException();
  50. }
  51. }
  52. public HashSet<FF8String> GetAreaNames() => JSMObjects != null && JSMObjects.Count > 0 ?
  53. (
  54. from jsmObject in JSMObjects
  55. from script in jsmObject.Scripts
  56. from instruction in script.Segment.Flatten()
  57. where instruction is SETPLACE
  58. let setPlace = ((SETPLACE)instruction)
  59. select setPlace.AreaName()).ToHashSet() : null;
  60. public bool Init(ushort? inputFieldID = null, Sections flags = Sections.ALL)
  61. {
  62. Flags = flags;
  63. Memory.SuppressDraw = true;
  64. var aw = ArchiveWorker.Load(Memory.Archives.A_FIELD);
  65. var test = aw.GetListOfFiles();
  66. //TODO fix endless look on FieldID 50.
  67. ID = inputFieldID ?? Memory.FieldHolder.FieldID;
  68. var count = (Memory.FieldHolder.Fields?.Length ?? 0);
  69. if (ID >= count)
  70. return false;
  71. FileName = Memory.FieldHolder.GetString(ID);
  72. ArchiveName = test.FirstOrDefault(x => x.IndexOf(FileName, StringComparison.OrdinalIgnoreCase) >= 0);
  73. if (string.IsNullOrWhiteSpace(ArchiveName))
  74. {
  75. Memory.Log.WriteLine($"FileNotFound :: {ID} - {FileName.ToUpper()}");
  76. Mod = FieldModes.Disabled;
  77. return false;
  78. }
  79. var fieldArchive = aw.GetArchive(ArchiveName);
  80. var listOfFiles = fieldArchive.GetListOfFiles();
  81. string findString(string s) =>
  82. listOfFiles.FirstOrDefault(x => x.IndexOf(s, StringComparison.OrdinalIgnoreCase) >= 0);
  83. byte[] getFile(string s)
  84. {
  85. s = findString(Path.GetFileNameWithoutExtension(ArchiveName)+s);
  86. return !string.IsNullOrWhiteSpace(s) ? fieldArchive.GetBinaryFile(s) : null;
  87. }
  88. if (!flags.HasFlag(Sections.MIM | Sections.MAP) ||
  89. (Background = Background.Load(getFile(".mim"), getFile(".map"))) == null)
  90. {
  91. Mod = FieldModes.Disabled;
  92. }
  93. if (flags.HasFlag(Sections.CA | Sections.ID))
  94. {
  95. Cameras = Cameras.CreateInstance(getFile(".ca"));
  96. WalkMesh = WalkMesh.Load(getFile(".ID"), Cameras);
  97. }
  98. //let's start with scripts
  99. var sJsm = findString(".jsm");
  100. var sSy = findString(".sy");
  101. if (flags.HasFlag(Sections.JSM | Sections.SYM) && !string.IsNullOrWhiteSpace(sJsm) && (FileName != "test3"))
  102. {
  103. JSMObjects = Scripts.Jsm.File.Read(fieldArchive.GetBinaryFile(sJsm));
  104. if (Mod != FieldModes.NoJSM)
  105. {
  106. if (!string.IsNullOrWhiteSpace(sSy))
  107. {
  108. var symObjects = Sym.Reader.FromBytes(fieldArchive.GetBinaryFile(sSy));
  109. Services = Initializer.GetServices();
  110. EventEngine = ServiceId.Field[Services].Engine;
  111. EventEngine.Reset();
  112. for (var objIndex = 0; objIndex < JSMObjects.Count; objIndex++)
  113. {
  114. var obj = JSMObjects[objIndex];
  115. var fieldObject = new FieldObject(obj.Id, symObjects.GetObjectOrDefault(objIndex).Name);
  116. foreach (var script in obj.Scripts)
  117. fieldObject.Scripts.Add(script.ScriptId, script.Segment.GetExecuter());
  118. EventEngine.RegisterObject(fieldObject);
  119. }
  120. Mod++;
  121. }
  122. else
  123. {
  124. Debug.WriteLine($"FileNotFound :: {FileName.ToUpper()}.sy");
  125. //sy file might be optional.
  126. //Mod = Field_modes.NoJSM;
  127. }
  128. }
  129. }
  130. else
  131. {
  132. Mod = FieldModes.NoJSM;
  133. //goto end;
  134. }
  135. //if (flags.HasFlag(Sections.MCH))
  136. //{
  137. // byte[] mchB = getFile(".mch");//Field character models
  138. //}
  139. //if (flags.HasFlag(Sections.ONE))
  140. //{
  141. // byte[] oneB = getFile(".one");//Field character models container
  142. //}
  143. //if (flags.HasFlag(Sections.MSD))
  144. //{
  145. // byte[] msdB = getFile(".msd");//dialogs
  146. //}
  147. if (flags.HasFlag(Sections.INF))
  148. {
  149. var infData = getFile(".inf");//gateways
  150. if (infData != null && infData.Length > 0)
  151. INF = INF.Load(infData);
  152. }
  153. if (flags.HasFlag(Sections.TDW))
  154. {
  155. var tdwData = getFile(".tdw");//extra font
  156. if (tdwData != null && tdwData.Length > 0)
  157. TDW = new TDW(tdwData);
  158. }
  159. if (flags.HasFlag(Sections.MSK))
  160. {
  161. var mskData = getFile(".msk");//movie cam
  162. if (mskData != null && mskData.Length > 0)
  163. MSK = new MSK(mskData);
  164. }
  165. if (flags.HasFlag(Sections.RAT | Sections.MRT))
  166. {
  167. var ratData = getFile(".rat");//battle on field
  168. var mrtData = getFile(".mrt");//battle on field
  169. if (ratData != null && mrtData != null && ratData.Length > 0 && mrtData.Length > 0)
  170. MrtRat = new MrtRat(mrtData, ratData);
  171. }
  172. //if (flags.HasFlag(Sections.PMD))
  173. //{
  174. // byte[] pmdB = getFile(".pmd");//particle info
  175. // if (pmdB != null && pmdB.Length > 4)
  176. // using (FileStream fs = new FileStream(Path.Combine(Path.GetTempPath(),
  177. // $"{Memory.FieldHolder.GetString()}.pmd"), FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
  178. // fs.Write(pmdB, 0, pmdB.Length);
  179. //}
  180. if (flags.HasFlag(Sections.PMP))
  181. {
  182. var pmpData = getFile(".pmp");//particle graphic?
  183. if (pmpData != null && pmpData.Length > 4)
  184. PMP = new PMP(pmpData);
  185. }
  186. if (flags.HasFlag(Sections.SFX))
  187. {
  188. var sfxData = getFile(".sfx");//sound effects
  189. if (sfxData != null && sfxData.Length > 0)
  190. SFX = new SFX(sfxData);
  191. }
  192. if (Mod == FieldModes.NoJSM && Background == null)
  193. {
  194. Mod = FieldModes.Disabled;
  195. }
  196. return SFX != null || PMP != null || MrtRat != null || MSK != null || TDW != null || INF != null ||
  197. JSMObjects != null || EventEngine != null || Cameras != null || WalkMesh != null ||
  198. Background != null || Services != null;
  199. }
  200. public override string ToString() => $"{{{ID}, {FileName}, {Mod}}}";
  201. /*
  202. public HashSet<ushort> GetForcedBattleEncounters() => JSMObjects != null && JSMObjects.Count > 0 ?
  203. (
  204. from jsmObject in JSMObjects
  205. from script in jsmObject.Scripts
  206. from instruction in script.Segment.Flatten()
  207. where instruction is BATTLE
  208. let battle = ((BATTLE)instruction)
  209. select battle.Encounter).ToHashSet() : null;
  210. */
  211. public void Update()
  212. {
  213. switch (Mod)
  214. {
  215. case FieldModes.Init:
  216. break;
  217. case FieldModes.DebugRender:
  218. UpdateScript();
  219. Background?.Update();
  220. break; //await events here
  221. case FieldModes.NoJSM://no scripts but has background.
  222. Background?.Update();
  223. break; //await events here
  224. case FieldModes.Disabled:
  225. break;
  226. default:
  227. throw new ArgumentOutOfRangeException();
  228. }
  229. }
  230. private static void UpdateScript()
  231. {
  232. //We do not know every instruction and it's not possible for now to play field with unknown instruction
  233. //eventEngine.Update(services);
  234. }
  235. #endregion Methods
  236. }
  237. }