private static void ParseScripts(byte[] jsmb, byte[] symb) { //string[] symbolNames = new string[symb.Length / 32]; if (symb == null) { return; } symbolNames = System.Text.Encoding.ASCII.GetString(symb).Replace(" ", "").Replace("\0", "").Split('\n'); //for(int i = 0; i<symbolNames.Length; i++) // symbolNames[i] = System.Text.Encoding.ASCII.GetString(symb, i * 32, 32).TrimEnd('\0', '\n', ' '); //File.WriteAllBytes("D:/symb.test", symb); jsm = new SJSM(); //File.WriteAllBytes("D:\\test.jsm", jsmb); using (Stream str = new MemoryStream(jsmb)) using (BinaryReader br = new BinaryReader(str)) { jsm.cDoorEntity = br.ReadByte(); jsm.cWalkmeshEntity = br.ReadByte(); jsm.cBackgroundEntity = br.ReadByte(); jsm.cOtherEntity = br.ReadByte(); jsm.offsetSecOne = br.ReadUInt16(); jsm.offsetScriptData = br.ReadUInt16(); EntryPointEntity[] epe = new EntryPointEntity[jsm.cDoorEntity + jsm.cOtherEntity + jsm.cWalkmeshEntity + jsm.cBackgroundEntity]; for (int i = 0; i < epe.Length; i++) { ushort bb = br.ReadUInt16(); epe[i].scriptCount = (byte)((bb & 0x7F) + 1); epe[i].label = (byte)(bb >> 7); // was throwing exception epe[i].labelASM = symbolNames != null && epe[i].label < symbolNames.Length ? symbolNames[epe[i].label] : ""; } int SYMscriptNameStartingPoint = jsm.cDoorEntity + jsm.cOtherEntity + jsm.cWalkmeshEntity + jsm.cBackgroundEntity; jsm.EntityEntryPoints = epe; EntryPointScript[] eps = new EntryPointScript[(jsm.offsetScriptData - jsm.offsetSecOne) / 2 - 1]; for (int i = 0; i < eps.Length; i++) { ushort bb = br.ReadUInt16(); eps[i].position = (ushort)((bb & 0x7FFF) * 4); eps[i].flag = (byte)(bb >> 15); } ushort eof = br.ReadUInt16(); jsm.entryPointScripts = eps; //br.BaseStream.Seek(jsm.offsetScriptData, SeekOrigin.Begin); ScriptSystem = new List <ScriptEntry>(); List <ScriptOpcode> scriptChunk = new List <ScriptOpcode>(); int scriptLabelPointer = 0; while (br.BaseStream.Position != br.BaseStream.Length) { if (br.BaseStream.Position == br.BaseStream.Length) { break; //?? } uint binaryOpcode = br.ReadUInt32(); uint parameter = 0; uint opcode = 0; if ((binaryOpcode & 0xFFFFFF00) == 0) //when only function { opcode = binaryOpcode; parameter = 0; } else { opcode = binaryOpcode >> 16; opcode = (opcode >> 8) | opcode << 8 & 0xFF00; parameter = binaryOpcode & 0xFFFF; } if (opcode == 5 && scriptChunk.Count != 0) //label { ushort entityNumber = 0; if (symbolNames != null && SYMscriptNameStartingPoint + scriptLabelPointer < symbolNames.Length) { entityNumber = (ushort)FindEntity(symbolNames[SYMscriptNameStartingPoint + scriptLabelPointer]); } int locId = ScriptSystem.Count(x => x.Entity == entityNumber); ScriptSystem.Add(new ScriptEntry() { Entity = entityNumber, ScriptName = (SYMscriptNameStartingPoint + scriptLabelPointer + 1 < symbolNames.Length ? symbolNames[SYMscriptNameStartingPoint + scriptLabelPointer++] : ""), ID = scriptChunk[0].parameter, localID = (ushort)locId++, Scripts = scriptChunk.ToArray() }); scriptChunk.Clear(); } scriptChunk.Add(new ScriptOpcode() { parameter = (ushort)parameter, opcodeBinary = (ushort)opcode, opcodeASM = Enum.GetName(typeof(JSMopcodes), opcode), opcode = (JSMopcodes)opcode }); if (br.BaseStream.Position == br.BaseStream.Length) { ushort entityNumber = 0; if (symbolNames != null && SYMscriptNameStartingPoint + scriptLabelPointer < symbolNames.Length) { entityNumber = (ushort)FindEntity(symbolNames[SYMscriptNameStartingPoint + scriptLabelPointer]); } int locId = ScriptSystem.Count(x => x.Entity == entityNumber); ScriptSystem.Add(new ScriptEntry() { Entity = entityNumber, ScriptName = (SYMscriptNameStartingPoint + scriptLabelPointer + 1 < symbolNames.Length ? symbolNames[SYMscriptNameStartingPoint + scriptLabelPointer++]:""), ID = scriptChunk[0].parameter, localID = (ushort)locId++, Scripts = scriptChunk.ToArray() }); break; } } /* * okay, my notes on JSM: * so the exec is always Lines first, they tend to always contain 8 IDs like touch touchoff etc * it begins with setline * * next are doors, yes? * they are like open, close, on, off * so you have to test the location of the player and see if he triggers any of this script * * next are other things * finally an character entity- director. He plays like if we should call some functions or not * * it's like RET(8) makes it never use the code again in a loop of execution * * so it all plays normally, because almost everytime it's RET of the function. All action is triggered by like PUSH or TALK * * Other functions are not normally playing. See bgroom_4. Default code is actually playing the monitor.on functions * * 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 * everything else leave for triggering. Ugh, that's going to be painful * */ } }
private static void Init() { ArchiveWorker aw = new ArchiveWorker($"{Memory.Archives.A_FIELD}.fs"); string[] test = aw.GetListOfFiles(); if (Memory.FieldHolder.FieldID >= Memory.FieldHolder.fields.Length || Memory.FieldHolder.FieldID < 0) { return; } var CollectionEntry = test.Where(x => x.ToLower().Contains(Memory.FieldHolder.fields[Memory.FieldHolder.FieldID])); if (!CollectionEntry.Any()) { return; } string fieldArchive = CollectionEntry.First(); int fieldLen = fieldArchive.Length - 2; fieldArchive = fieldArchive.Substring(0, fieldLen); byte[] fs = ArchiveWorker.GetBinaryFile(Memory.Archives.A_FIELD, $"{fieldArchive}fs"); byte[] fi = ArchiveWorker.GetBinaryFile(Memory.Archives.A_FIELD, $"{fieldArchive}fi"); byte[] fl = ArchiveWorker.GetBinaryFile(Memory.Archives.A_FIELD, $"{fieldArchive}fl"); if (fs == null || fi == null || fl == null) { return; } string[] test_ = ArchiveWorker.GetBinaryFileList(fl); string mim = null; string map = null; try { mim = test_.First(x => x.ToLower().Contains(".mim")); } catch {} try { map = test_.First(x => x.ToLower().Contains(".map")); } catch {} if (mim != null && map != null) { byte[] mimb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, mim); byte[] mapb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, map); ParseBackground(mimb, mapb); } #if DEBUG if (Memory.FieldHolder.FieldID == 180) { goto safeDebugpoint; //delete me } #endif //let's start with scripts byte[] jsm = null; byte[] sy = null; string s_jsm = null; string s_sy = null; try { s_jsm = test_.First(x => x.ToLower().Contains(".jsm")); } catch { } try { s_sy = test_.First(x => x.ToLower().Contains(".sy")); } catch { } if (s_jsm != null && s_sy != null) { jsm = ArchiveWorker.FileInTwoArchives(fi, fs, fl, s_jsm); sy = ArchiveWorker.FileInTwoArchives(fi, fs, fl, s_sy); ParseScripts(jsm, sy); } Stack = new List <int>(); #if DEBUG OutputAllParsedScripts(); #endif //string mch = test_.Where(x => x.ToLower().Contains(".mch")).First(); //string one = test_.Where(x => x.ToLower().Contains(".one")).First(); //string msd = test_.Where(x => x.ToLower().Contains(".msd")).First(); //string inf = test_.Where(x => x.ToLower().Contains(".inf")).First(); //string id = test_.Where(x => x.ToLower().Contains(".id")).First(); //string ca = test_.Where(x => x.ToLower().Contains(".ca")).First(); //string tdw = test_.Where(x => x.ToLower().Contains(".tdw")).First(); //string msk = test_.Where(x => x.ToLower().Contains(".msk")).First(); //string rat = test_.Where(x => x.ToLower().Contains(".rat")).First(); //string pmd = test_.Where(x => x.ToLower().Contains(".pmd")).First(); //string sfx = test_.Where(x => x.ToLower().Contains(".sfx")).First(); //byte[] mchb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, mch); //Field character models //byte[] oneb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, one); //Field character models container //byte[] msdb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, msd); //dialogs //byte[] infb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, inf); //gateways //byte[] idb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, id); //walkmesh //byte[] cab = ArchiveWorker.FileInTwoArchives(fi, fs, fl, ca); //camera //byte[] tdwb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, tdw); //extra font //byte[] mskb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, msk); //movie cam //byte[] ratb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, rat); //battle on field //byte[] pmdb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, pmd); //particle info //byte[] sfxb = ArchiveWorker.FileInTwoArchives(fi, fs, fl, sfx); //sound effects safeDebugpoint: mod++; return; }