module_field_debug.cs 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122
  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. internal 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 List<Tile> tiles;
  16. private struct Tile
  17. {
  18. public short x, y;
  19. public ushort z;
  20. public byte texID; // 4 bits
  21. public byte pallID; //[6-10]
  22. public byte srcx, srcy;
  23. public byte layId;
  24. public byte blendType;
  25. public byte state;
  26. public byte parameter;
  27. public byte blend1;
  28. public byte blend2;
  29. }
  30. private struct SJSM
  31. {
  32. public byte cDoorEntity;
  33. public byte cWalkmeshEntity;
  34. public byte cBackgroundEntity;
  35. public byte cOtherEntity;
  36. public ushort offsetSecOne;
  37. public ushort offsetScriptData;
  38. public EntryPointEntity[] EntityEntryPoints;
  39. public EntryPointScript[] entryPointScripts;
  40. public int[] ScriptData;
  41. }
  42. private static List<ScriptEntry> ScriptSystem;
  43. private static string[] symbolNames;
  44. private static List<int> Stack;
  45. private struct EntryPointEntity
  46. {
  47. public byte scriptCount;
  48. public byte label;
  49. public string labelASM;
  50. }
  51. private struct EntryPointScript
  52. {
  53. public ushort position;
  54. public byte flag;
  55. }
  56. private struct ScriptOpcode
  57. {
  58. public ushort opcodeBinary;
  59. public string opcodeASM;
  60. public JSMopcodes opcode;
  61. public ushort parameter;
  62. }
  63. private struct ScriptEntry //final struct
  64. {
  65. public ushort Entity;
  66. public string ScriptName;
  67. public ushort ID;
  68. public ushort localID;
  69. public ScriptOpcode[] Scripts;
  70. }
  71. private static SJSM jsm;
  72. private static int width, height;
  73. private enum JSMopcodes
  74. {
  75. NOP,
  76. CAL,
  77. JMP,
  78. JPF,
  79. GJMP,
  80. LBL,
  81. RET,
  82. PSHN_L,
  83. PSHI_L,
  84. POPI_L,
  85. PSHM_B,
  86. POPM_B,
  87. PSHM_W,
  88. POPM_W,
  89. PSHM_L,
  90. POPM_L,
  91. PSHSM_B,
  92. PSHSM_W,
  93. PSHSM_L,
  94. PSHAC,
  95. REQ,
  96. REQSW,
  97. REQEW,
  98. PREQ,
  99. PREQSW,
  100. PREQEW,
  101. UNUSE,
  102. DEBUG,
  103. HALT,
  104. SET,
  105. SET3,
  106. IDLOCK,
  107. IDUNLOCK,
  108. EFFECTPLAY2,
  109. FOOTSTEP,
  110. JUMP,
  111. JUMP3,
  112. LADDERUP,
  113. LADDERDOWN,
  114. LADDERUP2,
  115. LADDERDOWN2,
  116. MAPJUMP,
  117. MAPJUMP3,
  118. SETMODEL,
  119. BASEANIME,
  120. ANIME,
  121. ANIMEKEEP,
  122. CANIME,
  123. CANIMEKEEP,
  124. RANIME,
  125. RANIMEKEEP,
  126. RCANIME,
  127. RCANIMEKEEP,
  128. RANIMELOOP,
  129. RCANIMELOOP,
  130. LADDERANIME,
  131. DISCJUMP,
  132. SETLINE,
  133. LINEON,
  134. LINEOFF,
  135. WAIT,
  136. MSPEED,
  137. MOVE,
  138. MOVEA,
  139. PMOVEA,
  140. CMOVE,
  141. FMOVE,
  142. PJUMPA,
  143. ANIMESYNC,
  144. ANIMESTOP,
  145. MESW,
  146. MES,
  147. MESSYNC,
  148. MESVAR,
  149. ASK,
  150. WINSIZE,
  151. WINCLOSE,
  152. UCON,
  153. UCOFF,
  154. MOVIE,
  155. MOVIESYNC,
  156. SETPC,
  157. DIR,
  158. DIRP,
  159. DIRA,
  160. PDIRA,
  161. SPUREADY,
  162. TALKON,
  163. TALKOFF,
  164. PUSHON,
  165. PUSHOFF,
  166. ISTOUCH,
  167. MAPJUMPO,
  168. MAPJUMPON,
  169. MAPJUMPOFF,
  170. SETMESSPEED,
  171. SHOW,
  172. HIDE,
  173. TALKRADIUS,
  174. PUSHRADIUS,
  175. AMESW,
  176. AMES,
  177. GETINFO,
  178. THROUGHON,
  179. THROUGHOFF,
  180. BATTLE,
  181. BATTLERESULT,
  182. BATTLEON,
  183. BATTLEOFF,
  184. KEYSCAN,
  185. KEYON,
  186. AASK,
  187. PGETINFO,
  188. DSCROLL,
  189. LSCROLL,
  190. CSCROLL,
  191. DSCROLLA,
  192. LSCROLLA,
  193. CSCROLLA,
  194. SCROLLSYNC,
  195. RMOVE,
  196. RMOVEA,
  197. RPMOVEA,
  198. RCMOVE,
  199. RFMOVE,
  200. MOVESYNC,
  201. CLEAR,
  202. DSCROLLP,
  203. LSCROLLP,
  204. CSCROLLP,
  205. LTURNR,
  206. LTURNL,
  207. CTURNR,
  208. CTURNL,
  209. ADDPARTY,
  210. SUBPARTY,
  211. CHANGEPARTY,
  212. REFRESHPARTY,
  213. SETPARTY,
  214. ISPARTY,
  215. ADDMEMBER,
  216. SUBMEMBER,
  217. ISMEMBER,
  218. LTURN,
  219. CTURN,
  220. PLTURN,
  221. PCTURN,
  222. JOIN,
  223. MESFORCUS,
  224. BGANIME,
  225. RBGANIME,
  226. RBGANIMELOOP,
  227. BGANIMESYNC,
  228. BGDRAW,
  229. BGOFF,
  230. BGANIMESPEED,
  231. SETTIMER,
  232. DISPTIMER,
  233. SHADETIMER,
  234. SETGETA,
  235. SETROOTTRANS,
  236. SETVIBRATE,
  237. STOPVIBRATE,
  238. MOVIEREADY,
  239. GETTIMER,
  240. FADEIN,
  241. FADEOUT,
  242. FADESYNC,
  243. SHAKE,
  244. SHAKEOFF,
  245. FADEBLACK,
  246. FOLLOWOFF,
  247. FOLLOWON,
  248. GAMEOVER,
  249. ENDING,
  250. SHADELEVEL,
  251. SHADEFORM,
  252. FMOVEA,
  253. FMOVEP,
  254. SHADESET,
  255. MUSICCHANGE,
  256. MUSICLOAD,
  257. FADENONE,
  258. POLYCOLOR,
  259. POLYCOLORALL,
  260. KILLTIMER,
  261. CROSSMUSIC,
  262. DUALMUSIC,
  263. EFFECTPLAY,
  264. EFFECTLOAD,
  265. LOADSYNC,
  266. MUSICSTOP,
  267. MUSICVOL,
  268. MUSICVOLTRANS,
  269. MUSICVOLFADE,
  270. ALLSEVOL,
  271. ALLSEVOLTRANS,
  272. ALLSEPOS,
  273. ALLSEPOSTRANS,
  274. SEVOL,
  275. SEVOLTRANS,
  276. SEPOS,
  277. SEPOSTRANS,
  278. SETBATTLEMUSIC,
  279. BATTLEMODE,
  280. SESTOP,
  281. BGANIMEFLAG,
  282. INITSOUND,
  283. BGSHADE,
  284. BGSHADESTOP,
  285. RBGSHADELOOP,
  286. DSCROLL2,
  287. LSCROLL2,
  288. CSCROLL2,
  289. DSCROLLA2,
  290. LSCROLLA2,
  291. CSCROLLA2,
  292. DSCROLLP2,
  293. LSCROLLP2,
  294. CSCROLLP2,
  295. SCROLLSYNC2,
  296. SCROLLMODE2,
  297. MENUENABLE,
  298. MENUDISABLE,
  299. FOOTSTEPON,
  300. FOOTSTEPOFF,
  301. FOOTSTEPOFFALL,
  302. FOOTSTEPCUT,
  303. PREMAPJUMP,
  304. USE,
  305. SPLIT,
  306. ANIMESPEED,
  307. RND,
  308. DCOLADD,
  309. DCOLSUB,
  310. TCOLADD,
  311. TCOLSUB,
  312. FCOLADD,
  313. FCOLSUB,
  314. COLSYNC,
  315. DOFFSET,
  316. LOFFSETS,
  317. COFFSETS,
  318. LOFFSET,
  319. COFFSET,
  320. OFFSETSYNC,
  321. RUNENABLE,
  322. RUNDISABLE,
  323. MAPFADEOFF,
  324. MAPFADEON,
  325. INITTRACE,
  326. SETDRESS,
  327. GETDRESS,
  328. FACEDIR,
  329. FACEDIRA,
  330. FACEDIRP,
  331. FACEDIRLIMIT,
  332. FACEDIROFF,
  333. SARALYOFF,
  334. SARALYON,
  335. SARALYDISPOFF,
  336. SARALYDISPON,
  337. MESMODE,
  338. FACEDIRINIT,
  339. FACEDIRI,
  340. JUNCTION,
  341. SETCAMERA,
  342. BATTLECUT,
  343. FOOTSTEPCOPY,
  344. WORLDMAPJUMP,
  345. RFACEDIRI,
  346. RFACEDIR,
  347. RFACEDIRA,
  348. RFACEDIRP,
  349. RFACEDIROFF,
  350. FACEDIRSYNC,
  351. COPYINFO,
  352. PCOPYINFO,
  353. RAMESW,
  354. BGSHADEOFF,
  355. AXIS,
  356. AXISSYNC,
  357. MENUNORMAL,
  358. MENUPHS,
  359. BGCLEAR,
  360. GETPARTY,
  361. MENUSHOP,
  362. DISC,
  363. DSCROLL3,
  364. LSCROLL3,
  365. CSCROLL3,
  366. MACCEL,
  367. MLIMIT,
  368. ADDITEM,
  369. SETWITCH,
  370. SETODIN,
  371. RESETGF,
  372. MENUNAME,
  373. REST,
  374. MOVECANCEL,
  375. PMOVECANCEL,
  376. ACTORMODE,
  377. MENUSAVE,
  378. SAVEENABLE,
  379. PHSENABLE,
  380. HOLD,
  381. MOVIECUT,
  382. SETPLACE,
  383. SETDCAMERA,
  384. CHOICEMUSIC,
  385. GETCARD,
  386. DRAWPOINT,
  387. PHSPOWER,
  388. KEY,
  389. CARDGAME,
  390. SETBAR,
  391. DISPBAR,
  392. KILLBAR,
  393. SCROLLRATIO2,
  394. WHOAMI,
  395. MUSICSTATUS,
  396. MUSICREPLAY,
  397. DOORLINEOFF,
  398. DOORLINEON,
  399. MUSICSKIP,
  400. DYING,
  401. SETHP,
  402. GETHP,
  403. MOVEFLUSH,
  404. MUSICVOLSYNC,
  405. PUSHANIME,
  406. POPANIME,
  407. KEYSCAN2,
  408. KEYON2,
  409. PARTICLEON,
  410. PARTICLEOFF,
  411. KEYSIGHNCHANGE,
  412. ADDGIL,
  413. ADDPASTGIL,
  414. ADDSEEDLEVEL,
  415. PARTICLESET,
  416. SETDRAWPOINT,
  417. MENUTIPS,
  418. LASTIN,
  419. LASTOUT,
  420. SEALEDOFF,
  421. MENUTUTO,
  422. OPENEYES,
  423. CLOSEEYES,
  424. BLINKEYES,
  425. SETCARD,
  426. HOWMANYCARD,
  427. WHERECARD,
  428. ADDMAGIC,
  429. SWAP,
  430. SETPARTY2,
  431. SPUSYNC,
  432. BROKEN,
  433. UNKNOWN1,
  434. UNKNOWN2,
  435. UNKNOWN3,
  436. UNKNOWN4,
  437. UNKNOWN5,
  438. UNKNOWN6,
  439. UNKNOWN7,
  440. UNKNOWN8,
  441. UNKNOWN9,
  442. UNKNOWN10,
  443. UNKNOWN11,
  444. UNKNOWN12,
  445. UNKNOWN13,
  446. UNKNOWN14,
  447. UNKNOWN15,
  448. UNKNOWN16,
  449. PREMAPJUMP2,
  450. TUTO
  451. }
  452. private enum Field_mods
  453. {
  454. INIT,
  455. DEBUGRENDER
  456. };
  457. internal static void Draw()
  458. {
  459. switch (mod)
  460. {
  461. case Field_mods.INIT:
  462. break; //null
  463. case Field_mods.DEBUGRENDER:
  464. DrawDebug();
  465. break;
  466. }
  467. }
  468. public static void ResetField()
  469. {
  470. mod = Field_mods.INIT;
  471. if (ScriptSystem != null)
  472. ScriptSystem.Clear();
  473. }
  474. private static void DrawDebug()
  475. {
  476. Memory.graphics.GraphicsDevice.Clear(Color.Black);
  477. Memory.SpriteBatchStartStencil();
  478. Rectangle src = new Rectangle(0, 0, tex.Width, tex.Height);
  479. Rectangle dst = src;
  480. dst.Size = (dst.Size.ToVector2() * Memory.Scale(tex.Width, tex.Height)).ToPoint();
  481. //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.
  482. //I setup scaling after noticing the field didn't size with the screen. I set it to center on screen.
  483. dst.Offset(Memory.Center.X - dst.Center.X, Memory.Center.Y - dst.Center.Y);
  484. Memory.spriteBatch.Draw(tex,dst, src, Color.White);
  485. //new Microsoft.Xna.Framework.Rectangle(0, 0, 1280 + (width - 320), 720 + (height - 224)),
  486. //new Microsoft.Xna.Framework.Rectangle(0, 0, tex.Width, tex.Height)
  487. Memory.SpriteBatchEnd();
  488. }
  489. internal static void Update()
  490. {
  491. #if DEBUG
  492. // lets you move through all the feilds just holding left or right. it will just loop when it runs out.
  493. if (Input.Button(Buttons.Left) )
  494. {
  495. Input.ResetInputLimit();
  496. init_debugger_Audio.PlaySound(0);
  497. Module_main_menu_debug.FieldPointer--;
  498. ResetField();
  499. }
  500. if (Input.Button(Buttons.Right) )
  501. {
  502. Input.ResetInputLimit();
  503. init_debugger_Audio.PlaySound(0);
  504. Module_main_menu_debug.FieldPointer++;
  505. ResetField();
  506. }
  507. #endif
  508. switch (mod)
  509. {
  510. case Field_mods.INIT:
  511. Init();
  512. StartupScript();// DEBUG
  513. break;
  514. case Field_mods.DEBUGRENDER:
  515. break; //await events here
  516. }
  517. }
  518. private static void StartupScript()
  519. {
  520. if (ScriptSystem != null)
  521. {
  522. var initDefaultCollection = ScriptSystem.Where(x => x.localID == 0 || x.localID == 1).ToList();
  523. foreach (var scr in initDefaultCollection)
  524. foreach (var opcode in scr.Scripts)
  525. if (ScriptSystem.Count != 0)
  526. ParseOpcode(opcode);
  527. }
  528. }
  529. private static void ParseOpcode(ScriptOpcode opcode)
  530. {
  531. int stack1 = 0;
  532. int stack2 = 0;
  533. //int stack3 = 0;
  534. switch (opcode.opcode)
  535. {
  536. case JSMopcodes.NOP:
  537. return;
  538. case JSMopcodes.LBL:
  539. return;
  540. case JSMopcodes.SETMODEL: //TODO
  541. Console.WriteLine("TODO: ENTITY SUBSYSTEM");
  542. return;
  543. case JSMopcodes.PSHN_L:
  544. Stack.Add(opcode.parameter);
  545. return;
  546. case JSMopcodes.BASEANIME: //TODO
  547. if (Stack.Count > 0)
  548. stack1 = POPstack();
  549. if (Stack.Count > 0)
  550. stack2 = POPstack();
  551. Console.WriteLine("TODO: ENTITY SUBSYSTEM; ANIMATION");
  552. return;
  553. case JSMopcodes.SETPC: //TODO
  554. stack1 = POPstack();
  555. Console.WriteLine("TODO: PARTY SUBSYSTEM");
  556. return;
  557. case JSMopcodes.HIDE: //TODO
  558. Console.WriteLine("TODO: ENTITY SUBSYSTEM");
  559. return;
  560. case JSMopcodes.UCOFF: //TODO
  561. Console.WriteLine("TODO: I/O SUBSYSTEM");
  562. return;
  563. case JSMopcodes.CLEAR: //TODO
  564. Console.WriteLine("TODO: CLEAR()");
  565. return;
  566. case JSMopcodes.POPM_B:
  567. if (Stack.Count > 0)
  568. stack1 = POPstack();
  569. if(stack1 < Memory.FieldHolder.FieldMemory.Length) // had one come out of range.
  570. Memory.FieldHolder.FieldMemory[stack1] = (byte)opcode.parameter; //stack was count 0 something wrong here?
  571. return;
  572. case JSMopcodes.POPM_W:
  573. if (Stack.Count > 0)
  574. stack1 = POPstack();
  575. if (stack1 < Memory.FieldHolder.FieldMemory.Length)
  576. Memory.FieldHolder.FieldMemory[stack1] = (ushort)opcode.parameter;
  577. return;
  578. case JSMopcodes.BATTLEOFF: //TODO
  579. return;
  580. case JSMopcodes.MAPFADEOFF: //TODO
  581. return;
  582. case JSMopcodes.ADDMEMBER: //todo
  583. return;
  584. case JSMopcodes.ADDPARTY: //todo
  585. return;
  586. case JSMopcodes.SETBATTLEMUSIC:
  587. Memory.SetBattleMusic = POPstack();
  588. return;
  589. case JSMopcodes.CAL: //todo
  590. if (Stack.Count > 0)
  591. stack1 = POPstack();
  592. if (Stack.Count > 0)
  593. stack2 = POPstack();
  594. return;
  595. case JSMopcodes.MOVIEREADY: //todo
  596. if (Stack.Count > 0)
  597. stack1 = POPstack();
  598. if (Stack.Count > 0)
  599. stack2 = POPstack();
  600. return;
  601. case JSMopcodes.MOVIE: //todo
  602. return;
  603. case JSMopcodes.MOVIESYNC: //todo
  604. return;
  605. case JSMopcodes.MAPJUMPO: //todo
  606. if (Stack.Count > 0)
  607. stack2 = POPstack(); //walkmesh id
  608. if (Stack.Count > 0)
  609. {
  610. stack1 = POPstack(); //field map id
  611. Memory.FieldHolder.FieldID = (ushort)stack1;
  612. }
  613. ResetField();
  614. //todo
  615. return;
  616. }
  617. }
  618. private static int POPstack()
  619. {
  620. if (Stack.Count > 0)
  621. {
  622. int stack = Stack.Last();
  623. Stack.RemoveAt(Stack.Count() - 1);
  624. return stack;
  625. }
  626. return 0; // the stack is empty. maybe something is wrong?
  627. }
  628. private static void Init()
  629. {
  630. ArchiveWorker aw = new ArchiveWorker($"{Memory.Archives.A_FIELD}.fs");
  631. string[] test = aw.GetListOfFiles();
  632. if (Memory.FieldHolder.FieldID >= Memory.FieldHolder.fields.Length ||
  633. Memory.FieldHolder.FieldID < 0)
  634. return;
  635. var CollectionEntry = test.Where(x => x.ToLower().Contains(Memory.FieldHolder.fields[Memory.FieldHolder.FieldID]));
  636. if (!CollectionEntry.Any()) return;
  637. string fieldArchive = CollectionEntry.First();
  638. int fieldLen = fieldArchive.Length - 2;
  639. fieldArchive = fieldArchive.Substring(0, fieldLen);
  640. byte[] fs = ArchiveWorker.GetBinaryFile(Memory.Archives.A_FIELD, $"{fieldArchive}fs");
  641. byte[] fi = ArchiveWorker.GetBinaryFile(Memory.Archives.A_FIELD, $"{fieldArchive}fi");
  642. byte[] fl = ArchiveWorker.GetBinaryFile(Memory.Archives.A_FIELD, $"{fieldArchive}fl");
  643. if (fs == null || fi == null || fl == null) return;
  644. string[] test_ = ArchiveWorker.GetBinaryFileList(fl);
  645. string mim = null;
  646. string map = null;
  647. try
  648. {
  649. mim = test_.First(x => x.ToLower().Contains(".mim"));
  650. }
  651. catch{}
  652. try
  653. {
  654. map = test_.First(x => x.ToLower().Contains(".map"));
  655. }
  656. catch{}
  657. if (mim != null && map != null)
  658. {
  659. byte[] mimb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, mim);
  660. byte[] mapb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, map);
  661. ParseBackground(mimb, mapb);
  662. }
  663. #if DEBUG
  664. if (Memory.FieldHolder.FieldID == 180) goto safeDebugpoint; //delete me
  665. #endif
  666. //let's start with scripts
  667. byte[] jsm = null;
  668. byte[] sy = null;
  669. string s_jsm = null;
  670. string s_sy = null;
  671. try
  672. {
  673. s_jsm = test_.First(x => x.ToLower().Contains(".jsm"));
  674. }
  675. catch { }
  676. try
  677. {
  678. s_sy = test_.First(x => x.ToLower().Contains(".sy"));
  679. }
  680. catch { }
  681. if (s_jsm != null && s_sy != null)
  682. {
  683. jsm = ArchiveWorker.FileInTwoArchives(fi, fs, fl, s_jsm);
  684. sy = ArchiveWorker.FileInTwoArchives(fi, fs, fl, s_sy);
  685. ParseScripts(jsm, sy);
  686. }
  687. Stack = new List<int>();
  688. #if DEBUG
  689. OutputAllParsedScripts();
  690. #endif
  691. //string mch = test_.Where(x => x.ToLower().Contains(".mch")).First();
  692. //string one = test_.Where(x => x.ToLower().Contains(".one")).First();
  693. //string msd = test_.Where(x => x.ToLower().Contains(".msd")).First();
  694. //string inf = test_.Where(x => x.ToLower().Contains(".inf")).First();
  695. //string id = test_.Where(x => x.ToLower().Contains(".id")).First();
  696. //string ca = test_.Where(x => x.ToLower().Contains(".ca")).First();
  697. //string tdw = test_.Where(x => x.ToLower().Contains(".tdw")).First();
  698. //string msk = test_.Where(x => x.ToLower().Contains(".msk")).First();
  699. //string rat = test_.Where(x => x.ToLower().Contains(".rat")).First();
  700. //string pmd = test_.Where(x => x.ToLower().Contains(".pmd")).First();
  701. //string sfx = test_.Where(x => x.ToLower().Contains(".sfx")).First();
  702. //byte[] mchb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, mch); //Field character models
  703. //byte[] oneb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, one); //Field character models container
  704. //byte[] msdb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, msd); //dialogs
  705. //byte[] infb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, inf); //gateways
  706. //byte[] idb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, id); //walkmesh
  707. //byte[] cab = ArchiveWorker.FileInTwoArchives(fi, fs, fl, ca); //camera
  708. //byte[] tdwb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, tdw); //extra font
  709. //byte[] mskb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, msk); //movie cam
  710. //byte[] ratb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, rat); //battle on field
  711. //byte[] pmdb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, pmd); //particle info
  712. //byte[] sfxb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, sfx); //sound effects
  713. safeDebugpoint:
  714. mod++;
  715. return;
  716. }
  717. private static void OutputAllParsedScripts()
  718. {
  719. foreach (var a in ScriptSystem)
  720. {
  721. Console.WriteLine($"Entity: {a.Entity}\tName: {a.ScriptName}");
  722. int lineNumber = 0;
  723. foreach (var b in a.Scripts)
  724. Console.WriteLine($"{lineNumber++}:\t{b.opcodeASM} {b.parameter.ToString()}");
  725. }
  726. }
  727. private static void ParseScripts(byte[] jsmb, byte[] symb)
  728. {
  729. //string[] symbolNames = new string[symb.Length / 32];
  730. if(symb == null)
  731. return;
  732. symbolNames = System.Text.Encoding.ASCII.GetString(symb).Replace(" ", "").Replace("\0", "").Split('\n');
  733. //for(int i = 0; i<symbolNames.Length; i++)
  734. // symbolNames[i] = System.Text.Encoding.ASCII.GetString(symb, i * 32, 32).TrimEnd('\0', '\n', ' ');
  735. //File.WriteAllBytes("D:/symb.test", symb);
  736. jsm = new SJSM();
  737. //File.WriteAllBytes("D:\\test.jsm", jsmb);
  738. using (Stream str = new MemoryStream(jsmb))
  739. using (BinaryReader br = new BinaryReader(str))
  740. {
  741. jsm.cDoorEntity = br.ReadByte();
  742. jsm.cWalkmeshEntity = br.ReadByte();
  743. jsm.cBackgroundEntity = br.ReadByte();
  744. jsm.cOtherEntity = br.ReadByte();
  745. jsm.offsetSecOne = br.ReadUInt16();
  746. jsm.offsetScriptData = br.ReadUInt16();
  747. EntryPointEntity[] epe = new EntryPointEntity[jsm.cDoorEntity + jsm.cOtherEntity + jsm.cWalkmeshEntity + jsm.cBackgroundEntity];
  748. for (int i = 0; i < epe.Length; i++)
  749. {
  750. ushort bb = br.ReadUInt16();
  751. epe[i].scriptCount = (byte)((bb & 0x7F) + 1);
  752. epe[i].label = (byte)(bb >> 7);
  753. // was throwing exception
  754. epe[i].labelASM = symbolNames != null && epe[i].label < symbolNames.Length ? symbolNames[epe[i].label] : "";
  755. }
  756. int SYMscriptNameStartingPoint = jsm.cDoorEntity + jsm.cOtherEntity + jsm.cWalkmeshEntity + jsm.cBackgroundEntity;
  757. jsm.EntityEntryPoints = epe;
  758. EntryPointScript[] eps = new EntryPointScript[(jsm.offsetScriptData - jsm.offsetSecOne) / 2 - 1];
  759. for (int i = 0; i < eps.Length; i++)
  760. {
  761. ushort bb = br.ReadUInt16();
  762. eps[i].position = (ushort)((bb & 0x7FFF) * 4);
  763. eps[i].flag = (byte)(bb >> 15);
  764. }
  765. ushort eof = br.ReadUInt16();
  766. jsm.entryPointScripts = eps;
  767. //br.BaseStream.Seek(jsm.offsetScriptData, SeekOrigin.Begin);
  768. ScriptSystem = new List<ScriptEntry>();
  769. List<ScriptOpcode> scriptChunk = new List<ScriptOpcode>();
  770. int scriptLabelPointer = 0;
  771. while (br.BaseStream.Position != br.BaseStream.Length)
  772. {
  773. if (br.BaseStream.Position == br.BaseStream.Length)
  774. break; //??
  775. uint binaryOpcode = br.ReadUInt32();
  776. uint parameter = 0;
  777. uint opcode = 0;
  778. if ((binaryOpcode & 0xFFFFFF00) == 0) //when only function
  779. {
  780. opcode = binaryOpcode;
  781. parameter = 0;
  782. }
  783. else
  784. {
  785. opcode = binaryOpcode >> 16;
  786. opcode = (opcode >> 8) | opcode << 8 & 0xFF00;
  787. parameter = binaryOpcode & 0xFFFF;
  788. }
  789. if (opcode == 5 && scriptChunk.Count != 0) //label
  790. {
  791. ushort entityNumber =0;
  792. if (symbolNames != null && SYMscriptNameStartingPoint + scriptLabelPointer < symbolNames.Length)
  793. entityNumber = (ushort)FindEntity(symbolNames[SYMscriptNameStartingPoint + scriptLabelPointer]);
  794. int locId = ScriptSystem.Count(x => x.Entity == entityNumber);
  795. ScriptSystem.Add(new ScriptEntry()
  796. {
  797. Entity = entityNumber,
  798. ScriptName = (SYMscriptNameStartingPoint + scriptLabelPointer+1 < symbolNames.Length ? symbolNames[SYMscriptNameStartingPoint + scriptLabelPointer++] : ""),
  799. ID = scriptChunk[0].parameter,
  800. localID = (ushort)locId++,
  801. Scripts = scriptChunk.ToArray()
  802. });
  803. scriptChunk.Clear();
  804. }
  805. scriptChunk.Add(new ScriptOpcode()
  806. {
  807. parameter = (ushort)parameter,
  808. opcodeBinary = (ushort)opcode,
  809. opcodeASM = Enum.GetName(typeof(JSMopcodes), opcode),
  810. opcode = (JSMopcodes)opcode
  811. });
  812. if (br.BaseStream.Position == br.BaseStream.Length)
  813. {
  814. ushort entityNumber = 0;
  815. if (symbolNames != null && SYMscriptNameStartingPoint + scriptLabelPointer < symbolNames.Length)
  816. entityNumber = (ushort)FindEntity(symbolNames[SYMscriptNameStartingPoint + scriptLabelPointer]);
  817. int locId = ScriptSystem.Count(x => x.Entity == entityNumber);
  818. ScriptSystem.Add(new ScriptEntry()
  819. {
  820. Entity = entityNumber,
  821. ScriptName = (SYMscriptNameStartingPoint + scriptLabelPointer + 1 < symbolNames.Length ? symbolNames[SYMscriptNameStartingPoint + scriptLabelPointer++]:""),
  822. ID = scriptChunk[0].parameter,
  823. localID = (ushort)locId++,
  824. Scripts = scriptChunk.ToArray()
  825. });
  826. break;
  827. }
  828. }
  829. /*
  830. * okay, my notes on JSM:
  831. * so the exec is always Lines first, they tend to always contain 8 IDs like touch touchoff etc
  832. * it begins with setline
  833. *
  834. * next are doors, yes?
  835. * they are like open, close, on, off
  836. * so you have to test the location of the player and see if he triggers any of this script
  837. *
  838. * next are other things
  839. * finally an character entity- director. He plays like if we should call some functions or not
  840. *
  841. * it's like RET(8) makes it never use the code again in a loop of execution
  842. *
  843. * so it all plays normally, because almost everytime it's RET of the function. All action is triggered by like PUSH or TALK
  844. *
  845. * Other functions are not normally playing. See bgroom_4. Default code is actually playing the monitor.on functions
  846. *
  847. * So for sure I'll need to read .SYM, then pair the names with script IDs, then sort by the exec priority and read only the 0 and 1 as default and init scripts
  848. * everything else leave for triggering. Ugh, that's going to be painful
  849. *
  850. */
  851. }
  852. }
  853. private static int FindEntity(string entityName)
  854. {
  855. if (entityName.Contains("::"))
  856. entityName = entityName.Substring(0, entityName.IndexOf(':'));
  857. return symbolNames.ToList().IndexOf(entityName);
  858. }
  859. private static void ParseBackground(byte[] mimb, byte[] mapb)
  860. {
  861. if (mimb == null || mapb == null)
  862. return;
  863. int type1Width = 1664;
  864. tiles = new List<Tile>();
  865. int palletes = 24;
  866. //128x256
  867. PseudoBufferedStream pbsmap = new PseudoBufferedStream(mapb);
  868. PseudoBufferedStream pbsmim = new PseudoBufferedStream(mimb);
  869. while (pbsmap.Tell() + 16 < pbsmap.Length)
  870. {
  871. Tile tile = new Tile { x = pbsmap.ReadShort() };
  872. if (tile.x == 0x7FFF)
  873. break;
  874. tile.y = pbsmap.ReadShort();
  875. tile.z = pbsmap.ReadUShort();// (ushort)(4096 - pbsmap.ReadUShort());
  876. byte texIdBuffer = pbsmap.ReadByte();
  877. tile.texID = (byte)(texIdBuffer & 0xF);
  878. pbsmap.Seek(1, SeekOrigin.Current);
  879. //short testz = pbsmap.ReadShort();
  880. //testz = (short)(testz >> 6);
  881. //testz &= 0xF;
  882. tile.pallID = (byte)((pbsmap.ReadShort() >> 6) & 0xF);
  883. tile.srcx = pbsmap.ReadByte();
  884. tile.srcy = pbsmap.ReadByte();
  885. tile.layId = (byte)(pbsmap.ReadByte() & 0x7F);
  886. tile.blendType = pbsmap.ReadByte();
  887. tile.parameter = pbsmap.ReadByte();
  888. tile.state = pbsmap.ReadByte();
  889. tile.blend1 = (byte)((texIdBuffer >> 4) & 0x1);
  890. tile.blend2 = (byte)(texIdBuffer >> 5);
  891. tiles.Add(tile);
  892. //srcY = srcX == texID * 128 + srcX;
  893. }
  894. int lowestY = tiles.Min(x => x.y);
  895. int maximumY = tiles.Max(x => x.y);
  896. int lowestX = tiles.Min(x => x.x); //-160;
  897. int maximumX = tiles.Max(x => x.x);
  898. height = Math.Abs(lowestY) + maximumY + 16; //224
  899. width = Math.Abs(lowestX) + maximumX + 16; //320
  900. byte[] finalImage = new byte[height * width * 4]; //ARGB;
  901. byte[] finalOverlapImage = new byte[height * width * 4];
  902. tex = new Texture2D(Memory.graphics.GraphicsDevice, width, height);
  903. texOverlap = new Texture2D(Memory.graphics.GraphicsDevice, width, height);
  904. var MaximumLayer = tiles.Max(x => x.layId);
  905. var MinimumLayer = tiles.Min(x => x.layId);
  906. List<ushort> BufferDepth = tiles.GroupBy(x => x.z).Select(group => group.First()).Select(x => x.z).ToList();
  907. BufferDepth.Sort();
  908. for (int LayerId = 1; LayerId <= MaximumLayer + 1; LayerId++)
  909. {
  910. foreach (Tile tile in tiles)
  911. {
  912. if (LayerId != MaximumLayer + 1)
  913. {
  914. if (tile.layId != LayerId)
  915. continue;
  916. //if (tile.z != BufferDepth[LayerId])
  917. // continue;
  918. }
  919. else
  920. if (tile.layId != 0)
  921. continue;
  922. int palettePointer = 4096 + ((tile.pallID) * 512);
  923. int sourceImagePointer = 512 * palletes;
  924. int realX = Math.Abs(lowestX) + tile.x; //baseX
  925. int realY = Math.Abs(lowestY) + tile.y; //*width
  926. int realDestinationPixel = ((realY * width) + realX) * 4;
  927. if (tile.blend2 >= 4)
  928. {
  929. int startPixel = sourceImagePointer + tile.srcx + 128 * tile.texID + (type1Width * tile.srcy);
  930. for (int y = 0; y < 16; y++)
  931. for (int x = 0; x < 16; x++)
  932. {
  933. byte pixel = mimb[startPixel + x + (y * 1664)];
  934. ushort pixels = BitConverter.ToUInt16(mimb, 2 * pixel + palettePointer);
  935. if (pixels == 00)
  936. continue;
  937. byte red = (byte)((pixels) & 0x1F);
  938. byte green = (byte)((pixels >> 5) & 0x1F);
  939. byte blue = (byte)((pixels >> 10) & 0x1F);
  940. red = (byte)MathHelper.Clamp((red * 8), 0, 255);
  941. green = (byte)MathHelper.Clamp((green * 8), 0, 255);
  942. blue = (byte)MathHelper.Clamp((blue * 8), 0, 255);
  943. if (tile.blendType < 4)
  944. {
  945. if (true)//!bSaveToOverlapBuffer)
  946. {
  947. byte baseColorR = finalImage[realDestinationPixel + (x * 4) + (y * width * 4)];
  948. byte baseColorG = finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1];
  949. byte baseColorB = finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2];
  950. Blend(baseColorR, baseColorG, baseColorB, red, green, blue, tile, finalImage, realDestinationPixel, x, y);
  951. }
  952. else
  953. {
  954. byte baseColorR = finalOverlapImage[realDestinationPixel + (x * 4) + (y * width * 4)];
  955. byte baseColorG = finalOverlapImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1];
  956. byte baseColorB = finalOverlapImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2];
  957. Blend(baseColorR, baseColorG, baseColorB, red, green, blue, tile, finalOverlapImage, realDestinationPixel, x, y);
  958. }
  959. }
  960. else
  961. {
  962. if (true)//!bSaveToOverlapBuffer)
  963. {
  964. finalImage[realDestinationPixel + (x * 4) + (y * width * 4)] = red;
  965. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1] = green;
  966. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2] = blue;
  967. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 3] = 0xFF;
  968. }
  969. else
  970. {
  971. finalOverlapImage[realDestinationPixel + (x * 4) + (y * width * 4)] = red;
  972. finalOverlapImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1] = green;
  973. finalOverlapImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2] = blue;
  974. finalOverlapImage[realDestinationPixel + (x * 4) + (y * width * 4) + 3] = 0xFF;
  975. }
  976. }
  977. }
  978. }
  979. else
  980. {
  981. // int startPixel = sourceImagePointer + tile.srcx / 2 + 128 * tile.texID + (type1Width * tile.srcy);
  982. // for (int y = 0; y < 16; y++)
  983. // for (int x = 0; x < 16; x++)
  984. // {
  985. // byte index = mimb[startPixel + x + (y * 1664)];
  986. // ushort pixels = BitConverter.ToUInt16(mimb, 2 * (index & 0xF) + palettePointer);
  987. // byte red = (byte)((pixels) & 0x1F);
  988. // byte green = (byte)((pixels >> 5) & 0x1F);
  989. // byte blue = (byte)((pixels >> 10) & 0x1F);
  990. // red = (byte)MathHelper.Clamp((red * 8), 0, 255);
  991. // green = (byte)MathHelper.Clamp((green * 8), 0, 255);
  992. // blue = (byte)MathHelper.Clamp((blue * 8), 0, 255);
  993. // if (pixels != 0)
  994. // {
  995. // if (tile.blendType < 4)
  996. // {
  997. // byte baseColorR = finalImage[realDestinationPixel + (x * 4) + (y * width * 4)];
  998. // byte baseColorG = finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1];
  999. // byte baseColorB = finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2];
  1000. // Blend(baseColorR, baseColorG, baseColorB, red, green, blue, tile, finalImage, realDestinationPixel, x, y);
  1001. // }
  1002. // }
  1003. // pixels = BitConverter.ToUInt16(mimb, 2 * (index >> 4) + palettePointer);
  1004. // red = (byte)((pixels) & 0x1F);
  1005. // green = (byte)((pixels >> 5) & 0x1F);
  1006. // blue = (byte)((pixels >> 10) & 0x1F);
  1007. // red = (byte)MathHelper.Clamp((red * 8), 0, 255);
  1008. // green = (byte)MathHelper.Clamp((green * 8), 0, 255);
  1009. // blue = (byte)MathHelper.Clamp((blue * 8), 0, 255);
  1010. // if (pixels != 0)
  1011. // {
  1012. // if (tile.blendType < 4)
  1013. // {
  1014. // byte baseColorR = finalImage[realDestinationPixel + (x * 4) + (y * width * 4)];
  1015. // byte baseColorG = finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1];
  1016. // byte baseColorB = finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2];
  1017. // Blend(baseColorR, baseColorG, baseColorB, red, green, blue, tile, finalImage, realDestinationPixel, x, y);
  1018. // }
  1019. // }
  1020. // else
  1021. // {
  1022. // finalImage[realDestinationPixel + (x * 4) + (y * width * 4)] = red;
  1023. // finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1] = green;
  1024. // finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2] = blue;
  1025. // finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 3] = 0xFF;
  1026. // }
  1027. // }
  1028. }
  1029. }
  1030. }
  1031. tex.SetData(finalImage);
  1032. texOverlap.SetData(finalOverlapImage);
  1033. }
  1034. private static void DrawEntities()
  1035. {
  1036. throw new NotImplementedException();
  1037. }
  1038. 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)
  1039. {
  1040. switch (tile.blendType)
  1041. {
  1042. case 0:
  1043. finalImage[realDestinationPixel + (x * 4) + (y * width * 4)] = (byte)((baseColorR + red) / 2);
  1044. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1] = (byte)((baseColorG + green) / 2);
  1045. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2] = (byte)((baseColorB + blue) / 2);
  1046. break;
  1047. case 1:
  1048. finalImage[realDestinationPixel + (x * 4) + (y * width * 4)] = (byte)MathHelper.Clamp(baseColorR + red, 0, 255);
  1049. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1] = (byte)MathHelper.Clamp(baseColorG + green, 0, 255);
  1050. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2] = (byte)MathHelper.Clamp(baseColorB + blue, 0, 255);
  1051. break;
  1052. case 2:
  1053. finalImage[realDestinationPixel + (x * 4) + (y * width * 4)] = (byte)MathHelper.Clamp(baseColorR - red, 0, 255);
  1054. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1] = (byte)MathHelper.Clamp(baseColorG - green, 0, 255);
  1055. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2] = (byte)MathHelper.Clamp(baseColorB - blue, 0, 255);
  1056. break;
  1057. case 3:
  1058. break;
  1059. finalImage[realDestinationPixel + (x * 4) + (y * width * 4)] = (byte)MathHelper.Clamp((byte)(baseColorR + (0.25 * red)), 0, 255);
  1060. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 1] = (byte)MathHelper.Clamp((byte)(baseColorG + (0.25 * green)), 0, 255);
  1061. finalImage[realDestinationPixel + (x * 4) + (y * width * 4) + 2] = (byte)MathHelper.Clamp((byte)(baseColorB + (0.25 * blue)), 0, 255);
  1062. break;
  1063. }
  1064. }
  1065. }
  1066. }