private void FileMenuOpen_Click(object sender, RoutedEventArgs e) { OpenFileDialog openFileDialog = new OpenFileDialog { Filter = "Decompressed NUTR file|*.nutr.decompressed" }; if (openFileDialog.ShowDialog() == true) { Nutr.FileTypeBPLength fileType = Nutr.FileTypeBPLength.DRAMA; if (openFileDialog.FileName.Contains("interface", StringComparison.OrdinalIgnoreCase)) { fileType = Nutr.FileTypeBPLength.INTERFACE; } else if (openFileDialog.FileName.Contains("item", StringComparison.OrdinalIgnoreCase)) { fileType = Nutr.FileTypeBPLength.ITEM; } Title = $"Sailor Moon La Luna Splende Script Editor - {Path.GetFileName(openFileDialog.FileName)}"; NutrFile = Nutr.ParseFromFile(openFileDialog.FileName, fileType); commandsListBox.ItemsSource = NutrFile.PostScriptCommands.Select(c => $"{c.Line(NutrFile.Script.Select(n => n.Text).ToList())} (0x{c.LineNumber:X2}):\t\t" + $"0x{string.Join(" ", c.CommandBytes.Select(cb => $"{cb:X2}"))}"); dialogueListBox.ItemsSource = NutrFile.DialogueBoxes; } }
public static Nutr ParseFromFile(string file, FileTypeBPLength fileType) { byte[] data = File.ReadAllBytes(file); Nutr nutr = new Nutr(); int filePtr; nutr.BoilerPlate = data.Take((int)fileType).ToArray(); for (filePtr = (int)fileType; filePtr < data.Length;) { int length = BitConverter.ToInt32(new byte[] { data[filePtr], data[filePtr + 1], data[filePtr + 2], data[filePtr + 3] }); filePtr += 4; byte[] textBytes = new byte[length]; for (int j = 0; j < length; j++) { textBytes[j] = data[filePtr]; filePtr++; } string text = Encoding.UTF8.GetString(textBytes); if ((fileType == FileTypeBPLength.DRAMA && text == "suspend") || (fileType != FileTypeBPLength.DRAMA && text == "getString")) { nutr.Script.Add(new NutrLine { Text = text }); break; } byte[] lineEnd = new byte[] { data[filePtr], data[filePtr + 1], data[filePtr + 2], data[filePtr + 3] }; if (!lineEnd.SequenceEqual(NutrLine.LineEnd)) { throw new FileFormatException($"Expected line end after string '{text}' but found sequence '0x{lineEnd[0]:X2} 0x{lineEnd[1]:X2} 0x{lineEnd[2]:X2} 0x{lineEnd[3]:X2}' instead."); } filePtr += 4; nutr.Script.Add(new NutrLine { Text = text }); } bool encounteredTrapTrap = false; for (; ; filePtr++) { if (data[filePtr - 8] == 'T' && data[filePtr - 7] == 'R' && data[filePtr - 6] == 'A' && data[filePtr - 5] == 'P' && data[filePtr - 4] == 'T' && data[filePtr - 3] == 'R' && data[filePtr - 2] == 'A' && data[filePtr - 1] == 'P') { if (encounteredTrapTrap) { break; } else { encounteredTrapTrap = true; } } nutr.PostScript.Add(data[filePtr]); } for (; !(data[filePtr] == 'T' && data[filePtr + 1] == 'R' && data[filePtr + 2] == 'A' && data[filePtr + 3] == 'P');) { int lineNumber = BitConverter.ToInt32(new byte[] { data[filePtr], data[filePtr + 1], data[filePtr + 2], data[filePtr + 3] }); if (lineNumber > nutr.Script.Count) { break; } nutr.PostScriptCommands.Add(new PostScriptCommand { LineNumber = lineNumber, CommandBytes = new byte[] { data[filePtr + 4], data[filePtr + 5], data[filePtr + 6], data[filePtr + 7] }, }); filePtr += 8; } for (; filePtr < data.Length; filePtr++) { nutr.PostPostScript.Add(data[filePtr]); } if (fileType == FileTypeBPLength.DRAMA) { DialogueBox currentDialogueBox = new DialogueBox();; bool msg = false; foreach (var line in nutr.PostScriptCommands) { string text = line.Line(nutr.Script.Select(l => l.Text).ToList()); if (text == "msg") { msg = true; } else if (msg) { currentDialogueBox.DialogueLineIndices.Add(line.LineNumber); msg = false; } else if (currentDialogueBox != null && text == "talk") { nutr.DialogueBoxes.Add(currentDialogueBox); currentDialogueBox = new DialogueBox(); } } } else { for (int i = 0; i < nutr.Script.Count; i++) { nutr.DialogueBoxes.Add(new DialogueBox { DialogueLineIndices = new List <int> { i } }); } } return(nutr); }
public List <string> DialogueLineStrings(Nutr nutr) { return(DialogueLineIndices.Select(i => nutr.Script[i].Text).ToList()); }