// 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); }