Memory.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932
  1. using Microsoft.Xna.Framework;
  2. using Microsoft.Xna.Framework.Content;
  3. using Microsoft.Xna.Framework.Graphics;
  4. using System;
  5. using System.Collections.Concurrent;
  6. using System.Collections.Generic;
  7. using System.IO;
  8. using System.Linq;
  9. using System.Threading;
  10. using System.Threading.Tasks;
  11. #pragma warning disable CS0649
  12. namespace OpenVIII
  13. {
  14. public enum MODULE : int
  15. {
  16. BATTLE = 3,
  17. BATTLE_SWIRL = 4,
  18. FIELD = 5,
  19. FIELD_DEBUG = -5,
  20. BATTLE_DEBUG = -3,
  21. MOVIETEST = -9,
  22. OVERTURE_DEBUG = -12,
  23. MAINMENU_DEBUG = -13,
  24. WORLD_DEBUG = -17,
  25. FACE_TEST = -20,
  26. ICON_TEST = -21,
  27. CARD_TEST = -22,
  28. FIELD_MODEL_TEST = -51,
  29. }
  30. /// <summary>
  31. /// Battle Speed Settings
  32. /// </summary>
  33. /// <see cref="https://gamefaqs.gamespot.com/ps/197343-final-fantasy-viii/faqs/58936"/>
  34. public enum BattleSpeed : byte
  35. {
  36. Fastest = 1,
  37. Fast,
  38. Normal,
  39. Slow,
  40. Slowest,
  41. }
  42. /// <summary>
  43. /// Speed Mod
  44. /// </summary>
  45. /// <see cref="https://gamefaqs.gamespot.com/ps/197343-final-fantasy-viii/faqs/58936"/>
  46. public enum SpeedMod : byte
  47. {
  48. Stop = 0,
  49. Slow = 1,
  50. Normal = 2,
  51. Haste = 3,
  52. AlwaysFull = 0xFF //not sure what i should set this too.
  53. }
  54. public static partial class Memory
  55. {
  56. public static bool EnableDumpingData = false;
  57. public static BattleSpeed CurrentBattleSpeed => Memory.State?.Configuration?.BattleSpeed ?? BattleSpeed.Normal;
  58. public static List<Task> LeftOverTask = new List<Task>();
  59. public enum GraphicModes
  60. {
  61. OpenGL,
  62. DirectX
  63. };
  64. public static GraphicModes currentGraphicMode;
  65. //monogame
  66. public static GraphicsDeviceManager graphics;
  67. public static SpriteBatch spriteBatch;
  68. private static int mainThreadID;
  69. public static ContentManager content;
  70. public static bool IsActive = true;
  71. public static Font font;
  72. public static Task InitTask;
  73. //public static Texture2D[] iconsTex;
  74. public static Cards Cards;
  75. public static Card.Game Card_Game;
  76. public static Faces Faces;
  77. public static Icons Icons;
  78. public static Strings Strings;
  79. public static Kernel_bin Kernel_Bin;
  80. public static Texture2D shadowTexture;
  81. public static VertexPositionTexture[] shadowGeometry;
  82. public static Extended.Languages languages = Extended.Languages.en;
  83. public enum ScaleMode
  84. {
  85. /// <summary>
  86. /// scale object to have the same height as viewport
  87. /// </summary>
  88. FitVertical,
  89. /// <summary>
  90. /// scale object to have the same width as viewport
  91. /// </summary>
  92. FitHorizontal,
  93. /// <summary>
  94. /// Same as FitVertical unless width is too large, then it becomes FitHorizontal
  95. /// </summary>
  96. FitBoth,
  97. /// <summary>
  98. /// fill the entire viewport
  99. /// </summary>
  100. Stretch
  101. }
  102. public static Point Center => new Point(graphics.GraphicsDevice.Viewport.Width / 2, graphics.GraphicsDevice.Viewport.Height / 2);
  103. public const ScaleMode _scaleMode = ScaleMode.Stretch;
  104. public static Vector2 Scale(float Width = PreferredViewportWidth, float Height = PreferredViewportHeight, ScaleMode scaleMode = _scaleMode, int targetX = 0, int targetY = 0)
  105. {
  106. if (targetX == 0)
  107. targetX = graphics.GraphicsDevice.Viewport.Width;
  108. if (targetY == 0)
  109. targetY = graphics.GraphicsDevice.Viewport.Height;
  110. float h = targetX / Width;
  111. float v = targetY / Height;
  112. switch (scaleMode)
  113. {
  114. #pragma warning disable CS0162 // Unreachable code detected
  115. case ScaleMode.FitHorizontal:
  116. return new Vector2(h, h);
  117. case ScaleMode.FitVertical:
  118. return new Vector2(v, v);
  119. case ScaleMode.FitBoth:
  120. return (v * Width > targetX) ? new Vector2(h, h) : new Vector2(v, v);
  121. case ScaleMode.Stretch:
  122. default:
  123. return new Vector2(h, v);
  124. #pragma warning restore CS0162 // Unreachable code detected
  125. }
  126. }
  127. //original resolution I am working on, therefore if user scales it we need to propertially scale everything
  128. public const int PreferredViewportWidth = 1280;
  129. public const int PreferredViewportHeight = 720;
  130. public static GameTime gameTime;
  131. private static ushort prevmusic = 0;
  132. private static ushort currmusic = 0;
  133. /// <summary>
  134. /// Stores current savestate. When you save this is wrote. When you load this is replaced.
  135. /// </summary>
  136. private static Saves.Data _state = new Saves.Data();
  137. public static ushort MusicIndex
  138. {
  139. get
  140. {
  141. if (dicMusic.Count > 0)
  142. {
  143. while ((prevmusic > currmusic || prevmusic == ushort.MinValue && currmusic == ushort.MaxValue) &&
  144. !dicMusic.ContainsKey(currmusic))
  145. {
  146. if (dicMusic.Keys.Max() < currmusic)
  147. {
  148. currmusic = dicMusic.Keys.Max();
  149. }
  150. else
  151. {
  152. currmusic--;
  153. }
  154. }
  155. while (dicMusic.Count > 0 && prevmusic < currmusic && !dicMusic.ContainsKey(currmusic))
  156. {
  157. if (dicMusic.Keys.Max() < currmusic)
  158. {
  159. currmusic = dicMusic.Keys.Min();
  160. }
  161. else
  162. {
  163. currmusic++;
  164. }
  165. }
  166. return currmusic;
  167. }
  168. else return 0;
  169. }
  170. set
  171. {
  172. prevmusic = currmusic;
  173. currmusic = value;
  174. }
  175. }
  176. public static readonly Dictionary<ushort, List<string>> dicMusic = new Dictionary<ushort, List<string>>(); //ogg and sgt files have same 3 digit prefix.
  177. public static void SpriteBatchStartStencil(SamplerState ss = null) =>
  178. spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.Opaque, ss ?? SamplerState.PointClamp, graphics.GraphicsDevice.DepthStencilState);
  179. public static void SpriteBatchStart(BlendState bs = null, SamplerState ss = null) =>
  180. spriteBatch.Begin(SpriteSortMode.Deferred, bs ?? BlendState.AlphaBlend, ss ?? SamplerState.PointClamp, graphics.GraphicsDevice.DepthStencilState);
  181. public static void SpriteBatchStartAlpha(SpriteSortMode sortMode = SpriteSortMode.Deferred, SamplerState ss = null, Matrix? tm = null) =>
  182. spriteBatch.Begin(sortMode: sortMode, blendState: BlendState.AlphaBlend, samplerState: ss ?? SamplerState.PointClamp, transformMatrix: tm);
  183. public static void SpriteBatchEnd() => spriteBatch.End();
  184. public static readonly BlendState blendState_BasicAdd = new BlendState()
  185. {
  186. ColorSourceBlend = Blend.SourceColor,
  187. ColorDestinationBlend = Blend.DestinationColor,
  188. ColorBlendFunction = BlendFunction.Add,
  189. AlphaSourceBlend = Blend.SourceAlpha,
  190. AlphaDestinationBlend = Blend.DestinationAlpha,
  191. AlphaBlendFunction = BlendFunction.Add
  192. };
  193. /// <summary>
  194. /// subtract. Used for windows/glass makes color darker of things behind this layer.
  195. /// </summary>
  196. /// <see cref="http://community.monogame.net/t/solved-custom-blendstate-advice/11006"/>
  197. public static readonly BlendState blendState_Subtract = new BlendState
  198. {
  199. ColorWriteChannels = ColorWriteChannels.Blue|ColorWriteChannels.Green|ColorWriteChannels.Red,
  200. ColorSourceBlend = Blend.One,
  201. //AlphaSourceBlend = Blend.One,
  202. ColorDestinationBlend = Blend.One,
  203. //AlphaDestinationBlend = Blend.One,
  204. ColorBlendFunction = BlendFunction.ReverseSubtract
  205. };
  206. /// <summary>
  207. /// add. seems to work if colors are preblended like if they overlap the colors combined ahead of time. Used for light.
  208. /// </summary>
  209. /// <see cref="http://community.monogame.net/t/solved-custom-blendstate-advice/11006"/>
  210. public static readonly BlendState blendState_Add = new BlendState
  211. {
  212. ColorWriteChannels = ColorWriteChannels.Blue | ColorWriteChannels.Green | ColorWriteChannels.Red,
  213. ColorSourceBlend = Blend.One,
  214. //AlphaSourceBlend = Blend.One,
  215. ColorDestinationBlend = Blend.One,
  216. //AlphaDestinationBlend = Blend.One,
  217. ColorBlendFunction = BlendFunction.Add
  218. };
  219. /// <summary>
  220. /// untested add with blendfactor. You set the GraphicsDevice.BlendFactor before drawing.
  221. /// </summary>
  222. public static readonly BlendState blendState_Add_BlendFactor = new BlendState
  223. {
  224. ColorWriteChannels = ColorWriteChannels.Blue | ColorWriteChannels.Green | ColorWriteChannels.Red,
  225. ColorSourceBlend = Blend.BlendFactor,
  226. //AlphaSourceBlend = Blend.One,
  227. ColorDestinationBlend = Blend.One,
  228. //AlphaDestinationBlend = Blend.One,
  229. ColorBlendFunction = BlendFunction.Add
  230. };
  231. public static readonly BlendState blendState_forceDraw = new BlendState()
  232. {
  233. ColorSourceBlend = Blend.SourceColor,
  234. ColorDestinationBlend = Blend.SourceColor,
  235. ColorBlendFunction = BlendFunction.Add,
  236. AlphaSourceBlend = Blend.SourceAlpha,
  237. AlphaDestinationBlend = Blend.DestinationAlpha,
  238. AlphaBlendFunction = BlendFunction.Add,
  239. };
  240. private static MODULE module = MODULE.OVERTURE_DEBUG;
  241. public static string FF8DIR { get; private set; }
  242. public static string FF8DIRdata { get; private set; }
  243. public static string FF8DIRdata_lang { get; private set; }
  244. public static int InitTaskMethod(object obj)
  245. {
  246. CancellationToken token = (CancellationToken)obj;
  247. if (!token.IsCancellationRequested)
  248. Memory.Strings = new Strings();
  249. // requires strings because it uses an array generated in strings.
  250. // saves data will reference kernel_bin.
  251. if (!token.IsCancellationRequested)
  252. Kernel_Bin = new Kernel_bin();
  253. List<Task> tasks = new List<Task>();
  254. if (!token.IsCancellationRequested)
  255. {
  256. // this has a soft requirement on kernel_bin. It checks for null so should work without it.
  257. tasks.Add(Task.Run(() => { MItems = Items_In_Menu.Read(); }, token));
  258. //loads all savegames from steam2013 or cd2000 or steam2019 directories. first come first serve.
  259. //TODO allow chosing of which save folder to use.
  260. tasks.Add(Task.Run(Saves.Init, token));
  261. //tasks.Add(Task.Run(() => InitState = Saves.Data.LoadInitOut(), token));
  262. tasks.Add(Task.Run(InitStrings, token));
  263. if (graphics?.GraphicsDevice != null) // all below require graphics to work. to load textures graphics device needed.
  264. {
  265. //this initializes the fonts and drawing system- holds fonts in-memory
  266. tasks.Add(Task.Run(() => { font = new Font(); }, token));
  267. // card images in menu.
  268. tasks.Add(Task.Run(() => { Cards = Cards.Load(); }, token));
  269. tasks.Add(Task.Run(() => { Card_Game = new Card.Game(); }, token));
  270. tasks.Add(Task.Run(() => { Faces = Faces.Load(); }, token));
  271. tasks.Add(Task.Run(() => { Icons = Icons.Load(); }, token));
  272. tasks.Add(Task.Run(() => { Magazines = Magazine.Load(); }, token));
  273. }
  274. Task.WaitAll(tasks.ToArray());
  275. InitState = Saves.Data.LoadInitOut();
  276. State = InitState.Clone();
  277. if (graphics?.GraphicsDevice != null) // all below require graphics to work. to load textures graphics device needed.
  278. {
  279. //// requires font, faces, and icons. currently cards only used in debug menu. will
  280. //// have support for cards when added to menu.
  281. //if (!token.IsCancellationRequested)
  282. // Menu.Module.Init();
  283. // requires font, faces, and icons. currently cards only used in debug menu. will
  284. // have support for cards when added to menu.
  285. if (!token.IsCancellationRequested)
  286. Menu.InitStaticMembers();
  287. }
  288. }
  289. //EXE_Offsets test = new EXE_Offsets();
  290. Inited = true;
  291. return 0;
  292. }
  293. public static bool Inited { get; private set; } = false;
  294. public static bool IsMainThread => Thread.CurrentThread.ManagedThreadId == mainThreadID;
  295. public static ConcurrentQueue<Action> MainThreadOnlyActions;
  296. public static void Init(GraphicsDeviceManager graphics, SpriteBatch spriteBatch, ContentManager content)
  297. {
  298. Random = new Random((int)DateTime.Now.Ticks);
  299. mainThreadID = Thread.CurrentThread.ManagedThreadId;
  300. MainThreadOnlyActions = new ConcurrentQueue<Action>();
  301. FF8DIR = GameLocation.Current.DataPath;
  302. FF8DIRdata = Extended.GetUnixFullPath(Path.Combine(FF8DIR, "Data"));
  303. string testdir = Extended.GetUnixFullPath(Path.Combine(FF8DIRdata, $"lang-{Extended.GetLanguageShort()}"));
  304. FF8DIRdata_lang = Directory.Exists(testdir) ? testdir : FF8DIRdata;
  305. Memory.graphics = graphics;
  306. Memory.spriteBatch = spriteBatch;
  307. Memory.content = content;
  308. Memory.FieldHolder.FieldMemory = new int[1024];
  309. FF8StringReference.Init();
  310. TokenSource = new CancellationTokenSource();
  311. Token = TokenSource.Token;
  312. InitTask = new Task<int>(InitTaskMethod, Token);
  313. InitTask.Start();
  314. }
  315. /// <summary>
  316. /// If true by the end of Update() will skip the next Draw()
  317. /// </summary>
  318. public static bool SuppressDraw { get; set; }
  319. public static bool IsMouseVisible { get; set; } = false;
  320. public static Saves.Data PrevState { get; set; }
  321. public static Saves.Data State
  322. {
  323. get => _state; set
  324. {
  325. _state = value;
  326. _state.Loadtime = Memory.gameTime?.TotalGameTime ?? new TimeSpan();
  327. }
  328. }
  329. public static CancellationTokenSource TokenSource { get; private set; }
  330. public static CancellationToken Token { get; private set; }
  331. public static Items_In_Menu MItems { get; private set; }
  332. public static Magazine Magazines { get; private set; }
  333. public static Saves.Data InitState { get; private set; }
  334. public static event EventHandler<MODULE> ModuleChangeEvent;
  335. public static MODULE Module
  336. {
  337. get => module; set
  338. {
  339. if (module != value)
  340. {
  341. module = value;
  342. ModuleChangeEvent?.Invoke(null, value);
  343. }
  344. }
  345. }
  346. #region battleProvider
  347. /// <summary>
  348. /// Active battle encounter. Set by field or battle module. You shouldn't change it in-battle.
  349. /// </summary>
  350. public static int battle_encounter = 0;
  351. /// <summary>
  352. /// Battle music pointer. Set by SETBATTLEMUSIC in field module or by world module. Default=6
  353. /// </summary>
  354. public static int SetBattleMusic = 6;
  355. public static Init_debugger_battle.Encounter[] encounters;
  356. #endregion battleProvider
  357. #region MusicDataMidi
  358. public static Dictionary<ushort, string> Songssgt = new Dictionary<ushort, string>()
  359. {
  360. {0, "Lose" },
  361. {1, "Win" },
  362. {2, "Open" },
  363. {3, "Combat" },
  364. {4, "Run" },
  365. {5, "Battle" },
  366. {6, "Funsui" },
  367. {7, "End" },
  368. {8, "Antenna" },
  369. {9, "Waiting" },
  370. {10, "Ante " },
  371. {11, "Wind" },
  372. {12, "Crab" },
  373. {13, "Battle2" },
  374. {14, "Friend2" },
  375. {15, "Fuan2" },
  376. {16, "March2" },
  377. {17, "Land" },
  378. {18, "Julia" },
  379. {19, "Waltz" },
  380. {20, "Friend " },
  381. {21, "Dungeon" },
  382. {22, "Pianosolo" },
  383. {23, "Parade" },
  384. {24, "March1" },
  385. {25, "Secret" },
  386. {26, "Garden" },
  387. {27, "Fuan " },
  388. {28, "Polka2" },
  389. {29, "Anthem" },
  390. {30, "FlangChorus" },
  391. {31, "DubChorus" },
  392. {32, "SoloChorus" },
  393. {33, "FemaleChorus" },
  394. {34, "Chorus" },
  395. {35, "M7F5" },
  396. {36, "Sorceress" },
  397. {37, "Reet" },
  398. {38, "Soyo" },
  399. {39, "Rouka" },
  400. {40, "Night" },
  401. {41, "Field" },
  402. {42, "Guitar" },
  403. {43, "Concert" },
  404. {44, "Sea" },
  405. {45, "Silent" },
  406. {46, "Resistance" },
  407. {47, "Kaiso" },
  408. {48, "Horizon" },
  409. {49, "Master" },
  410. {50, "Battle2" },
  411. {51, "Rinoa" },
  412. {52, "Trabia" },
  413. {53, "Horizon2" },
  414. {54, "Truth" },
  415. {55, "Prison" },
  416. {56, "GalbadiaGarden" },
  417. {57, "Timber" },
  418. {58, "Galbadia " },
  419. {59, "Pinchi" },
  420. {60, "Scene1" },
  421. {61, "Pub" },
  422. {62, "Bat3" },
  423. {63, "Stage" },
  424. {64, "Choco" },
  425. {65, "White" },
  426. {66, "Majomv" },
  427. {67, "Musho" },
  428. {68, "Missile" },
  429. {69, "Speech" },
  430. {70, "Card" },
  431. {71, "Gomon" },
  432. {72, "Soto" },
  433. {73, "Majobat" },
  434. {74, "Train" },
  435. {75, "Garden2" },
  436. {76, "Bossbat2" },
  437. {77, "LastDungeon" },
  438. {78, "Gafly" },
  439. {79, "Demo" },
  440. {80, "Spy" },
  441. {81, "VoiceDeChocobo" },
  442. {82, "Salt" },
  443. {83, "Alien" },
  444. {84, "Sekichu" },
  445. {85, "Esta" },
  446. {86, "Moonmv" },
  447. {87, "Mdmotor" },
  448. {88, "Moonmv2" },
  449. {89, "Fly" },
  450. {90, "BossBat1" },
  451. {91, "Rag1" },
  452. {92, "Rag2" },
  453. {93, "LastBoss" },
  454. {94, "Lastwhite" },
  455. {95, "Lasbl" },
  456. {96, "Keisho" },
  457. {97, "Compression" },
  458. };
  459. #endregion MusicDataMidi
  460. #region MusicDataOGG
  461. public static Dictionary<ushort, FF8String> Songsogg;
  462. private static void InitStrings()
  463. {
  464. Songsogg = new Dictionary<ushort, FF8String>()
  465. {
  466. {0,"Lose" },
  467. {1,"The Winner" },
  468. {4,"Never Look Back" },
  469. {5,"Don't Be Afraid" },
  470. {7,"Dead End" },
  471. {8,"Starting Up" },
  472. {9,"Intruders" },
  473. {12,"Don't Be Afraid (X-ATM092)" },
  474. {13,"Force Your Way" },
  475. {14,"FITHOS LUSEC WECOS VINOSEC (No Intro)" },
  476. {15,"Unrest" },
  477. {16,"The Stage is Set" },
  478. {17,"The Landing" },
  479. {18,"Love Grows" },
  480. {19,"Waltz for the Moon" },
  481. {20,"Ami" },
  482. {21,"Find Your Way" },
  483. {22,"Julia" },
  484. {23,"FITHOS LUSEC WECOS VINOSEC" },
  485. {24,"SeeD" },
  486. {25,"Tell Me" },
  487. {26,"Balamb GARDEN" },
  488. {27,"Fear" },
  489. {28,"Dance with the Balamb-Fish" },
  490. {29,"Cactus Jack" },
  491. {35,"The Mission" },
  492. {36,"SUCCESSION OF WITCHES" },
  493. {41,"Blue Fields" },
  494. {42,"Breezy" },
  495. {43,"Concert" },
  496. {46,"Timber Owls" },
  497. {47,"Fragments of Memories" },
  498. {48,"Fisherman's Horizon" },
  499. {49,"Heresy" },
  500. {51,"My Mind" },
  501. {52,"Where I Belong" },
  502. {53,"Starting Up (Looped)" },
  503. {54,"Truth" },
  504. {55,"Trust Me" },
  505. {56,"Galbadia GARDEN" },
  506. {57,"Martial Law" },
  507. {58,"Under Her Control" },
  508. {59,"Only a Plank Between One and Perdition" },
  509. {60,"Junction" },
  510. {61,"Roses and Wine" },
  511. {62,"The Man with the Machine Gun" },
  512. {63,"A Sacrifice" },
  513. {64,"ODEKA ke Chocobo" },
  514. {65,"Drifting" },
  515. {66,"Wounded" },
  516. {67,"Jailed" },
  517. {68,"Retaliation" },
  518. {69,"The Oath" },
  519. {70,"Shuffle or Boogie" },
  520. {71,"Rivals" },
  521. {72,"Blue Sky" },
  522. {73,"Premonition" },
  523. {75,"Galbadia GARDEN (No Intro)" },
  524. {76,"Maybe I'm a Lion" },
  525. {77,"The Castle" },
  526. {78,"Movin'" },
  527. {79,"Overture" },
  528. {80,"The Spy" },
  529. {81,"Mods de Chocobo" },
  530. {82,"The Salt Flats" },
  531. {83,"The Residents" },
  532. {84,"Lunatic Pandora" },
  533. {85,"Silence and Motion" },
  534. {86,"Tears of the Moon" },
  535. {88,"Tears of the Moon (Alternate)" },
  536. {89,"Ride On" },
  537. {90,"The Legendary Beast" },
  538. {91,"Slide Show Part 1" },
  539. {92,"Slide Show Part 2" },
  540. {93,"The Extreme" },
  541. {96,"The Successor" },
  542. {97,"Compression of Time" },
  543. {99,"The Landing (No Intro)" },
  544. {512,"The Loser" },
  545. {513,"Eyes on Me" },
  546. {514,"Irish Jig (Concert)" },
  547. {515,"Eyes on Me (Concert)" },
  548. {516,"Movin' (No Intro)" },
  549. {517,"The Landing (Alternate)" },
  550. {518,"The Landing (Alternate - No Intro)" },
  551. {519,"Galbadia GARDEN (Alternate)" },
  552. };
  553. DrawPointMagic = new Dictionary<byte, FF8String>()
  554. {
  555. {0, "Cure - Balamb Garden courtyard"},
  556. {1, "Blizzard - Balamb Garden training center"},
  557. {2, "Full-Life - Balamb Garden MD level"},
  558. {3, "Esuna - Balamb Garden library next to the book shelf"},
  559. {4, "Demi - Balamb Garden cafeteria (only during Garden Riot)"},
  560. {5, "Bio - Balamb Garden B2 floor"},
  561. {6, "Thunder - Balamb outside junk shop"},
  562. {7, "Cure - Balamb harbor"},
  563. {8, "Fire - Fire Cavern"},
  564. {9, "Silence - Dollet town square"},
  565. {10, "Blind - Dollet Communications Tower"},
  566. {11, "Scan - Timber Pub Aurora back alley"},
  567. {12, "Cure - Timber outside the pub"},
  568. {13, "Blizzaga - Timber Maniacs Building left room"},
  569. {14, "Haste - Galbadia Garden lobby"},
  570. {15, "Life - Galbadia Garden changing rooms"},
  571. {16, "Shell - Galbadia Garden courtyard"},
  572. {17, "Protect - Galbadia Garden ice rink"},
  573. {18, "Double - Galbadia Garden auditorium"},
  574. {19, "Aura - Outside Galbadia Garden during Garden war"},
  575. {20, "Cure - Timber forests in a Laguna dream"},
  576. {21, "Water - Timber forests in a Laguna dream"},
  577. {22, "Thundara - Deling City park"},
  578. {23, "Zombie - Deling City Sewers"},
  579. {24, "Esuna - Deling City Sewers"},
  580. {25, "Bio - Deling City Sewers"},
  581. {26, "Fira"},
  582. {27, "Berserk - D-District Prison Floor 9 - right cell"},
  583. {28, "Thundaga - D-District Prison Floor 11 - right cell"},
  584. {29, "Aero - Outside D-District Prison"},
  585. {30, "Blizzara - Missile Base - control room"},
  586. {31, "Blind - Missile Base room with G-Soldiers who ask to deliver a message"},
  587. {32, "Full-Life - Missile Base - silo room"},
  588. {33, "Drain - Winhill road south from town square"},
  589. {34, "Dispel - Winhill town square"},
  590. {35, "Curaga - Winhill Laguna's room in the dream"},
  591. {36, "Reflect - Winhill east road"},
  592. {37, "Protect - Tomb of the Unknown King - outside"},
  593. {38, "Float - Tomb of the Unknown King - north room"},
  594. {39, "Cura - Tomb of the Unknown King - east room"},
  595. {40, "Haste - Fishermans Horizon abandoned train station"},
  596. {41, "Shell - Fishermans Horizon junk shop"},
  597. {42, "Regen - Fishermans Horizon overlooking the sun panel"},
  598. {43, "Full-Life - Fishermans Horizon Master Fisherman's fishing spot"},
  599. {44, "Ultima - Fishermans Horizon mayor's house"},
  600. {45, "Thundaga - Great Salt Lake past the dinosaur skeleton"},
  601. {46, "Meteor - Great Salt Lake dinosaur skeleton"},
  602. {47, "Curaga - Esthar city streets near city entrance"},
  603. {48, "Blizzard - Esthar outside palace"},
  604. {49, "Quake - Esthar outside Odine's Lab"},
  605. {50, "Tornado - Esthar shopping mall"},
  606. {51, "Double - Esthar Odine's Lab in a Laguna dream"},
  607. {52, "Pain"},
  608. {53, "Flare - Esthar Odine's Lab in a Laguna dream"},
  609. {54, "Stop - Sorceress Memorial"},
  610. {55, "Stop"},
  611. {56, "Life - Tears' Point entrance"},
  612. {57, "Reflect - Tears' Point middle"},
  613. {58, "Death - Lunatic Pandora Laboratory in a Laguna dream"},
  614. {59, "Holy - Lunatic Pandora near Elevator #1"},
  615. {60, "Silence - Lunatic Pandora"},
  616. {61, "Ultima - Lunatic Pandora"},
  617. {62, "Confuse"},
  618. {63, "Break - Lunatic Pandora on the way to fight Adel"},
  619. {64, "Meteor - Lunatic Pandora entrance"},
  620. {65, "Curaga - Lunatic Pandora elevator room"},
  621. {66, "Slow"},
  622. {67, "Curaga - Edea's Orphanage"},
  623. {68, "Flare"},
  624. {69, "Holy"},
  625. {70, "Sleep - Centra Excavation Site"},
  626. {71, "Confuse - Centra Excavation Site"},
  627. {72, "Aero - Centra Ruins right ladder after the lift"},
  628. {73, "Drain - Centra Ruins platform after the first staircase"},
  629. {74, "Pain - Centra Ruins next to the dome"},
  630. {75, "Thundaga - Trabia Garden in front of the statue"},
  631. {76, "Zombie - Trabia Garden cemetery"},
  632. {77, "Aura - Trabia Garden stage"},
  633. {78, "Ultima - Shumi Village - above ground"},
  634. {79, "Blizzaga - Shumi Village - outside elder's house"},
  635. {80, "Firaga - Shumi Village workshop"},
  636. {81, "Tornado"},
  637. {82, "Holy - White SeeD Ship"},
  638. {83, "Cura - Ragnarok room with a red Propagator"},
  639. {84, "Life - Ragnarok hangar upstairs"},
  640. {85, "Full-Life - Ragnarok room with save point"},
  641. {86, "Dispel - Deep Sea Research Center second level"},
  642. {87, "Esuna - Deep Sea Research Center secret room"},
  643. {88, "Triple - Deep Sea Research Center third screen on the way to Ultima Weapon's lair"},
  644. {89, "Ultima - Deep Sea Research Center fifth screen on the way to Ultima Weapon's lair"},
  645. {90, "Meltdown - Lunar Base room before the escape pods"},
  646. {91, "Meteor - Lunar Base Ellone's room"},
  647. {92, "Haste"},
  648. {93, "Slow"},
  649. {94, "Curaga"},
  650. {95, "Life"},
  651. {96, "Stop"},
  652. {97, "Regen"},
  653. {98, "Double"},
  654. {99, "Triple"},
  655. {100, "Flare - Ultimecia Castle outside"},
  656. {101, "Curaga - Ultimecia Castle storage room"},
  657. {102, "Cura - Ultimecia Castle passageway"},
  658. {103, "Scan"},
  659. {104, "Esuna"},
  660. {105, "Slow - Ultimecia Castle courtyard"},
  661. {106, "Dispel - Ultimecia Castle chapel"},
  662. {107, "Stop - Ultimecia Castle clock tower"},
  663. {108, "Life"},
  664. {109, "Flare"},
  665. {110, "Aura - Ultimecia Castle wine cellar"},
  666. {111, "Holy - Ultimecia Castle treasure room"},
  667. {112, "Meteor"},
  668. {113, "Meltdown - Ultimecia Castle art gallery"},
  669. {114, "Ultima - Ultimecia Castle armory"},
  670. {115, "Full-Life - Ultimecia Castle prison"},
  671. {116, "Triple"},
  672. {117, "Fire"},
  673. {118, "Fire"},
  674. {119, "Fire"},
  675. {120, "Fire"},
  676. {121, "Fire"},
  677. {122, "Fire"},
  678. {123, "Fire"},
  679. {124, "Fire"},
  680. {125, "Fire"},
  681. {126, "Fire"},
  682. {127, "Fire"},
  683. {128, "Cure"},
  684. {129, "Esuna"},
  685. {130, "Thunder"},
  686. {131, "Fira"},
  687. {132, "Thundara"},
  688. {133, "Blizzara"},
  689. {134, "Blizzard"},
  690. {135, "Fire"},
  691. {136, "Cure"},
  692. {137, "Water"},
  693. {138, "Cura"},
  694. {139, "Esuna"},
  695. {140, "Scan"},
  696. {141, "Shell"},
  697. {142, "Haste"},
  698. {143, "Aero"},
  699. {144, "Bio"},
  700. {145, "Life"},
  701. {146, "Demi"},
  702. {147, "Protect"},
  703. {148, "Holy"},
  704. {149, "Thundaga"},
  705. {150, "Stop"},
  706. {151, "Firaga"},
  707. {152, "Regen"},
  708. {153, "Blizzaga"},
  709. {154, "Confuse"},
  710. {155, "Flare"},
  711. {156, "Dispel"},
  712. {157, "Slow"},
  713. {158, "Quake"},
  714. {159, "Curaga"},
  715. {160, "Tornado"},
  716. {161, "Full-Life"},
  717. {162, "Reflect"},
  718. {163, "Aura"},
  719. {164, "Quake"},
  720. {165, "Double"},
  721. {166, "Break"},
  722. {167, "Meteor"},
  723. {168, "Ultima"},
  724. {169, "Triple"},
  725. {170, "Confuse"},
  726. {171, "Blind"},
  727. {172, "Quake"},
  728. {173, "Sleep"},
  729. {174, "Silence"},
  730. {175, "Flare"},
  731. {176, "Death"},
  732. {177, "Drain"},
  733. {178, "Pain"},
  734. {179, "Berserk"},
  735. {180, "Float"},
  736. {181, "Zombie"},
  737. {182, "Meltdown"},
  738. {183, "Ultima"},
  739. {184, "Tornado"},
  740. {185, "Quake"},
  741. {186, "Meteor"},
  742. {187, "Holy"},
  743. {188, "Flare"},
  744. {189, "Aura"},
  745. {190, "Ultima"},
  746. {191, "Triple"},
  747. {192, "Full-Life"},
  748. {193, "Tornado"},
  749. {194, "Quake"},
  750. {195, "Meteor"},
  751. {196, "Holy"},
  752. {197, "Flare"},
  753. {198, "Aura"},
  754. {199, "Ultima"},
  755. {200, "Triple"},
  756. {201, "Full-Life"},
  757. {202, "Tornado"},
  758. {203, "Quake"},
  759. {204, "Meteor"},
  760. {205, "Holy"},
  761. {206, "Flare"},
  762. {207, "Aura"},
  763. {208, "Ultima"},
  764. {209, "Triple"},
  765. {210, "Full-Life"},
  766. {211, "Ultima"},
  767. {212, "Meteor"},
  768. {213, "Holy"},
  769. {214, "Flare"},
  770. {215, "Aura"},
  771. {216, "Ultima"},
  772. {217, "Triple"},
  773. {218, "Full-Life"},
  774. {219, "Meteor"},
  775. {220, "Holy"},
  776. {221, "Triple"},
  777. {222, "Aura"},
  778. {223, "Ultima"},
  779. {224, "Triple"},
  780. {225, "Full-Life"},
  781. {226, "Meteor"},
  782. {227, "Holy"},
  783. {228, "Flare"},
  784. {229, "Aura"},
  785. {230, "Ultima"},
  786. {231, "Triple"},
  787. {232, "Full-Life"},
  788. {233, "Meteor"},
  789. {234, "Triple"},
  790. {235, "Flare"},
  791. {236, "Aura"},
  792. {237, "Ultima"},
  793. {238, "Triple"},
  794. {239, "Full-Life"},
  795. {240, "Meteor"},
  796. {241, "Holy"},
  797. {242, "Flare"},
  798. {243, "Aura"},
  799. {244, "Ultima"},
  800. {245, "Blizzard"},
  801. {246, "Cure"},
  802. {247, "Dispel"},
  803. {248, "Confuse"},
  804. {249, "Meteor"},
  805. {250, "Double"},
  806. {251, "Aura"},
  807. {252, "Holy"},
  808. {253, "Flare"},
  809. {254, "Ultima"},
  810. {255, "Scan"}
  811. };
  812. }
  813. #endregion MusicDataOGG
  814. #region DrawPointMagic
  815. public static Dictionary<byte, FF8String> DrawPointMagic;
  816. public static Input2 Input2;
  817. /// <summary>
  818. /// Random number generator seeded with time.
  819. /// </summary>
  820. /// <remarks>creates global random class for all sort of things</remarks>
  821. public static Random Random = null;
  822. public static int Year = 2013; // need to dynamicly detect if 2000/2013/2019, maybe need 2000 1.2 as well.
  823. #endregion DrawPointMagic
  824. public static void Update()
  825. {
  826. Action a = null;
  827. while (IsMainThread && (MainThreadOnlyActions?.TryDequeue(out a) ?? false))
  828. { a.Invoke(); }
  829. for (int i = 0; IsMainThread && i < LeftOverTask.Count; i++)
  830. {
  831. if (LeftOverTask[i].IsCompleted)
  832. {
  833. LeftOverTask[i].Dispose();
  834. LeftOverTask.RemoveAt(i--);
  835. }
  836. }
  837. }
  838. public static class FieldHolder
  839. {
  840. //public static string[] MapList;
  841. public static ushort FieldID = 263;
  842. public static string[] fields;
  843. public static int[] FieldMemory;
  844. public static string GetString() => fields?.ElementAtOrDefault(FieldID);
  845. }
  846. }
  847. }