module_battle_Debug.cs 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Microsoft.Xna.Framework;
  5. using Microsoft.Xna.Framework.Graphics;
  6. using Microsoft.Xna.Framework.Input;
  7. namespace FF8
  8. {
  9. static class Module_battle_debug
  10. {
  11. private static uint bs_cameraPointer;
  12. private static Matrix projectionMatrix, viewMatrix, worldMatrix;
  13. private static float degrees=90, Yshift;
  14. private static readonly float camDistance = 10.0f;
  15. private static Vector3 camPosition, camTarget;
  16. private static TIM2 textureInterface;
  17. private static Texture2D[] textures;
  18. static List<EnemyInstanceInformation> EnemyInstances;
  19. static List<CharacterInstanceInformation> CharacterInstances;
  20. //skyRotating floats are hardcoded
  21. private static readonly ushort[] skyRotators = { 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x4, 0x4, 0x0, 0x0, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x4, 0x4, 0x0, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x2, 0x0, 0x0, 0x8, 0xfffc, 0xfffc, 0x0, 0x0, 0x0, 0x4, 0x0, 0x8, 0x0, 0x4, 0x4, 0x0, 0x4, 0x0, 0x4, 0xfffc, 0x8, 0xfffc, 0xfffc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x4, 0x4, 0x0, 0x0, 0x4, 0x4, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x4, 0x4, 0x8, 0xfffc, 0x4, 0x4, 0x4, 0x4, 0x8, 0x8, 0x4, 0xfffc, 0xfffc, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0xfffc, 0x0, 0x0, 0x0, 0x0, 0x8, 0x8, 0x0, 0x8, 0xfffc, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x8, 0x0, 0x8, 0x8 };
  22. static float localRotator = 0.0f; //a rotator is a float that holds current axis rotation for sky. May be malformed by skyRotators or TimeCompression magic
  23. public static BasicEffect effect;
  24. public static AlphaTestEffect ate;
  25. private static BattleCamera battleCamera;
  26. private static string battlename = "a0stg000.x";
  27. private static byte[] stageBuffer;
  28. private static int battleModule = 0;
  29. private const int BATTLEMODULE_INIT = 0;
  30. private const int BATTLEMODULE_READDATA = 1;
  31. private const int BATTLEMODULE_DRAWGEOMETRY = 2;
  32. private const int BATTLEMODULE_CAMERAINTRO = 3;
  33. private const int BATTLEMODULE_ACTIVE = 4;
  34. private const float FPS = 1000.0f / 15f; //Natively the game we are rewritting works in 15 FPS per second
  35. /// <summary>
  36. /// This is helper struct that works along with VertexPosition to provide Clut, texture page and bool to decide if it's quad or triangle
  37. /// </summary>
  38. private struct Stage_GeometryInfoSupplier
  39. {
  40. public bool bQuad;
  41. public byte clut;
  42. public byte texPage;
  43. }
  44. private struct EnemyInstanceInformation
  45. {
  46. public Debug_battleDat Data;
  47. /// <summary>
  48. /// bit position of the enemy in encounter data. Use to pair the information with encounter data
  49. /// </summary>
  50. public byte index;
  51. public bool bIsHidden;
  52. public bool bIsActive;
  53. public bool bIsUntargetable;
  54. public AnimationSystem animationSystem;
  55. }
  56. /// <summary>
  57. /// CharacterInstanceInformation should only be used for battle-exclusive data. Manipulating HP, GFs, junctions and other character-specific
  58. /// things should happen outside battle, because such information about characters is shared between almost all modules.
  59. /// This field contains information about the current status of battle rendering like animation frames/ rendering flags/ effects attached
  60. /// </summary>
  61. private struct CharacterInstanceInformation
  62. {
  63. public CharacterData Data;
  64. public int characterId; //0 is Whatever guy
  65. public bool bIsHidden; //GF sequences, magic...
  66. public AnimationSystem animationSystem;
  67. }
  68. private struct BattleCamera
  69. {
  70. public BattleCameraSettings battleCameraSettings;
  71. public BattleCameraCollection battleCameraCollection;
  72. }
  73. private struct BattleCameraSettings
  74. {
  75. public byte[] unk;
  76. }
  77. private struct BattleCameraCollection
  78. {
  79. public uint cAnimCollectionCount;
  80. public uint pCameraEOF;
  81. public BattleCameraSet[] battleCameraSet;
  82. }
  83. private struct BattleCameraSet
  84. {
  85. public uint[] animPointers;
  86. public uint globalSetPointer;
  87. public CameraAnimation[] cameraAnimation;
  88. }
  89. private struct CameraAnimation
  90. {
  91. public ushort header;
  92. }
  93. private struct Triangle
  94. {
  95. public ushort A;
  96. public ushort B;
  97. public ushort C;
  98. public byte U1;
  99. public byte V1;
  100. public byte U2;
  101. public byte V2;
  102. public byte clut;
  103. public byte U3;
  104. public byte V3;
  105. public byte TexturePage;
  106. public byte bHide;
  107. public byte Red;
  108. public byte Green;
  109. public byte Blue;
  110. public byte GPU;
  111. }
  112. private struct Quad
  113. {
  114. public ushort A;
  115. public ushort B;
  116. public ushort C;
  117. public ushort D;
  118. public byte U1;
  119. public byte V1;
  120. public byte clut;
  121. public byte U2;
  122. public byte V2;
  123. public byte TexturePage;
  124. public byte bHide;
  125. public byte U3;
  126. public byte V3;
  127. public byte U4;
  128. public byte V4;
  129. public byte Red;
  130. public byte Green;
  131. public byte Blue;
  132. public byte GPU;
  133. }
  134. private struct MainGeometrySection
  135. {
  136. public uint Group1Pointer;
  137. public uint Group2Pointer;
  138. public uint Group3Pointer;
  139. public uint Group4Pointer;
  140. public uint TextureUNUSEDPointer;
  141. public uint TexturePointer;
  142. public uint EOF;
  143. }
  144. private struct ObjectsGroup
  145. {
  146. public uint numberOfSections;
  147. public uint settings1Pointer;
  148. public uint objectListPointer;
  149. public uint settings2Pointer;
  150. public uint relativeEOF;
  151. }
  152. private struct Vertex
  153. {
  154. public short X;
  155. public short Y;
  156. public short Z;
  157. }
  158. private struct Model
  159. {
  160. public Vertex[] vertices;
  161. public Triangle[] triangles;
  162. public Quad[] quads;
  163. }
  164. private struct ModelGroup
  165. {
  166. public Model[] models;
  167. }
  168. private static ModelGroup[] modelGroups;
  169. private static Debug_battleDat[] monstersData;
  170. private struct CharacterData
  171. {
  172. public Debug_battleDat character, weapon;
  173. };
  174. private static PseudoBufferedStream pbs;
  175. private static byte GetTexturePage(byte texturepage) => (byte)(texturepage & 0x0F);
  176. private static byte GetClutId(ushort clut)
  177. {
  178. ushort bb = MakiExtended.UshortLittleEndian(clut);
  179. return (byte)(((bb >> 14) & 0x03) | (bb << 2) & 0x0C);
  180. }
  181. public static void ResetState() { battleModule = BATTLEMODULE_INIT; }
  182. public static void Update()
  183. {
  184. switch (battleModule)
  185. {
  186. case BATTLEMODULE_INIT:
  187. InitBattle();
  188. break;
  189. case BATTLEMODULE_READDATA:
  190. ReadData();
  191. break;
  192. case BATTLEMODULE_DRAWGEOMETRY:
  193. FPSCamera();
  194. break;
  195. }
  196. if (Input.Button(Keys.F1))
  197. DEBUGframe += 1;
  198. if (Input.Button(Keys.F2))
  199. DEBUGframe--;
  200. }
  201. public static void Draw()
  202. {
  203. switch (battleModule)
  204. {
  205. case BATTLEMODULE_DRAWGEOMETRY:
  206. DrawGeometry();
  207. DrawMonsters();
  208. DrawCharactersWeapons();
  209. UpdateFrames();
  210. break;
  211. }
  212. }
  213. /// <summary>
  214. /// Method to render characters and weapons for them
  215. /// </summary>
  216. private static void DrawCharactersWeapons()
  217. {
  218. Memory.graphics.GraphicsDevice.RasterizerState = RasterizerState.CullNone;
  219. Memory.graphics.GraphicsDevice.BlendState = BlendState.AlphaBlend;
  220. Memory.graphics.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
  221. Memory.graphics.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp;
  222. ate.Projection = projectionMatrix; ate.View = viewMatrix; ate.World = worldMatrix;
  223. effect.TextureEnabled = true;
  224. //CHARACTER
  225. for (int n = 0; n < CharacterInstances.Count; n++)
  226. {
  227. CheckAnimationFrame(Debug_battleDat.EntityType.Character, n);
  228. Vector3 charaPosition = new Vector3(-40 + n * 10, 0, -40);
  229. for (int i = 0; i < CharacterInstances[n].Data.character.geometry.cObjects; i++)
  230. {
  231. var a = CharacterInstances[n].Data.character.GetVertexPositions(i,charaPosition ,Quaternion.CreateFromYawPitchRoll(3f,0,0), CharacterInstances[n].animationSystem.animationId, CharacterInstances[n].animationSystem.animationFrame, frameperFPS / FPS); //DEBUG
  232. if (a == null || a.Item1.Length == 0)
  233. return;
  234. for (int k = 0; k < a.Item1.Length / 3; k++)
  235. {
  236. ate.Texture = CharacterInstances[n].Data.character.textures.textures[a.Item2[k]];
  237. foreach (var pass in ate.CurrentTechnique.Passes)
  238. {
  239. pass.Apply();
  240. Memory.graphics.GraphicsDevice.DrawUserPrimitives(primitiveType: PrimitiveType.TriangleList,
  241. vertexData: a.Item1, vertexOffset: k*3, primitiveCount: 1);
  242. }
  243. }
  244. }
  245. DrawShadow(charaPosition, ate, .5f);
  246. }
  247. //WEAPON
  248. for (int n = 0; n < CharacterInstances.Count; n++)
  249. { if (CharacterInstances[n].Data.weapon == null)
  250. return;
  251. CheckAnimationFrame(Debug_battleDat.EntityType.Weapon, n);
  252. Vector3 weaponPosition = new Vector3(-40 + n * 10, 0+DEBUGframe, -40+1);
  253. for (int i = 0; i < CharacterInstances[n].Data.weapon.geometry.cObjects; i++)
  254. {
  255. var a = CharacterInstances[n].Data.weapon.GetVertexPositions(i, weaponPosition, Quaternion.CreateFromYawPitchRoll(3f, 0, 0), CharacterInstances[n].animationSystem.animationId, CharacterInstances[n].animationSystem.animationFrame, frameperFPS / FPS); //DEBUG
  256. if (a == null || a.Item1.Length == 0)
  257. return;
  258. for (int k = 0; k < a.Item1.Length / 3; k++)
  259. {
  260. ate.Texture = CharacterInstances[n].Data.weapon.textures.textures[a.Item2[k]];
  261. foreach (var pass in ate.CurrentTechnique.Passes)
  262. {
  263. pass.Apply();
  264. Memory.graphics.GraphicsDevice.DrawUserPrimitives(primitiveType: PrimitiveType.TriangleList,
  265. vertexData: a.Item1, vertexOffset: k*3, primitiveCount: 1);
  266. }
  267. }
  268. }
  269. }
  270. }
  271. private static void CheckAnimationFrame(Debug_battleDat.EntityType type, int n)
  272. {
  273. Debug_battleDat.Animation animationSystem;
  274. switch(type)
  275. {
  276. case Debug_battleDat.EntityType.Monster:
  277. animationSystem = EnemyInstances[n].Data.animHeader.animations[EnemyInstances[n].animationSystem.animationId];
  278. if (EnemyInstances[n].animationSystem.animationFrame >= animationSystem.cFrames)
  279. {
  280. var InstanceInformationProvider = EnemyInstances[n];
  281. InstanceInformationProvider.animationSystem.animationFrame = 0;
  282. if (EnemyInstances[n].animationSystem.AnimationQueue.Count > 0)
  283. {
  284. InstanceInformationProvider.animationSystem.animationId = EnemyInstances[n].animationSystem.AnimationQueue.First();
  285. EnemyInstances[n].animationSystem.AnimationQueue.RemoveAt(0);
  286. }
  287. EnemyInstances[n] = InstanceInformationProvider;
  288. }
  289. return;
  290. case Debug_battleDat.EntityType.Character:
  291. case Debug_battleDat.EntityType.Weapon:
  292. animationSystem = CharacterInstances[n].Data.character.animHeader.animations[CharacterInstances[n].animationSystem.animationId];
  293. if (CharacterInstances[n].animationSystem.animationFrame >= animationSystem.cFrames)
  294. {
  295. var InstanceInformationProvider = CharacterInstances[n];
  296. InstanceInformationProvider.animationSystem.animationFrame = 0;
  297. if (CharacterInstances[n].animationSystem.AnimationQueue.Count > 0)
  298. {
  299. InstanceInformationProvider.animationSystem.animationId = CharacterInstances[n].animationSystem.AnimationQueue.First();
  300. CharacterInstances[n].animationSystem.AnimationQueue.RemoveAt(0);
  301. }
  302. CharacterInstances[n] = InstanceInformationProvider;
  303. }
  304. return;
  305. default:
  306. return;
  307. }
  308. }
  309. /// <summary>
  310. /// Animation system. Decided to go for struct, so I can attach it to instance and manipulate easily grouped. It's also open for modifications
  311. /// </summary>
  312. private struct AnimationSystem
  313. {
  314. public int animationId;
  315. public int animationFrame;
  316. public bool bStopAnimation; //pertification placeholder?
  317. public List<int> AnimationQueue;
  318. }
  319. public static int DEBUGframe = 0;
  320. private static void DrawMonsters()
  321. {
  322. Memory.graphics.GraphicsDevice.RasterizerState = RasterizerState.CullNone;
  323. Memory.graphics.GraphicsDevice.BlendState = BlendState.AlphaBlend;
  324. Memory.graphics.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
  325. Memory.graphics.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp;
  326. ate.Projection = projectionMatrix; ate.View = viewMatrix; ate.World = worldMatrix;
  327. effect.TextureEnabled = true;
  328. if (EnemyInstances == null)
  329. return;
  330. for (int n = 0; n < EnemyInstances.Count; n++)
  331. {
  332. if (EnemyInstances[n].Data.GetId == 127)
  333. {
  334. //TODO;
  335. continue;
  336. }
  337. CheckAnimationFrame(Debug_battleDat.EntityType.Monster, n);
  338. var enemyPosition = Memory.encounters[Memory.battle_encounter].enemyCoordinates.GetEnemyCoordinateByIndex(EnemyInstances[n].index);
  339. for (int i = 0; i < EnemyInstances[n].Data.geometry.cObjects; i++)
  340. {
  341. var a = EnemyInstances[n].Data.GetVertexPositions(
  342. objectId: i,
  343. position: enemyPosition.GetVector(),
  344. rotation: Quaternion.CreateFromYawPitchRoll(0, 0, 0),
  345. animationId: EnemyInstances[n].animationSystem.animationId,
  346. animationFrame: EnemyInstances[n].animationSystem.animationFrame,
  347. step: frameperFPS / FPS);
  348. if (a == null || a.Item1.Length == 0)
  349. return;
  350. for (int k = 0; k < a.Item1.Length / 3; k++)
  351. {
  352. ate.Texture = EnemyInstances[n].Data.textures.textures[a.Item2[k]];
  353. foreach (var pass in ate.CurrentTechnique.Passes)
  354. {
  355. pass.Apply();
  356. Memory.graphics.GraphicsDevice.DrawUserPrimitives(primitiveType: PrimitiveType.TriangleList,
  357. vertexData: a.Item1, vertexOffset: k * 3, primitiveCount: 1);
  358. }
  359. }
  360. }
  361. DrawShadow(enemyPosition.GetVector(), ate, EnemyInstances[n].Data.skeleton.GetScale.X/5);
  362. }
  363. }
  364. private static void DrawShadow(Vector3 enemyPosition, AlphaTestEffect ate, float scale)
  365. {
  366. VertexPositionTexture[] ptCopy = Memory.shadowGeometry.Clone() as VertexPositionTexture[];
  367. for(int i = 0; i<ptCopy.Length; i++)
  368. ptCopy[i].Position = Vector3.Transform(ptCopy[i].Position, Matrix.CreateScale(scale));
  369. for (int i = 0; i < ptCopy.Length; i++)
  370. ptCopy[i].Position = Vector3.Add(ptCopy[i].Position, new Vector3(enemyPosition.X, 0.1f, enemyPosition.Z));
  371. ate.Texture = Memory.shadowTexture;
  372. foreach(var pass in ate.CurrentTechnique.Passes)
  373. {
  374. pass.Apply();
  375. Memory.graphics.GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, ptCopy, 0, 8);
  376. }
  377. }
  378. /// <summary>
  379. /// Increments animation frames by N, where N is equal to int(deltaTime/FPS).
  380. /// 15FPS is one frame per ~66 miliseconds. Therefore if deltaTime hits at least:
  381. /// below 33, then frame gets interpolated
  382. /// above 122, then frame gets skipped (by x/66)
  383. /// </summary>
  384. private static void UpdateFrames()
  385. {
  386. float tick = Memory.gameTime.ElapsedGameTime.Milliseconds;
  387. frameperFPS += tick;
  388. if (frameperFPS > FPS)
  389. {
  390. for (int x = 0; x < EnemyInstances.Count; x++)
  391. {
  392. var InstanceInformationProvider = EnemyInstances[x];
  393. InstanceInformationProvider.animationSystem.animationFrame++;
  394. EnemyInstances[x] = InstanceInformationProvider;
  395. }
  396. for (int x = 0; x < CharacterInstances.Count; x++)
  397. {
  398. var InstanceInformationProvider = CharacterInstances[x];
  399. InstanceInformationProvider.animationSystem.animationFrame++;
  400. CharacterInstances[x] = InstanceInformationProvider;
  401. }
  402. frameperFPS = 0.0f;
  403. }
  404. }
  405. /// <summary>
  406. /// Plays requested animation for given entity immidiately (without waiting for current animation to stop if have any queued animations)
  407. /// </summary>
  408. /// <param name="entityType">Provide either Monster or Character/weapon</param>
  409. /// <param name="nIndex">Index of entityTypeInstance. Monster is monsterInstances, character is CharacterInstances</param>
  410. /// <param name="newAnimId">self explanatory</param>
  411. public static void PlayAnimationImmidiately(Debug_battleDat.EntityType entityType, int nIndex, int newAnimId)
  412. {
  413. switch(entityType)
  414. {
  415. case Debug_battleDat.EntityType.Monster:
  416. EnemyInstanceInformation MInstanceInformationProvider = EnemyInstances[nIndex];
  417. MInstanceInformationProvider.animationSystem.animationId = newAnimId;
  418. MInstanceInformationProvider.animationSystem.animationFrame = 0;
  419. EnemyInstances[nIndex] = MInstanceInformationProvider;
  420. return;
  421. case Debug_battleDat.EntityType.Character:
  422. case Debug_battleDat.EntityType.Weapon:
  423. CharacterInstanceInformation CInstanceInformationProvider = CharacterInstances[nIndex];
  424. CInstanceInformationProvider.animationSystem.animationId = newAnimId;
  425. CInstanceInformationProvider.animationSystem.animationFrame = 0;
  426. CharacterInstances[nIndex] = CInstanceInformationProvider;
  427. return;
  428. default:
  429. return;
  430. }
  431. }
  432. public static void AddAnimationToQueue(Debug_battleDat.EntityType entityType, int nIndex, int newAnimId)
  433. {
  434. switch (entityType)
  435. {
  436. case Debug_battleDat.EntityType.Monster:
  437. EnemyInstanceInformation MInstanceInformationProvider = EnemyInstances[nIndex];
  438. MInstanceInformationProvider.animationSystem.AnimationQueue.Add(newAnimId);
  439. EnemyInstances[nIndex] = MInstanceInformationProvider;
  440. return;
  441. case Debug_battleDat.EntityType.Character:
  442. case Debug_battleDat.EntityType.Weapon:
  443. CharacterInstanceInformation CInstanceInformationProvider = CharacterInstances[nIndex];
  444. CInstanceInformationProvider.animationSystem.AnimationQueue.Add(newAnimId);
  445. CharacterInstances[nIndex] = CInstanceInformationProvider;
  446. return;
  447. default:
  448. return;
  449. }
  450. }
  451. const float defaultmaxMoveSpeed = 1f;
  452. const float MoveSpeedChange = 1f;
  453. static float maxMoveSpeed = defaultmaxMoveSpeed;
  454. const float maxLookSpeed = 0.25f;
  455. public static void FPSCamera()
  456. {
  457. #region FPScamera
  458. //speedcontrols
  459. //+ to increase
  460. //- to decrease
  461. //* to reset
  462. if (Input.Button(Keys.OemPlus) || Input.Button(Keys.Add))
  463. {
  464. maxMoveSpeed += MoveSpeedChange;
  465. }
  466. if (Input.Button(Keys.OemMinus) || Input.Button(Keys.Subtract))
  467. {
  468. maxMoveSpeed -= MoveSpeedChange;
  469. if (maxMoveSpeed < defaultmaxMoveSpeed) maxMoveSpeed = defaultmaxMoveSpeed;
  470. }
  471. if (Input.Button(Keys.Multiply)) maxMoveSpeed = defaultmaxMoveSpeed;
  472. //speed is effected by the milliseconds between frames. so alittle goes a long way. :P
  473. float x_shift = Input.Distance(Buttons.MouseXjoy, maxLookSpeed);
  474. float y_shift = Input.Distance(Buttons.MouseYjoy, maxLookSpeed);
  475. float leftdistX = Math.Abs(Input.Distance(Buttons.LeftStickX, maxMoveSpeed));
  476. float leftdistY = Math.Abs(Input.Distance(Buttons.LeftStickY, maxMoveSpeed));
  477. x_shift += Input.Distance(Buttons.RightStickX, maxLookSpeed);
  478. y_shift += Input.Distance(Buttons.RightStickY, maxLookSpeed);
  479. Yshift -= y_shift;
  480. degrees = (degrees + (int)x_shift) % 360;
  481. Yshift = MathHelper.Clamp(Yshift, -80, 80);
  482. if (leftdistY == 0)
  483. {
  484. leftdistY = Input.Distance(maxMoveSpeed);
  485. }
  486. if (leftdistX == 0)
  487. {
  488. leftdistX = Input.Distance(maxMoveSpeed);
  489. }
  490. if (Input.Button(Buttons.Up))
  491. {
  492. camPosition.X += (float)Math.Cos(MathHelper.ToRadians(degrees)) * leftdistY / 10;
  493. camPosition.Z += (float)Math.Sin(MathHelper.ToRadians(degrees)) * leftdistY / 10;
  494. camPosition.Y -= Yshift / 50;
  495. }
  496. if (Input.Button(Buttons.Down))
  497. {
  498. camPosition.X -= (float)Math.Cos(MathHelper.ToRadians(degrees)) * leftdistY / 10;
  499. camPosition.Z -= (float)Math.Sin(MathHelper.ToRadians(degrees)) * leftdistY / 10;
  500. camPosition.Y += Yshift / 50;
  501. }
  502. if (Input.Button(Buttons.Left))
  503. {
  504. camPosition.X += (float)Math.Cos(MathHelper.ToRadians(degrees - 90)) * leftdistX / 10;
  505. camPosition.Z += (float)Math.Sin(MathHelper.ToRadians(degrees - 90)) * leftdistX / 10;
  506. }
  507. if (Input.Button(Buttons.Right))
  508. {
  509. camPosition.X += (float)Math.Cos(MathHelper.ToRadians(degrees + 90)) * leftdistX / 10;
  510. camPosition.Z += (float)Math.Sin(MathHelper.ToRadians(degrees + 90)) * leftdistX / 10;
  511. }
  512. //Input.LockMouse();
  513. camTarget.X = camPosition.X + (float)Math.Cos(MathHelper.ToRadians(degrees)) * camDistance;
  514. camTarget.Z = camPosition.Z + (float)Math.Sin(MathHelper.ToRadians(degrees)) * camDistance;
  515. camTarget.Y = camPosition.Y - Yshift / 5;
  516. viewMatrix = Matrix.CreateLookAt(camPosition, camTarget,
  517. Vector3.Up);
  518. #endregion
  519. }
  520. private static void DrawGeometry()
  521. {
  522. Memory.spriteBatch.GraphicsDevice.Clear(Color.Black);
  523. Memory.graphics.GraphicsDevice.RasterizerState = RasterizerState.CullNone;
  524. Memory.graphics.GraphicsDevice.BlendState = BlendState.AlphaBlend;
  525. Memory.graphics.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
  526. Memory.graphics.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp;
  527. ate.Projection = projectionMatrix; ate.View = viewMatrix; ate.World = worldMatrix;
  528. effect.TextureEnabled = true;
  529. for(int n = 0; n < modelGroups.Length; n++)
  530. foreach (var b in modelGroups[n].models)
  531. {
  532. var vpt = GetVertexBuffer(b);
  533. if (n == 3 && skyRotators[Memory.encounters[Memory.battle_encounter].Scenario] != 0)
  534. CreateRotation(vpt);
  535. if (vpt == null) continue;
  536. int localVertexIndex = 0;
  537. for (int i = 0; i < vpt.Item1.Length; i++)
  538. {
  539. ate.Texture = textures[vpt.Item1[i].clut]; //provide texture per-face
  540. foreach (var pass in ate.CurrentTechnique.Passes)
  541. {
  542. pass.Apply();
  543. if (vpt.Item1[i].bQuad)
  544. {
  545. Memory.graphics.GraphicsDevice.DrawUserPrimitives(primitiveType: PrimitiveType.TriangleList,
  546. vertexData: vpt.Item2, vertexOffset: localVertexIndex, primitiveCount: 2);
  547. localVertexIndex += 6;
  548. }
  549. else
  550. {
  551. Memory.graphics.GraphicsDevice.DrawUserPrimitives(primitiveType: PrimitiveType.TriangleList,
  552. vertexData: vpt.Item2, vertexOffset: localVertexIndex, primitiveCount: 1);
  553. localVertexIndex += 3;
  554. }
  555. }
  556. }
  557. }
  558. Memory.SpriteBatchStartAlpha();
  559. Memory.font.RenderBasicText(Font.CipherDirty($"Encounter ready at: {Memory.battle_encounter}"), 0, 0, 1, 1, 0, 1);
  560. Memory.font.RenderBasicText(Font.CipherDirty($"Debug variable: {DEBUGframe}"), 20, 30 * 1, 1, 1, 0, 1);
  561. Memory.font.RenderBasicText(Font.CipherDirty($"1000/deltaTime milliseconds: {1000/Memory.gameTime.ElapsedGameTime.Milliseconds}"), 20, 30 * 2, 1, 1, 0, 1);
  562. Memory.SpriteBatchEnd();
  563. }
  564. private static void CreateRotation(Tuple<Stage_GeometryInfoSupplier[], VertexPositionTexture[]> vpt)
  565. {
  566. localRotator += (short)skyRotators[Memory.encounters[Memory.battle_encounter].Scenario]/4096f * Memory.gameTime.ElapsedGameTime.Milliseconds;
  567. if (localRotator <= 0)
  568. return;
  569. for (int i = 0; i < vpt.Item2.Length; i++)
  570. vpt.Item2[i].Position = Vector3.Transform(vpt.Item2[i].Position, Matrix.CreateRotationY(MathHelper.ToRadians(localRotator)));
  571. }
  572. /// <summary>
  573. /// Converts requested Model data (Stage group geometry) into MonoGame VertexPositionTexture
  574. /// </summary>
  575. /// <param name="model"></param>
  576. /// <returns></returns>
  577. private static Tuple<Stage_GeometryInfoSupplier[], VertexPositionTexture[]> GetVertexBuffer(Model model)
  578. {
  579. List<VertexPositionTexture> vptDynamic = new List<VertexPositionTexture>();
  580. List<Stage_GeometryInfoSupplier> bs_renderer_supplier = new List<Stage_GeometryInfoSupplier>();
  581. if (model.vertices == null) return null;
  582. for (int i = 0; i < model.triangles.Length; i++)
  583. {
  584. Vertex A = model.vertices[model.triangles[i].A];
  585. Vertex B = model.vertices[model.triangles[i].B];
  586. Vertex C = model.vertices[model.triangles[i].C];
  587. vptDynamic.Add(new VertexPositionTexture(new Vector3((float)A.X / 100, (float)A.Y / 100, (float)A.Z / 100),
  588. CalculateUV(model.triangles[i].U2, model.triangles[i].V2, model.triangles[i].TexturePage, textureInterface.GetWidth)));
  589. vptDynamic.Add(new VertexPositionTexture(new Vector3((float)B.X / 100, (float)B.Y / 100, (float)B.Z / 100),
  590. CalculateUV(model.triangles[i].U3, model.triangles[i].V3, model.triangles[i].TexturePage, textureInterface.GetWidth)));
  591. vptDynamic.Add(new VertexPositionTexture(new Vector3((float)C.X / 100, (float)C.Y / 100, (float)C.Z / 100),
  592. CalculateUV(model.triangles[i].U1, model.triangles[i].V1, model.triangles[i].TexturePage, textureInterface.GetWidth)));
  593. bs_renderer_supplier.Add(new Stage_GeometryInfoSupplier()
  594. {
  595. bQuad = false,
  596. clut = model.triangles[i].clut,
  597. texPage = model.triangles[i].TexturePage
  598. });
  599. }
  600. for (int i = 0; i < model.quads.Length; i++)
  601. {
  602. //I have to re-trangulate it. Fortunately I had been working on this lately
  603. Vertex A = model.vertices[model.quads[i].A]; //1
  604. Vertex B = model.vertices[model.quads[i].B]; //2
  605. Vertex C = model.vertices[model.quads[i].C]; //4
  606. Vertex D = model.vertices[model.quads[i].D]; //3
  607. //triangluation wing-reorder
  608. //1 2 4
  609. vptDynamic.Add(new VertexPositionTexture(new Vector3((float)A.X / 100, (float)A.Y / 100, (float)A.Z / 100),
  610. CalculateUV(model.quads[i].U1, model.quads[i].V1, model.quads[i].TexturePage, textureInterface.GetWidth)));
  611. vptDynamic.Add(new VertexPositionTexture(new Vector3((float)B.X / 100, (float)B.Y / 100, (float)B.Z / 100),
  612. CalculateUV(model.quads[i].U2, model.quads[i].V2, model.quads[i].TexturePage, textureInterface.GetWidth)));
  613. vptDynamic.Add(new VertexPositionTexture(new Vector3((float)D.X / 100, (float)D.Y / 100, (float)D.Z / 100),
  614. CalculateUV(model.quads[i].U4, model.quads[i].V4, model.quads[i].TexturePage, textureInterface.GetWidth)));
  615. //1 3 4
  616. vptDynamic.Add(new VertexPositionTexture(new Vector3((float)A.X / 100, (float)A.Y / 100, (float)A.Z / 100),
  617. CalculateUV(model.quads[i].U1, model.quads[i].V1, model.quads[i].TexturePage, textureInterface.GetWidth)));
  618. vptDynamic.Add(new VertexPositionTexture(new Vector3((float)C.X / 100, (float)C.Y / 100, (float)C.Z / 100),
  619. CalculateUV(model.quads[i].U3, model.quads[i].V3, model.quads[i].TexturePage, textureInterface.GetWidth)));
  620. vptDynamic.Add(new VertexPositionTexture(new Vector3((float)D.X / 100, (float)D.Y / 100, (float)D.Z / 100),
  621. CalculateUV(model.quads[i].U4, model.quads[i].V4, model.quads[i].TexturePage, textureInterface.GetWidth)));
  622. bs_renderer_supplier.Add(new Stage_GeometryInfoSupplier()
  623. {
  624. bQuad = true,
  625. clut = model.quads[i].clut,
  626. texPage = model.quads[i].TexturePage
  627. });
  628. }
  629. return new Tuple<Stage_GeometryInfoSupplier[], VertexPositionTexture[]>
  630. (bs_renderer_supplier.ToArray(), vptDynamic.ToArray());
  631. }
  632. private static Vector2 CalculateUV(byte U, byte V, byte texPage, int texWidth)
  633. {
  634. //old code from my wiki page
  635. //Float U = (float)U_Byte / (float)(TIM_Texture_Width * 2) + ((float)Texture_Page / (TIM_Texture_Width * 2));
  636. float fU = (float)U / texWidth + (((float)texPage * 128) / texWidth);
  637. float fV = V / 256.0f;
  638. return new Vector2(fU, fV);
  639. }
  640. private static void InitBattle()
  641. {
  642. //MakiExtended.Debugger_Spawn();
  643. //MakiExtended.Debugger_Feed(typeof(Module_battle_debug), System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
  644. Input.OverrideLockMouse=true;
  645. Input.CurrentMode = Input.MouseLockMode.Center;
  646. Init_debugger_battle.Encounter enc = Memory.encounters[Memory.battle_encounter];
  647. int stage = enc.Scenario;
  648. battlename = $"a0stg{stage.ToString("000")}.x";
  649. Console.WriteLine($"BS_DEBUG: Loading stage {battlename}");
  650. Console.WriteLine($"BS_DEBUG/ENC: Encounter: {Memory.battle_encounter}\t cEnemies: {enc.EnabledEnemy}\t Enemies: {string.Join(",", enc.BEnemies.Where(x => x != 0x00).Select(x => $"{x}").ToArray())}");
  651. //init renderer
  652. effect = new BasicEffect(Memory.graphics.GraphicsDevice);
  653. camTarget = new Vector3(41.91198f, 33.59995f, 6.372305f);
  654. camPosition = new Vector3(40.49409f, 39.70397f, -43.321299f);
  655. projectionMatrix = Matrix.CreatePerspectiveFieldOfView(
  656. MathHelper.ToRadians(45f),
  657. Memory.graphics.GraphicsDevice.DisplayMode.AspectRatio,
  658. 1f, 1000f);
  659. viewMatrix = Matrix.CreateLookAt(camPosition, camTarget,
  660. new Vector3(0f, 1f, 0f));// Y up
  661. worldMatrix = Matrix.CreateWorld(camTarget, Vector3.
  662. Forward, Vector3.Up);
  663. battleModule++;
  664. RasterizerState rasterizerState = new RasterizerState
  665. {
  666. CullMode = CullMode.None
  667. };
  668. ate = new AlphaTestEffect(Memory.graphics.GraphicsDevice)
  669. {
  670. Projection = projectionMatrix,
  671. View = viewMatrix,
  672. World = worldMatrix
  673. };
  674. return;
  675. }
  676. #region fileParsing
  677. private static void ReadData()
  678. {
  679. ArchiveWorker aw = new ArchiveWorker(Memory.Archives.A_BATTLE);
  680. string[] test = aw.GetListOfFiles();
  681. battlename = test.First(x => x.ToLower().Contains(battlename));
  682. stageBuffer = ArchiveWorker.GetBinaryFile(Memory.Archives.A_BATTLE, battlename);
  683. pbs = new PseudoBufferedStream(stageBuffer);
  684. bs_cameraPointer = GetCameraPointer();
  685. pbs.Seek(bs_cameraPointer, 0);
  686. ReadCamera();
  687. uint sectionCounter = pbs.ReadUInt();
  688. if (sectionCounter != 6)
  689. {
  690. Console.WriteLine($"BS_PARSER_PRE_OBJECTSECTION: Main geometry section has no 6 pointers at: {pbs.Tell()}");
  691. battleModule++;
  692. return;
  693. }
  694. MainGeometrySection MainSection = ReadObjectGroupPointers();
  695. ObjectsGroup[] objectsGroups = new ObjectsGroup[4]
  696. {
  697. ReadObjectsGroup(MainSection.Group1Pointer),
  698. ReadObjectsGroup(MainSection.Group2Pointer),
  699. ReadObjectsGroup(MainSection.Group3Pointer),
  700. ReadObjectsGroup(MainSection.Group4Pointer)
  701. };
  702. modelGroups = new ModelGroup[4]
  703. {
  704. ReadModelGroup(objectsGroups[0].objectListPointer),
  705. ReadModelGroup(objectsGroups[1].objectListPointer),
  706. ReadModelGroup(objectsGroups[2].objectListPointer),
  707. ReadModelGroup(objectsGroups[3].objectListPointer)
  708. };
  709. ReadTexture(MainSection.TexturePointer);
  710. ReadCharacters();
  711. ReadMonster();
  712. battleModule++;
  713. }
  714. public static int DEBUG = 0;
  715. private static float frameperFPS = 0.0f;
  716. private static void ReadCharacters()
  717. {
  718. CharacterInstances = new List<CharacterInstanceInformation>
  719. {
  720. new CharacterInstanceInformation()
  721. {
  722. Data = ReadCharacterData(0,0,0),
  723. animationSystem = new AnimationSystem(){ AnimationQueue = new List<int>()},
  724. characterId = 0,
  725. },
  726. new CharacterInstanceInformation()
  727. {
  728. Data = ReadCharacterData(1,3,8),
  729. animationSystem = new AnimationSystem(){ AnimationQueue = new List<int>()},
  730. characterId = 1
  731. },
  732. new CharacterInstanceInformation()
  733. {
  734. Data = ReadCharacterData(2,6,13),
  735. animationSystem = new AnimationSystem(){ AnimationQueue = new List<int>()},
  736. characterId = 2
  737. },
  738. new CharacterInstanceInformation()
  739. {
  740. Data = ReadCharacterData(3,7,18),
  741. animationSystem = new AnimationSystem(){ AnimationQueue = new List<int>()},
  742. characterId = 3
  743. },
  744. new CharacterInstanceInformation()
  745. {
  746. Data = ReadCharacterData(4,9,23),
  747. animationSystem = new AnimationSystem(){ AnimationQueue = new List<int>()},
  748. characterId = 4
  749. },
  750. new CharacterInstanceInformation()
  751. {
  752. Data = ReadCharacterData(5,11,28),
  753. animationSystem = new AnimationSystem(){ AnimationQueue = new List<int>()},
  754. characterId = 5
  755. },
  756. new CharacterInstanceInformation()
  757. {
  758. Data = ReadCharacterData(6,14,33),
  759. animationSystem = new AnimationSystem(){ AnimationQueue = new List<int>()},
  760. characterId = 6
  761. },
  762. new CharacterInstanceInformation()
  763. {
  764. Data = ReadCharacterData(8,17,35),
  765. animationSystem = new AnimationSystem(){ AnimationQueue = new List<int>()},
  766. characterId = 8
  767. },
  768. new CharacterInstanceInformation()
  769. {
  770. Data = ReadCharacterData(9,19,37),
  771. animationSystem = new AnimationSystem(){ AnimationQueue = new List<int>()},
  772. characterId = 9
  773. },
  774. new CharacterInstanceInformation()
  775. {
  776. Data = ReadCharacterData(10,21,39),
  777. animationSystem = new AnimationSystem(){ AnimationQueue = new List<int>()},
  778. characterId = 10
  779. },
  780. new CharacterInstanceInformation()
  781. {
  782. Data = ReadCharacterData(7,16,-1),
  783. animationSystem = new AnimationSystem(){ AnimationQueue = new List<int>()},
  784. characterId = 7
  785. }
  786. };
  787. }
  788. private static CharacterData ReadCharacterData(int characterId, int alternativeCostumeId, int weaponId)
  789. {
  790. var character = new Debug_battleDat(characterId, Debug_battleDat.EntityType.Character, alternativeCostumeId);
  791. Debug_battleDat weapon;
  792. if (characterId == 1 || characterId == 9)
  793. weapon = new Debug_battleDat(characterId, Debug_battleDat.EntityType.Weapon, weaponId, character);
  794. else if (weaponId != -1) weapon = new Debug_battleDat(characterId, Debug_battleDat.EntityType.Weapon, weaponId);
  795. else weapon = null;
  796. return new CharacterData()
  797. {
  798. character = character,
  799. weapon = weapon
  800. };
  801. }
  802. /// <summary>
  803. /// This method is responsible to read/parse the enemy data. It holds the result in monstersData[]
  804. /// This method was designed to read only one instance of enemy. A list called EnemyInstance holds data information for each enemy
  805. /// </summary>
  806. private static void ReadMonster()
  807. {
  808. //for(int i = 0; i<199; i++)
  809. //{
  810. // var dcd = new Debug_battleDat(i, Debug_battleDat.EntityType.Monster);
  811. // var ecd = dcd.skeleton.GetScale.Y;
  812. // Console.WriteLine($"{i}/{ecd}");
  813. //}
  814. Init_debugger_battle.Encounter enc = Memory.encounters[Memory.battle_encounter];
  815. if (enc.EnabledEnemy == 0)
  816. {
  817. monstersData = new Debug_battleDat[0];
  818. return;
  819. }
  820. var DistinctMonsterPointers = enc.BEnemies.GroupBy(x => x).ToArray();
  821. monstersData = new Debug_battleDat[DistinctMonsterPointers.Count()];
  822. for (int n = 0; n < monstersData.Length; n++)
  823. monstersData[n] = new Debug_battleDat(DistinctMonsterPointers[n].Key, Debug_battleDat.EntityType.Monster);
  824. if (monstersData == null)
  825. monstersData = new Debug_battleDat[0];
  826. EnemyInstances = new List<EnemyInstanceInformation>();
  827. for(int i = 0; i<8; i++)
  828. if (MakiExtended.GetBit(enc.EnabledEnemy, 7-i))
  829. EnemyInstances.Add(new EnemyInstanceInformation() { Data = monstersData.Where(x => x.GetId == enc.BEnemies[i] ).First(),
  830. bIsHidden =MakiExtended.GetBit(enc.HiddenEnemies, 7-i),
  831. bIsActive = true,
  832. index = (byte)(7-i),
  833. bIsUntargetable = MakiExtended.GetBit(enc.UntargetableEnemy, 7-i),
  834. animationSystem = new AnimationSystem() { AnimationQueue= new List<int>()}}
  835. );
  836. }
  837. /// <summary>
  838. /// Method designed for Stage texture loading.
  839. /// </summary>
  840. /// <param name="texturePointer">Absolute pointer to TIM texture header in stageBuffer</param>
  841. private static void ReadTexture(uint texturePointer)
  842. {
  843. textureInterface = new TIM2(stageBuffer, texturePointer);
  844. textures = new Texture2D[textureInterface.GetClutCount];
  845. for (ushort i = 0; i < textureInterface.GetClutCount; i++)
  846. {
  847. byte[] b = textureInterface.CreateImageBuffer(textureInterface.GetClutColors(i));
  848. Texture2D tex = new Texture2D(Memory.spriteBatch.GraphicsDevice,
  849. textureInterface.GetWidth, textureInterface.GetHeight, false, SurfaceFormat.Color);
  850. tex.SetData(b);
  851. textures[i] = tex;
  852. }
  853. }
  854. /// <summary>
  855. /// Reads Stage model groups pointers and reads/parses them individually.
  856. /// Group0 is stage ground. It's always enabled except special sequences like GFs
  857. /// Group1 is main geometry. It's prior to Time Compression deformation
  858. /// Group2 is main/additional geometry. It's prior to Time Compression deformation
  859. /// Group3 is Sky. It's NON-prior to Time Compression, but may be modified by SkyRotators and/or TimeCompression last Stage skyRotation multiplier
  860. /// </summary>
  861. /// <param name="pointer"></param>
  862. /// <returns></returns>
  863. private static ModelGroup ReadModelGroup(uint pointer)
  864. {
  865. pbs.Seek(pointer, System.IO.SeekOrigin.Begin);
  866. uint modelsCount = pbs.ReadUInt();
  867. Model[] models = new Model[modelsCount];
  868. uint[] modelPointers = new uint[modelsCount];
  869. for (int i = 0; i < modelsCount; i++)
  870. modelPointers[i] = pointer + pbs.ReadUInt();
  871. for (int i = 0; i < modelsCount; i++)
  872. models[i] = ReadModel(modelPointers[i]);
  873. return new ModelGroup() { models = models };
  874. }
  875. /// <summary>
  876. /// This is the main class that reads given Stage geometry group. It stores the data into Model structure
  877. /// </summary>
  878. /// <param name="pointer">absolute pointer in pbs[deprecated] buffer for given Stage geometry group</param>
  879. /// <returns></returns>
  880. private static Model ReadModel(uint pointer)
  881. {
  882. bool bSpecial = false;
  883. pbs.Seek(pointer, System.IO.SeekOrigin.Begin);
  884. uint header = MakiExtended.UintLittleEndian(pbs.ReadUInt());
  885. if (header != 0x01000100) //those may be some switches, but I don't know what they mean
  886. {
  887. Console.WriteLine("WARNING- THIS STAGE IS DIFFERENT! It has weird object section. INTERESTING, TO REVERSE!");
  888. bSpecial = true;
  889. }
  890. ushort verticesCount = pbs.ReadUShort();
  891. Vertex[] vertices = new Vertex[verticesCount];
  892. for (int i = 0; i < verticesCount; i++)
  893. vertices[i] = ReadVertex();
  894. if (bSpecial && Memory.encounters[Memory.battle_encounter].Scenario == 20)
  895. return new Model();
  896. pbs.Seek((pbs.Tell() % 4) + 4, System.IO.SeekOrigin.Current);
  897. ushort trianglesCount = pbs.ReadUShort();
  898. ushort quadsCount = pbs.ReadUShort();
  899. pbs.Seek(4, System.IO.SeekOrigin.Current);
  900. Triangle[] triangles = new Triangle[trianglesCount];
  901. Quad[] quads = new Quad[quadsCount];
  902. if (trianglesCount > 0)
  903. for (int i = 0; i < trianglesCount; i++)
  904. triangles[i] = ReadTriangle();
  905. if (quadsCount > 0)
  906. for (int i = 0; i < quadsCount; i++)
  907. quads[i] = ReadQuad();
  908. return new Model()
  909. {
  910. vertices = vertices,
  911. triangles = triangles,
  912. quads = quads
  913. };
  914. }
  915. private static Triangle ReadTriangle()
  916. =>
  917. new Triangle()
  918. {
  919. A = pbs.ReadUShort(),
  920. B = pbs.ReadUShort(),
  921. C = pbs.ReadUShort(),
  922. U1 = pbs.ReadByte(),
  923. V1 = pbs.ReadByte(),
  924. U2 = pbs.ReadByte(),
  925. V2 = pbs.ReadByte(),
  926. clut = GetClutId(pbs.ReadUShort()),
  927. U3 = pbs.ReadByte(),
  928. V3 = pbs.ReadByte(),
  929. TexturePage = GetTexturePage(pbs.ReadByte()),
  930. bHide = pbs.ReadByte(),
  931. Red = pbs.ReadByte(),
  932. Green = pbs.ReadByte(),
  933. Blue = pbs.ReadByte(),
  934. GPU = pbs.ReadByte()
  935. };
  936. private static Quad ReadQuad()
  937. => new Quad()
  938. {
  939. A = pbs.ReadUShort(),
  940. B = pbs.ReadUShort(),
  941. C = pbs.ReadUShort(),
  942. D = pbs.ReadUShort(),
  943. U1 = pbs.ReadByte(),
  944. V1 = pbs.ReadByte(),
  945. clut = GetClutId(pbs.ReadUShort()),
  946. U2 = pbs.ReadByte(),
  947. V2 = pbs.ReadByte(),
  948. TexturePage = GetTexturePage(pbs.ReadByte()),
  949. bHide = pbs.ReadByte(),
  950. U3 = pbs.ReadByte(),
  951. V3 = pbs.ReadByte(),
  952. U4 = pbs.ReadByte(),
  953. V4 = pbs.ReadByte(),
  954. Red = pbs.ReadByte(),
  955. Green = pbs.ReadByte(),
  956. Blue = pbs.ReadByte(),
  957. GPU = pbs.ReadByte()
  958. };
  959. private static Vertex ReadVertex()
  960. => new Vertex()
  961. {
  962. X = pbs.ReadShort(),
  963. Y = pbs.ReadShort(),
  964. Z = pbs.ReadShort()
  965. };
  966. private static ObjectsGroup ReadObjectsGroup(uint pointer)
  967. {
  968. pbs.Seek(pointer, System.IO.SeekOrigin.Begin);
  969. return new ObjectsGroup()
  970. {
  971. numberOfSections = pbs.ReadUInt(),
  972. settings1Pointer = pointer + pbs.ReadUInt(),
  973. objectListPointer = pointer + pbs.ReadUInt(),
  974. settings2Pointer = pointer + pbs.ReadUInt(),
  975. relativeEOF = pointer + pbs.ReadUInt()
  976. };
  977. }
  978. private static MainGeometrySection ReadObjectGroupPointers()
  979. {
  980. int basePointer = (int)pbs.Tell() - 4;
  981. uint objectGroup_1 = (uint)basePointer + pbs.ReadUInt();
  982. uint objectGroup_2 = (uint)basePointer + pbs.ReadUInt();
  983. uint objectGroup_3 = (uint)basePointer + pbs.ReadUInt();
  984. uint objectGroup_4 = (uint)basePointer + pbs.ReadUInt();
  985. uint TextureUnused = (uint)basePointer + pbs.ReadUInt();
  986. uint Texture = (uint)basePointer + pbs.ReadUInt();
  987. uint EOF = (uint)basePointer + pbs.ReadUInt();
  988. if (EOF != pbs.Length)
  989. throw new Exception("BS_PARSER_ERROR_LENGTH: Geometry EOF pointer is other than buffered filesize");
  990. return new MainGeometrySection()
  991. {
  992. Group1Pointer = objectGroup_1,
  993. Group2Pointer = objectGroup_2,
  994. Group3Pointer = objectGroup_3,
  995. Group4Pointer = objectGroup_4,
  996. TextureUNUSEDPointer = TextureUnused,
  997. TexturePointer = Texture,
  998. EOF = EOF
  999. }; //EOF = EOF; beauty of language
  1000. }
  1001. /// <summary>
  1002. /// Gets vanilla engine camera pointers. A team that rewrote the game into PC just left PlayStation MIPS data inside files
  1003. /// and therefore their code is to skip given hardcoded data which in fact are PS compiled instructions
  1004. /// This data is naturally read by PlayStation in original console release.
  1005. /// </summary>
  1006. /// <returns>Camera pointer (data after PlayStation MIPS)</returns>
  1007. private static uint GetCameraPointer()
  1008. {
  1009. int[] _x5D4 = {4,5,9,12,13,14,15,21,22,23,24,26,
  1010. 29,32,33,34,35,36,39,40,50,53,55,61,62,63,64,65,66,67,68,69,70,
  1011. 71,72,73,75,78,82,83,85,86,87,88,89,90,91,94,96,97,98,99,100,105,
  1012. 106,121,122,123,124,125,126,127,135,138,141,144,145,148,149,150,
  1013. 151,158,160};
  1014. int[] _x5D8 = {
  1015. 0,1,2,3,6,7,10,11,17,18,25,27,28,38,41,42,43,47,49,57,58,59,60,74,
  1016. 76,77,80,81,84,93,95,101,102,103,104,109,110,111,112,113,114,115,116,
  1017. 117,118,119,120,128,129,130,131,132,133,134,139,140,143,146,152,153,154,
  1018. 155,156,159,161,162};
  1019. int _5d4 = _x5D4.Count(x => x == Memory.encounters[Memory.battle_encounter].Scenario);
  1020. int _5d8 = _x5D8.Count(x => x == Memory.encounters[Memory.battle_encounter].Scenario);
  1021. if (_5d4 > 0) return 0x5D4;
  1022. if (_5d8 > 0) return 0x5D8;
  1023. switch (Memory.encounters[Memory.battle_encounter].Scenario)
  1024. {
  1025. case 8:
  1026. case 48:
  1027. case 79:
  1028. return 0x618;
  1029. case 16:
  1030. return 0x628;
  1031. case 19:
  1032. return 0x644;
  1033. case 20:
  1034. return 0x61c;
  1035. case 30:
  1036. case 31:
  1037. return 0x934;
  1038. case 37:
  1039. return 0xcc0;
  1040. case 44:
  1041. case 45:
  1042. case 46:
  1043. return 0x9A4;
  1044. case 51:
  1045. case 52:
  1046. case 107:
  1047. case 108:
  1048. return 0x600;
  1049. case 54:
  1050. case 56:
  1051. return 0x620;
  1052. case 92:
  1053. return 0x83c;
  1054. case 136:
  1055. return 0x5fc;
  1056. case 137:
  1057. return 0xFDC;
  1058. case 142:
  1059. return 0x183C;
  1060. case 147:
  1061. return 0x10f0;
  1062. case 157:
  1063. return 0x638;
  1064. }
  1065. throw new Exception("0xFFF, unknown pointer!");
  1066. }
  1067. //TODO
  1068. private static void ReadCamera()
  1069. {
  1070. Memory.BS_CameraStruct = new Memory.VIII_cameraMemoryStruct();
  1071. uint cCameraHeaderSector = pbs.ReadUShort();
  1072. //if (cCameraHeaderSector != 0x2)
  1073. // ; //error handler?
  1074. uint pCameraSetting = pbs.ReadUShort();
  1075. uint pCameraAnimationCollection = pbs.ReadUShort();
  1076. uint sCameraDataSize = pbs.ReadUShort();
  1077. //Camera settings parsing?
  1078. BattleCameraSettings bcs = new BattleCameraSettings() { unk = pbs.ReadBytes(24) };
  1079. //end of camera settings parsing
  1080. pbs.Seek(bs_cameraPointer, 0);
  1081. pbs.Seek(pCameraAnimationCollection, System.IO.SeekOrigin.Current);
  1082. BattleCameraCollection bcc = new BattleCameraCollection { cAnimCollectionCount = pbs.ReadUShort() };
  1083. BattleCameraSet[] bcset = new BattleCameraSet[bcc.cAnimCollectionCount];
  1084. bcc.battleCameraSet = bcset;
  1085. for (int i = 0; i < bcc.cAnimCollectionCount; i++)
  1086. bcset[i] = new BattleCameraSet() { globalSetPointer = (uint)(pbs.Tell() + pbs.ReadUShort() - i * 2 - 2) };
  1087. bcc.pCameraEOF = pbs.ReadUShort();
  1088. for (int i = 0; i < bcc.cAnimCollectionCount; i++)
  1089. {
  1090. pbs.Seek(bcc.battleCameraSet[i].globalSetPointer, 0);
  1091. bcc.battleCameraSet[i].animPointers = new uint[8];
  1092. for (int n = 0; n < bcc.battleCameraSet[i].animPointers.Length; n++)
  1093. bcc.battleCameraSet[i].animPointers[n] = (uint)(pbs.Tell() + pbs.ReadUShort() * 2 - n * 2);
  1094. bcc.battleCameraSet[i].cameraAnimation = new CameraAnimation[bcc.battleCameraSet[i].animPointers.Length];
  1095. for (int n = 0; n < bcc.battleCameraSet[i].animPointers.Length; n++)
  1096. {
  1097. pbs.Seek(bcc.battleCameraSet[i].animPointers[n], 0);
  1098. bcc.battleCameraSet[i].cameraAnimation[n] = new CameraAnimation() { header = pbs.ReadUShort() };
  1099. }
  1100. }
  1101. battleCamera = new BattleCamera() { battleCameraCollection = bcc, battleCameraSettings = bcs };
  1102. //DEBUG DELETE ME
  1103. ReadAnimation(7);
  1104. //END OF DEBUG
  1105. pbs.Seek(bs_cameraPointer + sCameraDataSize, 0); //debug out
  1106. }
  1107. //WIP debug only, used for reverse engineering TODO
  1108. private static void ReadAnimation(int animId)
  1109. {
  1110. Memory.BS_CameraStruct.camAnimId = (byte)animId;
  1111. if ((animId >> 4) >= battleCamera.battleCameraCollection.cAnimCollectionCount)
  1112. return;
  1113. var pointer = battleCamera.battleCameraCollection.battleCameraSet[animId >> 4].animPointers[animId & 0xF];
  1114. pbs.Seek(pointer, 0);
  1115. ushort eax = pbs.ReadUShort();
  1116. Memory.BS_CameraStruct.mainController = eax; //[esi+2], ax
  1117. if (eax == 0xFFFF)
  1118. return;
  1119. ushort ebx = eax;
  1120. eax = (ushort)((eax >> 6) & 3);
  1121. eax--;
  1122. if (eax == 0)
  1123. {
  1124. eax = 0x200;
  1125. Memory.BS_CameraStruct.thirdWordController = Memory.BS_CameraStruct.secondWordController = eax;
  1126. goto structFullfiled;
  1127. }
  1128. eax--;
  1129. if (eax == 0)
  1130. {
  1131. eax = pbs.ReadUShort();
  1132. Memory.BS_CameraStruct.thirdWordController = Memory.BS_CameraStruct.secondWordController = eax;
  1133. goto structFullfiled;
  1134. }
  1135. eax--;
  1136. if (eax != 0)
  1137. goto structFullfiled;
  1138. Memory.BS_CameraStruct.secondWordController = pbs.ReadUShort(); //esi+4
  1139. Memory.BS_CameraStruct.thirdWordController = pbs.ReadUShort(); //esi+6
  1140. structFullfiled:
  1141. eax = ebx;
  1142. eax = (ushort)((eax >> 8) & 3);
  1143. switch (eax)
  1144. {
  1145. case 0:
  1146. break;
  1147. case 1:
  1148. break;
  1149. case 2:
  1150. break;
  1151. case 3:
  1152. break;
  1153. }
  1154. //default here
  1155. //there's now some operations to copy next vars
  1156. //see BS_Camera_ReadAnimation+CC 00103B8C
  1157. }
  1158. #endregion
  1159. }
  1160. }