module_field_debug.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. using Microsoft.Xna.Framework.Graphics;
  2. using System.Collections.Generic;
  3. using System;
  4. using System.Linq;
  5. using Microsoft.Xna.Framework;
  6. using System.Diagnostics;
  7. using System.IO;
  8. namespace FF8
  9. {
  10. public static class Module_field_debug
  11. {
  12. private static Field_mods mod = 0;
  13. private static Texture2D tex;
  14. private static Texture2D texOverlap;
  15. private static EventEngine eventEngine;
  16. private static IServices services;
  17. private static List<Tile> tiles;
  18. private struct Tile
  19. {
  20. public short x, y;
  21. public ushort z;
  22. public byte texID; // 4 bits
  23. public byte pallID; //[6-10]
  24. public byte srcx, srcy;
  25. public byte layId;
  26. public byte blendType;
  27. public byte state;
  28. public byte parameter;
  29. public byte blend1;
  30. public byte blend2;
  31. }
  32. private static int width, height;
  33. private enum Field_mods
  34. {
  35. INIT,
  36. DEBUGRENDER
  37. };
  38. public static void Draw()
  39. {
  40. switch (mod)
  41. {
  42. case Field_mods.INIT:
  43. break; //null
  44. case Field_mods.DEBUGRENDER:
  45. DrawDebug();
  46. break;
  47. }
  48. }
  49. public static void ResetField()
  50. {
  51. mod = Field_mods.INIT;
  52. }
  53. private static void DrawDebug()
  54. {
  55. Memory.graphics.GraphicsDevice.Clear(Color.Black);
  56. Memory.SpriteBatchStartStencil();
  57. Rectangle src = new Rectangle(0, 0, tex.Width, tex.Height);
  58. Rectangle dst = src;
  59. dst.Size = (dst.Size.ToVector2() * Memory.Scale(tex.Width, tex.Height)).ToPoint();
  60. //In game I think we'd keep the field from leaving the screen edge but would center on the Squall and the party when it can.
  61. //I setup scaling after noticing the field didn't size with the screen. I set it to center on screen.
  62. dst.Offset(Memory.Center.X - dst.Center.X, Memory.Center.Y - dst.Center.Y);
  63. Memory.spriteBatch.Draw(tex,dst, src, Color.White);
  64. //new Microsoft.Xna.Framework.Rectangle(0, 0, 1280 + (width - 320), 720 + (height - 224)),
  65. //new Microsoft.Xna.Framework.Rectangle(0, 0, tex.Width, tex.Height)
  66. Memory.SpriteBatchEnd();
  67. }
  68. public static void Update()
  69. {
  70. #if DEBUG
  71. // lets you move through all the feilds just holding left or right. it will just loop when it runs out.
  72. if (Input.Button(Buttons.Left) )
  73. {
  74. Input.ResetInputLimit();
  75. init_debugger_Audio.PlaySound(0);
  76. Module_main_menu_debug.FieldPointer--;
  77. ResetField();
  78. }
  79. if (Input.Button(Buttons.Right) )
  80. {
  81. Input.ResetInputLimit();
  82. init_debugger_Audio.PlaySound(0);
  83. Module_main_menu_debug.FieldPointer++;
  84. ResetField();
  85. }
  86. #endif
  87. switch (mod)
  88. {
  89. case Field_mods.INIT:
  90. Init();
  91. break;
  92. case Field_mods.DEBUGRENDER:
  93. UpdateScript();
  94. break; //await events here
  95. }
  96. }
  97. private static void UpdateScript()
  98. {
  99. //We do not know every instruction and it's not possible for now to play field with unknown instruction
  100. //eventEngine.Update(services);
  101. }
  102. private static void Init()
  103. {
  104. ArchiveWorker aw = new ArchiveWorker(Memory.Archives.A_FIELD);
  105. string[] test = aw.GetListOfFiles();
  106. //TODO fix endless look on FieldID 50.
  107. if (Memory.FieldHolder.FieldID >= Memory.FieldHolder.fields.Length ||
  108. Memory.FieldHolder.FieldID < 0)
  109. return;
  110. var CollectionEntry = test.Where(x => x.ToLower().Contains(Memory.FieldHolder.fields[Memory.FieldHolder.FieldID]));
  111. if (!CollectionEntry.Any()) return;
  112. string fieldArchive = CollectionEntry.First();
  113. int fieldLen = fieldArchive.Length - 2;
  114. fieldArchive = fieldArchive.Substring(0, fieldLen);
  115. byte[] fs = aw.GetBinaryFile( $"{fieldArchive}fs");
  116. byte[] fi = aw.GetBinaryFile( $"{fieldArchive}fi");
  117. byte[] fl = aw.GetBinaryFile( $"{fieldArchive}fl");
  118. if (fs == null || fi == null || fl == null) return;
  119. string[] test_ = aw.GetBinaryFileList(fl);
  120. string mim = null;
  121. string map = null;
  122. try
  123. {
  124. mim = test_.First(x => x.ToLower().Contains(".mim"));
  125. }
  126. catch{}
  127. try
  128. {
  129. map = test_.First(x => x.ToLower().Contains(".map"));
  130. }
  131. catch{}
  132. if (mim != null && map != null)
  133. {
  134. byte[] mimb = aw.FileInTwoArchives(fi, fs, fl, mim);
  135. byte[] mapb = aw.FileInTwoArchives(fi, fs, fl, map);
  136. ParseBackground(mimb, mapb);
  137. }
  138. //let's start with scripts
  139. byte[] jsm = null;
  140. byte[] sy = null;
  141. string s_jsm = null;
  142. string s_sy = null;
  143. try
  144. {
  145. s_jsm = test_.First(x => x.ToLower().Contains(".jsm"));
  146. }
  147. catch { }
  148. try
  149. {
  150. s_sy = test_.First(x => x.ToLower().Contains(".sy"));
  151. }
  152. catch { }
  153. if (s_jsm != null && s_sy != null)
  154. {
  155. jsm = aw.FileInTwoArchives(fi, fs, fl, s_jsm);
  156. sy = aw.FileInTwoArchives(fi, fs, fl, s_sy);
  157. }
  158. else return; // one or both values are null
  159. List<Jsm.GameObject> jsmObjects = Jsm.File.Read(jsm);
  160. if (sy == null)
  161. return;
  162. Sym.GameObjects symObjects = Sym.Reader.FromBytes(sy);
  163. services = FieldInitializer.GetServices();
  164. eventEngine = ServiceId.Field[services].Engine;
  165. eventEngine.Reset();
  166. for (var objIndex = 0; objIndex < jsmObjects.Count; objIndex++)
  167. {
  168. Jsm.GameObject obj = jsmObjects[objIndex];
  169. FieldObject fieldObject = new FieldObject(obj.Id, symObjects.GetObjectOrDefault(objIndex).Name);
  170. foreach (Jsm.GameScript script in obj.Scripts)
  171. fieldObject.Scripts.Add(script.ScriptId, script.Segment.GetExecuter());
  172. eventEngine.RegisterObject(fieldObject);
  173. }
  174. //string mch = test_.Where(x => x.ToLower().Contains(".mch")).First();
  175. //string one = test_.Where(x => x.ToLower().Contains(".one")).First();
  176. //string msd = test_.Where(x => x.ToLower().Contains(".msd")).First();
  177. //string inf = test_.Where(x => x.ToLower().Contains(".inf")).First();
  178. //string id = test_.Where(x => x.ToLower().Contains(".id")).First();
  179. //string ca = test_.Where(x => x.ToLower().Contains(".ca")).First();
  180. //string tdw = test_.Where(x => x.ToLower().Contains(".tdw")).First();
  181. //string msk = test_.Where(x => x.ToLower().Contains(".msk")).First();
  182. //string rat = test_.Where(x => x.ToLower().Contains(".rat")).First();
  183. //string pmd = test_.Where(x => x.ToLower().Contains(".pmd")).First();
  184. //string sfx = test_.Where(x => x.ToLower().Contains(".sfx")).First();
  185. //byte[] mchb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, mch); //Field character models
  186. //byte[] oneb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, one); //Field character models container
  187. //byte[] msdb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, msd); //dialogs
  188. //byte[] infb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, inf); //gateways
  189. //byte[] idb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, id); //walkmesh
  190. //byte[] cab = ArchiveWorker.FileInTwoArchives(fi, fs, fl, ca); //camera
  191. //byte[] tdwb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, tdw); //extra font
  192. //byte[] mskb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, msk); //movie cam
  193. //byte[] ratb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, rat); //battle on field
  194. //byte[] pmdb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, pmd); //particle info
  195. //byte[] sfxb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, sfx); //sound effects
  196. mod++;
  197. return;
  198. }
  199. private static void ParseBackground(byte[] mimb, byte[] mapb)
  200. {
  201. if (mimb == null || mapb == null)
  202. return;
  203. int type1Width = 1664;
  204. tiles = new List<Tile>();
  205. int palletes = 24;
  206. //128x256
  207. PseudoBufferedStream pbsmap = new PseudoBufferedStream(mapb);
  208. PseudoBufferedStream pbsmim = new PseudoBufferedStream(mimb);
  209. while (pbsmap.Tell() + 16 < pbsmap.Length)
  210. {
  211. Tile tile = new Tile { x = pbsmap.ReadShort() };
  212. if (tile.x == 0x7FFF)
  213. break;
  214. tile.y = pbsmap.ReadShort();
  215. tile.z = pbsmap.ReadUShort();// (ushort)(4096 - pbsmap.ReadUShort());
  216. byte texIdBuffer = pbsmap.ReadByte();
  217. tile.texID = (byte)(texIdBuffer & 0xF);
  218. pbsmap.Seek(1, SeekOrigin.Current);
  219. //short testz = pbsmap.ReadShort();
  220. //testz = (short)(testz >> 6);
  221. //testz &= 0xF;
  222. tile.pallID = (byte)((pbsmap.ReadShort() >> 6) & 0xF);
  223. tile.srcx = pbsmap.ReadByte();
  224. tile.srcy = pbsmap.ReadByte();
  225. tile.layId = (byte)(pbsmap.ReadByte() & 0x7F);
  226. tile.blendType = pbsmap.ReadByte();
  227. tile.parameter = pbsmap.ReadByte();
  228. tile.state = pbsmap.ReadByte();
  229. tile.blend1 = (byte)((texIdBuffer >> 4) & 0x1);
  230. tile.blend2 = (byte)(texIdBuffer >> 5);
  231. tiles.Add(tile);
  232. //srcY = srcX == texID * 128 + srcX;
  233. }
  234. int lowestY = tiles.Min(x => x.y);
  235. int maximumY = tiles.Max(x => x.y);
  236. int lowestX = tiles.Min(x => x.x); //-160;
  237. int maximumX = tiles.Max(x => x.x);
  238. height = Math.Abs(lowestY) + maximumY + 16; //224
  239. width = Math.Abs(lowestX) + maximumX + 16; //320
  240. byte[] finalImage = new byte[height * width * 4]; //ARGB;
  241. byte[] finalOverlapImage = new byte[height * width * 4];
  242. tex = new Texture2D(Memory.graphics.GraphicsDevice, width, height);
  243. texOverlap = new Texture2D(Memory.graphics.GraphicsDevice, width, height);
  244. var MaximumLayer = tiles.Max(x => x.layId);
  245. var MinimumLayer = tiles.Min(x => x.layId);
  246. List<ushort> BufferDepth = tiles.GroupBy(x => x.z).Select(group => group.First()).Select(x => x.z).ToList();
  247. BufferDepth.Sort();
  248. for (int LayerId = 1; LayerId <= MaximumLayer + 1; LayerId++)
  249. {
  250. foreach (Tile tile in tiles)
  251. {
  252. if (LayerId != MaximumLayer + 1)
  253. {
  254. if (tile.layId != LayerId)
  255. continue;
  256. //if (tile.z != BufferDepth[LayerId])
  257. // continue;
  258. }
  259. else
  260. if (tile.layId != 0)
  261. continue;
  262. int palettePointer = 4096 + ((tile.pallID) * 512);
  263. int sourceImagePointer = 512 * palletes;
  264. int realX = Math.Abs(lowestX) + tile.x; //baseX
  265. int realY = Math.Abs(lowestY) + tile.y; //*width
  266. int realDestinationPixel = ((realY * width) + realX) * 4;
  267. if (tile.blend2 >= 4)
  268. {
  269. int startPixel = sourceImagePointer + tile.srcx + 128 * tile.texID + (type1Width * tile.srcy);
  270. for (int y = 0; y < 16; y++)
  271. for (int x = 0; x < 16; x++)
  272. {
  273. byte pixel = mimb[startPixel + x + (y * 1664)];
  274. ushort pixels = BitConverter.ToUInt16(mimb, 2 * pixel + palettePointer);
  275. if (pixels == 00)
  276. continue;
  277. byte red = (byte)((pixels) & 0x1F);
  278. byte green = (byte)((pixels >> 5) & 0x1F);
  279. byte blue = (byte)((pixels >> 10) & 0x1F);
  280. red = (byte)MathHelper.Clamp((red * 8), 0, 255);
  281. green = (byte)MathHelper.Clamp((green * 8), 0, 255);
  282. blue = (byte)MathHelper.Clamp((blue * 8), 0, 255);
  283. if (tile.blendType < 4)
  284. {
  285. if (true)//!bSaveToOverlapBuffer)
  286. {
  287. byte baseColorR = finalImage[realDestinationPixel + (x * 4) + (y * width * 4)];
  288. byte baseColorG = finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1];
  289. byte baseColorB = finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2];
  290. Blend(baseColorR, baseColorG, baseColorB, red, green, blue, tile, finalImage, realDestinationPixel, x, y);
  291. }
  292. else
  293. {
  294. byte baseColorR = finalOverlapImage[realDestinationPixel + (x * 4) + (y * width * 4)];
  295. byte baseColorG = finalOverlapImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1];
  296. byte baseColorB = finalOverlapImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2];
  297. Blend(baseColorR, baseColorG, baseColorB, red, green, blue, tile, finalOverlapImage, realDestinationPixel, x, y);
  298. }
  299. }
  300. else
  301. {
  302. if (true)//!bSaveToOverlapBuffer)
  303. {
  304. finalImage[realDestinationPixel + (x * 4) + (y * width * 4)] = red;
  305. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1] = green;
  306. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2] = blue;
  307. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 3] = 0xFF;
  308. }
  309. else
  310. {
  311. finalOverlapImage[realDestinationPixel + (x * 4) + (y * width * 4)] = red;
  312. finalOverlapImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1] = green;
  313. finalOverlapImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2] = blue;
  314. finalOverlapImage[realDestinationPixel + (x * 4) + (y * width * 4) + 3] = 0xFF;
  315. }
  316. }
  317. }
  318. }
  319. else
  320. {
  321. // int startPixel = sourceImagePointer + tile.srcx / 2 + 128 * tile.texID + (type1Width * tile.srcy);
  322. // for (int y = 0; y < 16; y++)
  323. // for (int x = 0; x < 16; x++)
  324. // {
  325. // byte index = mimb[startPixel + x + (y * 1664)];
  326. // ushort pixels = BitConverter.ToUInt16(mimb, 2 * (index & 0xF) + palettePointer);
  327. // byte red = (byte)((pixels) & 0x1F);
  328. // byte green = (byte)((pixels >> 5) & 0x1F);
  329. // byte blue = (byte)((pixels >> 10) & 0x1F);
  330. // red = (byte)MathHelper.Clamp((red * 8), 0, 255);
  331. // green = (byte)MathHelper.Clamp((green * 8), 0, 255);
  332. // blue = (byte)MathHelper.Clamp((blue * 8), 0, 255);
  333. // if (pixels != 0)
  334. // {
  335. // if (tile.blendType < 4)
  336. // {
  337. // byte baseColorR = finalImage[realDestinationPixel + (x * 4) + (y * width * 4)];
  338. // byte baseColorG = finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1];
  339. // byte baseColorB = finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2];
  340. // Blend(baseColorR, baseColorG, baseColorB, red, green, blue, tile, finalImage, realDestinationPixel, x, y);
  341. // }
  342. // }
  343. // pixels = BitConverter.ToUInt16(mimb, 2 * (index >> 4) + palettePointer);
  344. // red = (byte)((pixels) & 0x1F);
  345. // green = (byte)((pixels >> 5) & 0x1F);
  346. // blue = (byte)((pixels >> 10) & 0x1F);
  347. // red = (byte)MathHelper.Clamp((red * 8), 0, 255);
  348. // green = (byte)MathHelper.Clamp((green * 8), 0, 255);
  349. // blue = (byte)MathHelper.Clamp((blue * 8), 0, 255);
  350. // if (pixels != 0)
  351. // {
  352. // if (tile.blendType < 4)
  353. // {
  354. // byte baseColorR = finalImage[realDestinationPixel + (x * 4) + (y * width * 4)];
  355. // byte baseColorG = finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1];
  356. // byte baseColorB = finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2];
  357. // Blend(baseColorR, baseColorG, baseColorB, red, green, blue, tile, finalImage, realDestinationPixel, x, y);
  358. // }
  359. // }
  360. // else
  361. // {
  362. // finalImage[realDestinationPixel + (x * 4) + (y * width * 4)] = red;
  363. // finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1] = green;
  364. // finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2] = blue;
  365. // finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 3] = 0xFF;
  366. // }
  367. // }
  368. }
  369. }
  370. }
  371. tex.SetData(finalImage);
  372. texOverlap.SetData(finalOverlapImage);
  373. }
  374. private static void DrawEntities()
  375. {
  376. throw new NotImplementedException();
  377. }
  378. private static void Blend(byte baseColorR, byte baseColorG, byte baseColorB, byte red, byte green, byte blue, Tile tile, byte[] finalImage, int realDestinationPixel, int x, int y)
  379. {
  380. switch (tile.blendType)
  381. {
  382. case 0:
  383. finalImage[realDestinationPixel + (x * 4) + (y * width * 4)] = (byte)((baseColorR + red) / 2);
  384. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1] = (byte)((baseColorG + green) / 2);
  385. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2] = (byte)((baseColorB + blue) / 2);
  386. break;
  387. case 1:
  388. finalImage[realDestinationPixel + (x * 4) + (y * width * 4)] = (byte)MathHelper.Clamp(baseColorR + red, 0, 255);
  389. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1] = (byte)MathHelper.Clamp(baseColorG + green, 0, 255);
  390. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2] = (byte)MathHelper.Clamp(baseColorB + blue, 0, 255);
  391. break;
  392. case 2:
  393. finalImage[realDestinationPixel + (x * 4) + (y * width * 4)] = (byte)MathHelper.Clamp(baseColorR - red, 0, 255);
  394. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1] = (byte)MathHelper.Clamp(baseColorG - green, 0, 255);
  395. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2] = (byte)MathHelper.Clamp(baseColorB - blue, 0, 255);
  396. break;
  397. case 3:
  398. break;
  399. finalImage[realDestinationPixel + (x * 4) + (y * width * 4)] = (byte)MathHelper.Clamp((byte)(baseColorR + (0.25 * red)), 0, 255);
  400. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1] = (byte)MathHelper.Clamp((byte)(baseColorG + (0.25 * green)), 0, 255);
  401. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2] = (byte)MathHelper.Clamp((byte)(baseColorB + (0.25 * blue)), 0, 255);
  402. break;
  403. }
  404. }
  405. }
  406. }