public void ToSource(YukaScript script, string path) { string sourcePath = Path.ChangeExtension(path, Constants.ykd); string stringPath = Path.ChangeExtension(path, Constants.csv); // write source code File.WriteAllText(sourcePath, script.Source()); // write string data if (script.stringTable.Count > 0) { StreamWriter w = new StreamWriter(new FileStream(stringPath, FileMode.Create)); w.WriteLine($"ID{CSVDelimiter}Speaker{CSVDelimiter}Original{CSVDelimiter}Translation{CSVDelimiter}TLC{CSVDelimiter}Edit{CSVDelimiter}QC{CSVDelimiter}Comments{CSVDelimiter}Generated"); // write names bool flag = false; foreach (var entry in script.stringTable) { if (entry.Key.StartsWith("N")) { if (!flag) { w.WriteLine(CSVDelimiter + "\r\n#Names:"); flag = true; } w.WriteLine(entry.Key + CSVDelimiter + CSVDelimiter + entry.Value.Text); } } // write lines flag = false; foreach (var entry in script.stringTable) { if (!entry.Key.StartsWith("N")) { if (!flag) { w.WriteLine(CSVDelimiter + "\r\n#Lines:"); flag = true; } string speaker = entry.Value.Speaker ?? ""; string line = entry.Value.Text; int fontID = entry.Value.FontID; int fontSize = fontID >= 0 && fontID < 16 ? Constants.fontInfo[fontID].FullWidthHorizontalSpacing : TextUtils.defaultCharWidth; string meta = '"' + (speaker + (fontSize != TextUtils.defaultCharWidth ? $"\ncw:{fontSize}" : "")).Trim() + '"'; line = '"' + line.Replace("\"", "\"\"") + '"'; w.WriteLine(entry.Key + CSVDelimiter + meta + CSVDelimiter + line); } } w.Close(); } }
public Decompiler(YukaScript script) { Script = script; }
/// <summary> /// Compiles an entire script into a binary script file (.yks) /// </summary> /// <param name="script">The script instance to compile</param> /// <param name="s">The output stream</param> /// <returns>The number of bytes written</returns> public long ToBinary(YukaScript script, Stream s) { long offset = s.Position; List <ScriptElement> flattened = new List <ScriptElement>(); Console.ForegroundColor = ConsoleColor.Cyan; foreach (ScriptElement elem in script.commands) { List <ScriptElement> cmds = Flatten(elem, false); flattened.AddRange(cmds); if (cmds.Count == 0 && FlagCollection.current.Has('v')) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("?????????????"); Console.ForegroundColor = ConsoleColor.Cyan; } foreach (ScriptElement cmd in cmds) { if (cmd is DataScriptElement dse && dse.elem is ControlDataElement cde) { string name = cde.name; if (!"else".Equals(name) && !"{".Equals(name) && !"}".Equals(name)) { jumpLabels.Add(name, cde); } } //Console.WriteLine(cmd); } } List <DataElement> code = new List <DataElement>(); Dictionary <string, FuncDataElement> functions = new Dictionary <string, FuncDataElement>(); foreach (ScriptElement elem in flattened) { if (elem is FuncCallScriptElement) { string name = (elem as FuncCallScriptElement).name; ScriptElement[] parameters = (elem as FuncCallScriptElement).parameters; if (!functions.ContainsKey(name)) { functions[name] = new FuncDataElement(name); } functions[name].lastOffset = code.Count; code.Add(functions[name]); code.Add(new RawDataElement(parameters.Length)); foreach (ScriptElement param in parameters) { if (param is DataScriptElement) { code.Add((param as DataScriptElement).elem); } else { throw new Exception("Expected DataScriptElement, got " + param.GetType().Name); } } } else if (elem is DataScriptElement) { DataElement data = (elem as DataScriptElement).elem; if (data is ControlDataElement) { (data as ControlDataElement).codeOffset = code.Count; } code.Add(data); } else { } if (FlagCollection.current.Has('v')) { Console.WriteLine(elem); } } Console.ForegroundColor = ConsoleColor.Yellow; DataManager dataManager = new DataManager(); List <Tuple <int, int, int, int> > index = new List <Tuple <int, int, int, int> >(); List <int> codeData = new List <int>(); foreach (DataElement elem in code) { if (elem is ControlDataElement) { string name = (elem as ControlDataElement).name; if (jumpLabels.ContainsKey(name)) { (elem as ControlDataElement).link = jumpLabels[name]; } } if (elem is RawDataElement) { codeData.Add((elem as RawDataElement).value); } else { elem.WriteData(dataManager); Tuple <int, int, int, int> entry = elem.GetIndex(); if (FlagCollection.current.Has('v')) { Console.WriteLine(entry); } int i = index.IndexOf(entry); if (i == -1) { i = index.Count; index.Add(entry); } codeData.Add(i); } } Console.ResetColor(); BinaryWriter bw = new BinaryWriter(s); // write header s.Write(new byte[] { 0x59, 0x4B, 0x53, 0x30, 0x30, 0x31, 0x01, 0x00 }, 0, 8); s.Write(new byte[] { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 8); bw.Write(0x30); bw.Write(codeData.Count); bw.Write(0x30 + codeData.Count * 4); bw.Write(index.Count); bw.Write(0x30 + codeData.Count * 4 + index.Count * 16); bw.Write(dataManager.offset); bw.Write(tempVarID); bw.Write(0); // write code sector foreach (int cmd in codeData) { bw.Write(cmd); } // write index foreach (Tuple <int, int, int, int> entry in index) { bw.Write(entry.Item1); bw.Write(entry.Item2); bw.Write(entry.Item3); bw.Write(entry.Item4); } // write data sector dataManager.WriteTo(s); return(s.Position - offset); }