private static TokenText ParseSpeakerText(IReadOnlyList <byte> bytes, FormatVersion version, Encoding encoding) { var line = new TokenText(); int bufferIndex = 0; while (bufferIndex < bytes.Count) { if (!TryParseTokens(bytes, ref bufferIndex, out var tokens, version, encoding)) { break; } line.Tokens.AddRange(tokens); } return(line); }
private static void ParsePages(IDialog message, IReadOnlyList <int> lineStartAddresses, IReadOnlyList <byte> buffer, FormatVersion version, Encoding encoding) { if (lineStartAddresses.Count == 0 || buffer.Count == 0) { return; } // The addresses are not relative to the start of the buffer // so we rebase the addresses first int lineStartAddressBase = lineStartAddresses[0]; int[] rebasedLineStartAddresses = new int[lineStartAddresses.Count]; for (int i = 0; i < lineStartAddresses.Count; i++) { rebasedLineStartAddresses[i] = lineStartAddresses[i] - lineStartAddressBase; } for (int lineIndex = 0; lineIndex < rebasedLineStartAddresses.Length; lineIndex++) { // Initialize a new line var line = new TokenText(); // Now that the line start addresses have been rebased, we can use them as indices into the buffer int bufferIndex = rebasedLineStartAddresses[lineIndex]; // Calculate the line end index int lineEndIndex = (lineIndex + 1) != rebasedLineStartAddresses.Length ? rebasedLineStartAddresses[lineIndex + 1] : buffer.Count; // Loop over the buffer until we find a 0 byte or have reached the end index while (bufferIndex < lineEndIndex) { if (!TryParseTokens(buffer, ref bufferIndex, out var tokens, version, encoding)) { break; } line.Tokens.AddRange(tokens); } // Add line to list of lines message.Lines.Add(line); } }
// TODO: maybe move the parsing functions to a seperate class /// <summary> /// Creates a <see cref="MessageScript"/> from a <see cref="MessageScriptBinary"/>. /// </summary> public static MessageScript FromBinary(MessageScriptBinary binary, FormatVersion version = FormatVersion.Detect, Encoding encoding = null) { if (binary == null) { throw new ArgumentNullException(nameof(binary)); } if (binary.DialogHeaders == null) { throw new ArgumentNullException(nameof(binary)); } // Create new script instance & set user id, format version var instance = new MessageScript { Id = binary.Header.UserId, FormatVersion = version == FormatVersion.Detect ? ( FormatVersion)binary.FormatVersion : version, Encoding = encoding }; // Convert the binary messages to their counterpart var labelOccurences = new Dictionary <string, int>(); foreach (var messageHeader in binary.DialogHeaders) { IDialog message; IReadOnlyList <int> pageStartAddresses; IReadOnlyList <byte> buffer; int pageCount; switch (messageHeader.Kind) { case BinaryDialogKind.Message: { var binaryMessage = (BinaryMessageDialog)messageHeader.Data.Value; pageStartAddresses = binaryMessage.PageStartAddresses; buffer = binaryMessage.TextBuffer; pageCount = binaryMessage.PageCount; // check for duplicates var name = ResolveName(labelOccurences, binaryMessage.Name); if (binaryMessage.SpeakerId == 0xFFFF) { message = new MessageDialog(name); } else if ((binaryMessage.SpeakerId & 0x8000) == 0x8000) { Trace.WriteLine(binaryMessage.SpeakerId.ToString("X4")); message = new MessageDialog(name, new VariableSpeaker(binaryMessage.SpeakerId & 0x0FFF)); } else { if (binary.SpeakerTableHeader.SpeakerNameArray.Value == null) { throw new InvalidDataException("Speaker name array is null while being referenced"); } TokenText speakerName = null; if (binaryMessage.SpeakerId < binary.SpeakerTableHeader.SpeakerCount) { speakerName = ParseSpeakerText(binary.SpeakerTableHeader.SpeakerNameArray .Value[binaryMessage.SpeakerId].Value, instance.FormatVersion, encoding == null ? Encoding.ASCII : encoding); } message = new MessageDialog(name, new NamedSpeaker(speakerName)); } } break; case BinaryDialogKind.Selection: { var binaryMessage = ( BinarySelectionDialog )messageHeader.Data.Value; pageStartAddresses = binaryMessage.OptionStartAddresses; buffer = binaryMessage.TextBuffer; pageCount = binaryMessage.OptionCount; var name = ResolveName(labelOccurences, binaryMessage.Name); message = new SelectionDialog(name, (SelectionDialogPattern)binaryMessage.Pattern); } break; default: throw new InvalidDataException("Unknown message type"); } if (pageCount != 0) { // Parse the line data ParsePages(message, pageStartAddresses, buffer, instance.FormatVersion, encoding == null ? Encoding.ASCII : encoding); } // Add it to the message list instance.Dialogs.Add(message); } return(instance); }
public NamedSpeaker(string name) { Name = new TokenTextBuilder() .AddString(name) .Build(); }
/// <summary> /// Constructs a new speaker. /// </summary> /// <param name="name">The name of the speaker.</param> public NamedSpeaker(TokenText name) { Name = name; }