Card_Game.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. using Microsoft.Xna.Framework;
  2. using Microsoft.Xna.Framework.Graphics;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. namespace OpenVIII.Card
  7. {
  8. public class Game
  9. {
  10. private const int year = 2013;
  11. private TextureHandler[] _symbolsNumbers;
  12. private TextureHandler[] _cardFaces;
  13. private TextureHandler[] _cardGameBG;
  14. private TextureHandler[] _cardOtherBG;
  15. private List<Entry> _symbolNumberEntries;
  16. private List<Entry> _cardFacesEntries;
  17. public TextureHandler[] SymbolsNumbers { get => _symbolsNumbers; private set => _symbolsNumbers = value; }
  18. //private TextureHandler[] Other;
  19. public TextureHandler[] CardFaces { get => _cardFaces; private set => _cardFaces = value; }
  20. public TextureHandler[] CardGameBG { get => _cardGameBG; private set => _cardGameBG = value; }
  21. public TextureHandler[] CardOtherBG { get => _cardOtherBG; private set => _cardOtherBG = value; }
  22. public IReadOnlyList<Entry> SymbolNumberEntries => _symbolNumberEntries;
  23. public IReadOnlyList<Entry> CardFacesEntries => _cardFacesEntries;
  24. public Game()
  25. {
  26. Memory.MainThreadOnlyActions.Enqueue(() =>
  27. {
  28. //Memory.EnableDumpingData = true;
  29. using (BinaryReader br = new BinaryReader(FileStreamOpen()))
  30. ReadSymbolsNumbers(0, br);
  31. //Memory.EnableDumpingData = false;
  32. });
  33. Memory.MainThreadOnlyActions.Enqueue(() =>
  34. {
  35. using (BinaryReader br = new BinaryReader(FileStreamOpen()))
  36. ReadCardFaces(2, br);
  37. });
  38. using (BinaryReader br = new BinaryReader(FileStreamOpen()))
  39. {
  40. //ReadTIM(1, br,out Other);
  41. ReadTIM(50, br, out _cardGameBG);
  42. ReadTIM(51, br, out _cardOtherBG);
  43. }
  44. }
  45. private FileStream FileStreamOpen() => new FileStream(EXE_Offsets.FileName[year], FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
  46. private void ReadCardFaces(int id, BinaryReader br)
  47. {
  48. TIM2 cardtim = new TIM2(br, EXE_Offsets.TIM[year][id]);
  49. using (Texture2D cardback = cardtim.GetTexture(55))
  50. {
  51. GenernateCardFaceEntries();
  52. cardtim.ForceSetClutColors(128);
  53. cardtim.ForceSetClutCount(112);
  54. int rows = 4;
  55. int size = cardback.Height / rows;
  56. int cols = cardback.Width / size;
  57. //using (Texture2D combined = new Texture2D(Memory.graphics.GraphicsDevice, cardback.Width, cardback.Height))
  58. //{
  59. Color[] data = new Color[size * size];
  60. Rectangle src = new Rectangle(new Point(size * (cols - 2), size * (rows - 1)), new Point(size));
  61. Rectangle dst;
  62. //cardback.GetData(0, src, data, 0, data.Length);
  63. //combined.SetData(0, src, data, 0, data.Length);
  64. int row = 0;
  65. int acol = 0;
  66. List<Point> rc = new List<Point>(110);
  67. int page = 0;
  68. int pages = cols / 2;
  69. List<TextureHandler> th = new List<TextureHandler>(pages);
  70. ushort i = 0;
  71. string filename = $"cards";
  72. while (i < 110 && page < pages)
  73. {
  74. Texture2D pagetex = new Texture2D(Memory.graphics.GraphicsDevice, cardback.Height, cardback.Height);
  75. for (int p = 0; p < 8 && i < 110; p++)
  76. {
  77. Texture2D cardface = cardtim.GetTexture(i);
  78. int coloff = i % 2;
  79. bool even = coloff == 0;
  80. if (row >= rows)
  81. {
  82. row = 0;
  83. acol += 2;
  84. }
  85. int col = acol + coloff;
  86. src = new Rectangle(new Point(size * (col), size * (row)), new Point(size));
  87. dst = new Rectangle(new Point(size * (coloff), size * (row)), new Point(size));
  88. cardface.GetData(0, src, data, 0, data.Length);
  89. //combined.SetData(0, src, data, 0, data.Length);
  90. pagetex.SetData(0, dst, data, 0, data.Length);
  91. rc.Add(new Point(col, row));
  92. if (!even) row++;
  93. i++;
  94. }
  95. if (page == pages - 1)
  96. {
  97. src = new Rectangle(new Point(size * (cols - 2), size * (rows - 1)), new Point(size));
  98. dst = new Rectangle(new Point(0, size * (rows - 1)), new Point(size));
  99. cardback.GetData(0, src, data, 0, data.Length);
  100. pagetex.SetData(0, dst, data, 0, data.Length);
  101. }
  102. if (Memory.EnableDumpingData)
  103. using (FileStream fs = new FileStream(Path.Combine(Path.GetTempPath(), $"{filename}_{page}.png"), FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
  104. pagetex.SaveAsPng(fs, cardback.Height, cardback.Height);
  105. th.Add(TextureHandler.Create($"{filename}_{page}.png", new Texture2DWrapper(pagetex)));
  106. page++;
  107. }
  108. CardFaces = th.ToArray();
  109. // if (Memory.EnableDumpingData)
  110. // using (FileStream fs = new FileStream(Path.Combine(Path.GetTempPath(), $"{filename}.combined.png"), FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
  111. // combined.SaveAsPng(fs, cardback.Width, cardback.Height);
  112. //}
  113. }
  114. }
  115. private void GenernateCardFaceEntries()
  116. {
  117. if (_cardFacesEntries == null || _cardFacesEntries.Count == 0)
  118. {
  119. _cardFacesEntries = new List<Entry>();
  120. Cards.ID[] CardValues = (Cards.ID[])Enum.GetValues(typeof(Cards.ID));
  121. Array.Sort(CardValues);
  122. const int size = 64;
  123. const int numberofcardsperpage = 8;
  124. const int cols = 2;
  125. const int rows = 4;
  126. for (int i = 0; i < CardValues.Length && CardValues[i] <= Cards.ID.Card_Back; i++)
  127. {
  128. new Entry
  129. {
  130. ID = CardValues[i],
  131. File = checked((byte)(i / numberofcardsperpage)),
  132. X = i % cols == 1 ? size : 0,
  133. Y = ((i / cols) % rows) * size,
  134. Height = size,
  135. Width = size,
  136. CustomPalette = checked((sbyte)i),
  137. };
  138. }
  139. }
  140. }
  141. private enum SymbolID
  142. {
  143. None,
  144. HexNumbers,
  145. Fire,
  146. Ice,
  147. Lightning,
  148. Earth,
  149. Poison,
  150. Wind,
  151. Water,
  152. Holy,
  153. Score,
  154. Buff,
  155. Debuff,
  156. Win,
  157. Lose,
  158. Draw,
  159. Same,
  160. Plus,
  161. Combo,
  162. }
  163. private void ReadSymbolsNumbers(int id, BinaryReader br)
  164. {
  165. const int pages = 3;
  166. List<TextureHandler> th = new List<TextureHandler>(pages);
  167. //3 pages, 256x256; inside () is palette id +1.
  168. //page 1 = 5 rows. first 3 rows are 16x16 grid, last 2 rows are a 24x24 grid
  169. // row 1 has 11 hex numbers: 0-A (1)
  170. // row 2 4 of 4 frame animations: fire(4), ice(7), lightning(10), earth(13)
  171. // row 3 4 of 4 frame animations: poison(16), wind(19), water(22), holy(25)
  172. // row 4 has 9 numbers: 0-9 (28)
  173. // row 5 has 2 items: +1, -1 (31 or 34)
  174. //page 2 = 3 rows of 256x48: You Win!(2), You Lose...(5), Draw(8)
  175. //page 3 = 3 rows of 256x64: Same!(9), Plus!(6), Combo!(9)
  176. GenerateEntriesSymbolsNumbers();
  177. TIM2 temp = new TIM2(br, EXE_Offsets.TIM[year][id]);
  178. //temp.ForceSetClutColors(16);
  179. //temp.ForceSetClutCount(48);
  180. int size = 256;
  181. //Rectangle pagesrc = new Rectangle(new Point(size * (page), size), new Point(size));
  182. //Rectangle dst;
  183. //using (Texture2D combined = new Texture2D(Memory.graphics.GraphicsDevice, size * 3, temp.GetHeight))
  184. //{
  185. Texture2D texture = null;
  186. Texture2D pagetex = null;
  187. sbyte CustomPalette = -1;
  188. sbyte File = -1;
  189. string filename = "";
  190. //string combinedfilename = $"text_combined.png";
  191. foreach (Entry e in SymbolNumberEntries)
  192. {
  193. if (File != e.File)
  194. {
  195. savepagetex();
  196. File = checked((sbyte)e.File);
  197. pagetex = new Texture2D(Memory.graphics.GraphicsDevice, size, size);
  198. filename = $"text_{File}.png";
  199. }
  200. if (CustomPalette != e.CustomPalette)
  201. {
  202. if (texture != null)
  203. texture.Dispose();
  204. CustomPalette = e.CustomPalette;
  205. texture = temp.GetTexture((ushort)CustomPalette);
  206. }
  207. Color[] data = new Color[(int)(e.Width * e.Height)];
  208. Rectangle src = e.GetRectangle;
  209. Rectangle dst = src;
  210. src.Offset(e.File * 256, 0);
  211. texture.GetData(0, src, data, 0, data.Length);
  212. pagetex.SetData(0, dst, data, 0, data.Length);
  213. //dst = src;
  214. //combined.SetData(0, dst, data, 0, data.Length);
  215. }
  216. texture.Dispose();
  217. savepagetex();
  218. void savepagetex()
  219. {
  220. if (pagetex != null)
  221. {
  222. if (Memory.EnableDumpingData)
  223. using (FileStream fs = new FileStream(Path.Combine(Path.GetTempPath(), filename), FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
  224. pagetex.SaveAsPng(fs, pagetex.Width, pagetex.Height);
  225. th.Add(TextureHandler.Create(filename, new Texture2DWrapper(pagetex)));
  226. }
  227. }
  228. //if (Memory.EnableDumpingData)
  229. // using (FileStream fs = new FileStream(Path.Combine(Path.GetTempPath(), combinedfilename), FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
  230. // combined.SaveAsPng(fs, combined.Width, combined.Height);
  231. //}
  232. //if (Memory.EnableDumpingData)
  233. // Memory.MainThreadOnlyActions.Enqueue(() => { temp.SaveCLUT(Path.Combine(Path.GetTempPath(), $"{filename}.CLUT.png")); });
  234. //SymbolsNumbers = new TextureHandler[temp.GetClutCount];
  235. //for (ushort i = 0; i < temp.GetClutCount; i++)
  236. //{
  237. // SymbolsNumbers[i] = TextureHandler.Create(filename, temp, i);
  238. // //Memory.MainThreadOnlyActions.Enqueue(SymbolsNumbers[i].Save);
  239. //}
  240. if (Memory.EnableDumpingData)
  241. {
  242. filename = $"text_raw.png";
  243. for (ushort i = 0; i < temp.GetClutCount || i == 0 && temp.GetClutCount == 0; i++)
  244. {
  245. th.Add(TextureHandler.Create(filename, temp, i));
  246. }
  247. }
  248. _symbolsNumbers = th.ToArray();
  249. }
  250. private void GenerateEntriesSymbolsNumbers()
  251. {
  252. if (_symbolNumberEntries == null || _symbolNumberEntries.Count == 0)
  253. {
  254. _symbolNumberEntries = new List<Entry>();
  255. for (int i = 0; i < 11; i++)
  256. {
  257. _symbolNumberEntries.Add(new Entry
  258. {
  259. ID = SymbolID.HexNumbers,
  260. File = 0,
  261. CustomPalette = 0,
  262. Location = new Vector2(i * 16, 0),
  263. Size = new Vector2(16, 16),
  264. NumberValue = i
  265. });
  266. }
  267. for (int k = 0; k < 2; k++)
  268. for (int j = 0; j < 4; j++)
  269. for (int i = 0; i < 4; i++)
  270. {
  271. _symbolNumberEntries.Add(new Entry
  272. {
  273. ID = (SymbolID)((int)(SymbolID.Fire) + j + (k * 4)),
  274. File = 0,
  275. CustomPalette = checked((sbyte)(3 * (j + 1 + (k * 4)))),
  276. Location = new Vector2((i + (4 * j)) * 16, 16 * (k + 1)),
  277. Size = new Vector2(16, 16),
  278. Frame = i,
  279. });
  280. }
  281. for (int i = 0; i < 9; i++)
  282. {
  283. _symbolNumberEntries.Add(new Entry
  284. {
  285. ID = SymbolID.Score,
  286. File = 0,
  287. CustomPalette = 27,
  288. Location = new Vector2(i * 24, 16 * 3),
  289. Size = new Vector2(24, 24),
  290. NumberValue = i
  291. });
  292. }
  293. for (int i = 0; i < 2; i++)
  294. {
  295. _symbolNumberEntries.Add(new Entry
  296. {
  297. ID = (SymbolID)((int)(SymbolID.Buff) + i),
  298. File = 0,
  299. CustomPalette = 30,
  300. Location = new Vector2(i * 24, 16 * 3 + 24),
  301. Size = new Vector2(24, 24),
  302. NumberValue = 1 + (-2 * i)
  303. });
  304. }
  305. for (int i = 0; i < 3; i++)
  306. {
  307. _symbolNumberEntries.Add(new Entry
  308. {
  309. ID = (SymbolID)((int)(SymbolID.Win) + i),
  310. File = 1,
  311. CustomPalette = checked((sbyte)(1 + 3 * i)),
  312. Location = new Vector2(0, 48 * i),
  313. Size = new Vector2(256, 48),
  314. });
  315. }
  316. for (int i = 0; i < 3; i++)
  317. {
  318. _symbolNumberEntries.Add(new Entry
  319. {
  320. ID = (SymbolID)((int)(SymbolID.Same) + i),
  321. File = 2,
  322. CustomPalette = checked((sbyte)(2 + 3 * i)),
  323. Location = new Vector2(0, 64 * i),
  324. Size = new Vector2(256, 64),
  325. });
  326. }
  327. }
  328. }
  329. private void ReadTIM(int id, BinaryReader br, out TextureHandler[] tex, ushort ForceSetClutColors = 0, ushort ForceSetClutCount = 0)
  330. {
  331. TIM2 temp = new TIM2(br, EXE_Offsets.TIM[year][id]);
  332. if (ForceSetClutColors > 0)
  333. temp.ForceSetClutColors(ForceSetClutColors);
  334. if (ForceSetClutCount > 0)
  335. temp.ForceSetClutCount(ForceSetClutCount);
  336. string filename = $"ff8exe{id.ToString("D2")}";
  337. if (Memory.EnableDumpingData)
  338. Memory.MainThreadOnlyActions.Enqueue(() => { temp.SaveCLUT(Path.Combine(Path.GetTempPath(), $"{filename}.CLUT.png")); });
  339. tex = new TextureHandler[temp.GetClutCount == 0 ? 1 : temp.GetClutCount];
  340. for (ushort i = 0; i < temp.GetClutCount || i == 0 && temp.GetClutCount == 0; i++)
  341. {
  342. tex[i] = TextureHandler.Create(filename, temp, i);
  343. }
  344. }
  345. }
  346. }