FieldCharaOne.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. using Microsoft.Xna.Framework.Graphics;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. namespace OpenVIII.Fields
  9. {
  10. class FieldCharaOne
  11. {
  12. public CharaModelHeaders[] fieldModels;
  13. public struct CharaModelHeaders
  14. {
  15. public uint offset; //points to texture
  16. public uint size; //size of whole segment
  17. public uint size2; //as above
  18. public uint flagDWORD; //this is either tim or indicator of main model
  19. public uint[] timOffset; //pointer to zero
  20. public uint modelDataOffset;
  21. public char[] modelName; //8
  22. public uint padding; //0xEEEEEEEE
  23. public Debug_MCH mch;
  24. public Texture2D[] textures;
  25. }
  26. public FieldCharaOne(int fieldId)
  27. {
  28. if (!FieldMainCharaOne.bAlreadyInitialized)
  29. FieldMainCharaOne.Init();
  30. ArchiveWorker aw = new ArchiveWorker(Memory.Archives.A_FIELD);
  31. string[] test = aw.GetListOfFiles();
  32. var CollectionEntry = test.Where(x => x.IndexOf(Memory.FieldHolder.fields[Memory.FieldHolder.FieldID],StringComparison.OrdinalIgnoreCase)>=0);
  33. if (!CollectionEntry.Any()) return;
  34. string fieldArchivename = CollectionEntry.First();
  35. var fieldArchive = aw.GetArchive(fieldArchivename);
  36. string[] test_ = fieldArchive.GetListOfFiles();
  37. string one;
  38. string main_chr;
  39. try
  40. {
  41. one = test_.First(x => x.EndsWith(".one",StringComparison.OrdinalIgnoreCase));
  42. }
  43. catch
  44. {
  45. return;
  46. }
  47. byte[] oneb = fieldArchive.GetBinaryFile(one);
  48. if (oneb.Length == 0)
  49. return;
  50. ReadBuffer(oneb);
  51. }
  52. private void ReadBuffer(byte[] oneBuffer)
  53. {
  54. List<CharaModelHeaders> cmh = new List<CharaModelHeaders>();
  55. int lastMsPosition = 0;
  56. using (MemoryStream ms = new MemoryStream(oneBuffer))
  57. using (BinaryReader br = new BinaryReader(ms))
  58. {
  59. uint nModels = br.ReadUInt32();
  60. for (int i = 0; i < nModels; i++)
  61. {
  62. CharaModelHeaders localCmh = new CharaModelHeaders
  63. {
  64. offset = br.ReadUInt32() + 4,
  65. size = br.ReadUInt32(),
  66. size2 = br.ReadUInt32(),
  67. flagDWORD = br.ReadUInt32()
  68. };
  69. bool bIgnorePadding = false;
  70. bool bMainChara = false;
  71. if (localCmh.flagDWORD >> 24 == 0xD0) //main character file
  72. {
  73. localCmh.timOffset = new uint[0];
  74. localCmh.modelDataOffset = 0xFFFFFFFF;
  75. ms.Seek(4, SeekOrigin.Current);
  76. bMainChara = true;
  77. }
  78. else if (localCmh.flagDWORD >> 24 == 0xa0) //unknown- object without texture/ placeholder?
  79. {
  80. localCmh.timOffset = new uint[0];
  81. localCmh.modelDataOffset = 0xFFFFFFFF;
  82. ms.Seek(8, SeekOrigin.Current);
  83. bIgnorePadding = true;
  84. }
  85. else
  86. {
  87. List<uint> timOffsets = new List<uint>();
  88. uint flagTimOffset = localCmh.flagDWORD & 0x00FFFFFF;
  89. timOffsets.Add(localCmh.flagDWORD << 8);
  90. uint localTimOffset;
  91. while ((localTimOffset = br.ReadUInt32()) != 0xFFFFFFFF)
  92. timOffsets.Add(localTimOffset & 0x00FFFFFF);
  93. localCmh.timOffset = timOffsets.ToArray();
  94. localCmh.modelDataOffset = br.ReadUInt32();
  95. }
  96. localCmh.modelName = br.ReadChars(8);
  97. localCmh.padding = br.ReadUInt32();
  98. if (localCmh.padding != 0xEEEEEEEE && !bIgnorePadding) //null models for placeholders are 2 not eeeeeeee
  99. throw new Exception("Chara one- padding was not 0xEEEEEEEE- check code for ReadBuffer in FieldCharaOne");
  100. if (localCmh.modelDataOffset != 0xFFFFFFFF)
  101. {
  102. lastMsPosition = (int)ms.Position;
  103. ms.Seek(localCmh.offset + localCmh.modelDataOffset, SeekOrigin.Begin);
  104. localCmh.mch = new Debug_MCH(ms, br, Debug_MCH.mchMode.FieldNPC, 3f);
  105. //ms.Seek(localCmh.offset + 4, SeekOrigin.Begin);
  106. List<Texture2D> texList = new List<Texture2D>();
  107. for (int n = 0; n < localCmh.timOffset.Length; n++)
  108. {
  109. if (localCmh.timOffset[n] > 0x10000000)
  110. localCmh.timOffset[n] = localCmh.timOffset[n] & 0x00FFFFFF;
  111. TIM2 localTim = new TIM2(br, localCmh.offset + localCmh.timOffset[n]);
  112. texList.Add(localTim.GetTexture());
  113. }
  114. localCmh.textures = texList.ToArray();
  115. ms.Seek(lastMsPosition, SeekOrigin.Begin);
  116. }
  117. else if (bMainChara)
  118. {
  119. lastMsPosition = (int)ms.Position;
  120. //this is main chara, so please grab data from main_chr.fs
  121. int getRefId = int.Parse(new string(localCmh.modelName).Substring(1, 3));
  122. var chara = FieldMainCharaOne.MainFieldCharacters.Where(x => x.id == getRefId).First();
  123. localCmh.modelDataOffset = 1;
  124. localCmh.mch = chara.mch;
  125. localCmh.textures = chara.textures;
  126. ms.Seek(localCmh.offset, SeekOrigin.Begin);
  127. localCmh.mch.MergeAnimations(ms, br);
  128. ms.Seek(lastMsPosition, SeekOrigin.Begin);
  129. }
  130. cmh.Add(localCmh);
  131. }
  132. }
  133. fieldModels = cmh.ToArray();
  134. }
  135. }
  136. //this is static, because it's always alive
  137. public static class FieldMainCharaOne
  138. {
  139. public static bool bAlreadyInitialized = false;
  140. public static MainFieldChara[] MainFieldCharacters;
  141. public struct MainFieldChara
  142. {
  143. public int id;
  144. public Debug_MCH mch;
  145. public Texture2D[] textures;
  146. }
  147. public static void Init(bool bForce = false)
  148. {
  149. if (bAlreadyInitialized && !bForce)
  150. return;
  151. List<MainFieldChara> mfc = new List<MainFieldChara>();
  152. ArchiveWorker aw = new ArchiveWorker(Memory.Archives.A_FIELD);
  153. string[] test = aw.GetListOfFiles();
  154. var CollectionEntry = test.Where(x => x.ToLower().Contains("main_chr"));
  155. if (!CollectionEntry.Any()) return;
  156. string fieldArchiveName = CollectionEntry.First();
  157. var fieldArchive = aw.GetArchive(fieldArchiveName);
  158. string[] test_ = fieldArchive.GetListOfFiles() ;
  159. for(int i = 0; i<test_.Length; i++)
  160. {
  161. //if (test_[i].Contains("d008.mch"))
  162. // continue;
  163. if (string.IsNullOrWhiteSpace(test_[i]))
  164. continue;
  165. byte[] oneb = fieldArchive.GetBinaryFile(test_[i]);
  166. if (oneb.Length < 64) //Hello Kazuo Suzuki! I will skip your dummy files
  167. continue;
  168. MainFieldChara currentLocalChara = ReadMainChara(oneb);
  169. int localId = int.Parse(Path.GetFileNameWithoutExtension(test_[i]).Substring(1,3));
  170. currentLocalChara.id = localId;
  171. mfc.Add(currentLocalChara);
  172. }
  173. MainFieldCharacters = mfc.ToArray();
  174. bAlreadyInitialized = true;
  175. }
  176. private static MainFieldChara ReadMainChara(byte[] oneb)
  177. {
  178. MainFieldChara localMfc = new MainFieldChara();
  179. using (MemoryStream ms = new MemoryStream(oneb))
  180. using (BinaryReader br = new BinaryReader(ms))
  181. {
  182. List<uint> timOffsets = new List<uint>();
  183. uint timOffset;
  184. while((timOffset = br.ReadUInt32())!=0xffffffff )
  185. timOffsets.Add(timOffset & 0x00FFFFFF);
  186. uint modelPointer = br.ReadUInt32();
  187. //read textures
  188. List<Texture2D> tex2Dreader = new List<Texture2D>();
  189. for(int i = 0; i<timOffsets.Count; i++)
  190. {
  191. TIM2 tim = new TIM2(br, timOffsets[i]);
  192. tex2Dreader.Add(tim.GetTexture());
  193. }
  194. localMfc.textures = tex2Dreader.ToArray();
  195. //read models
  196. ms.Seek(modelPointer, SeekOrigin.Begin);
  197. Debug_MCH mch = new Debug_MCH(ms, br, Debug_MCH.mchMode.FieldMain);
  198. localMfc.mch = mch;
  199. }
  200. return localMfc;
  201. }
  202. }
  203. }