private Dictionary <uint, dynamic> AlreadyReadNodes = new Dictionary <uint, dynamic>(); //Offset in the file, reference to node private dynamic ReadNode(BinaryDataReader reader, ByamlNodeType nodeType = 0) { // Read the node type if it has not been provided yet. bool nodeTypeGiven = nodeType != 0; if (!nodeTypeGiven) { nodeType = (ByamlNodeType)reader.ReadByte(); } if (nodeType >= ByamlNodeType.Array && nodeType <= ByamlNodeType.PathArray) { // Get the length of arrays. long?oldPos = null; uint offset = 0; if (nodeTypeGiven) { // If the node type was given, the array value is read from an offset. offset = reader.ReadUInt32(); if (AlreadyReadNodes.ContainsKey(offset)) { return(AlreadyReadNodes[offset]); } oldPos = reader.Position; reader.Seek(offset, SeekOrigin.Begin); } else { reader.Seek(-1); } dynamic value = null; int length = (int)Get3LsbBytes(reader.ReadUInt32()); switch (nodeType) { case ByamlNodeType.Array: value = ReadArrayNode(reader, length, offset); break; case ByamlNodeType.Dictionary: value = ReadDictionaryNode(reader, length, offset); break; case ByamlNodeType.StringArray: value = ReadStringArrayNode(reader, length); break; case ByamlNodeType.PathArray: value = ReadPathArrayNode(reader, length); break; default: throw new ByamlException($"Unknown node type '{nodeType}'."); } // Seek back to the previous position if this was a value positioned at an offset. if (oldPos.HasValue) { reader.Seek(oldPos.Value, SeekOrigin.Begin); } return(value); } else { // Read the following UInt32 which is representing the value directly. switch (nodeType) { case ByamlNodeType.StringIndex: return(_stringArray[reader.ReadInt32()]); case ByamlNodeType.PathIndex: return(_pathArray[reader.ReadInt32()]); case ByamlNodeType.Boolean: return(reader.ReadInt32() != 0); case ByamlNodeType.Integer: return(reader.ReadInt32()); case ByamlNodeType.Float: return(reader.ReadSingle()); case ByamlNodeType.Null: reader.Seek(0x4); return(null); default: throw new ByamlException($"Unknown node type '{nodeType}'."); } } }
private void WriteDictionary(BinaryDataWriter writer, object obj) { // Create a string-object dictionary out of the members. Dictionary <string, object> dictionary = new Dictionary <string, object>(); // Add the custom members if any have been created when collecting node contents previously. Dictionary <string, object> customMembers; if (_customMembers.TryGetValue(obj, out customMembers)) { foreach (KeyValuePair <string, object> customMember in customMembers) { dictionary.Add(customMember.Key, customMember.Value); } } // Add the ByamlMemberAttribute decorated members. ByamlObjectInfo objectInfo = _byamlObjectInfos[obj.GetType()]; foreach (KeyValuePair <string, ByamlMemberInfo> member in objectInfo.Members) { object value = member.Value.GetValue(obj); if (value != null || !member.Value.Optional) { dictionary.Add(member.Key, value); } } // Dictionaries need to be sorted ordinally by key. var sortedDict = dictionary.Values.Zip(dictionary.Keys, (Value, Key) => new { Key, Value }) .OrderBy(x => x.Key, StringComparer.Ordinal).ToList(); WriteTypeAndElementCount(writer, ByamlNodeType.Dictionary, dictionary.Count); // Write the key-value pairs. Dictionary <Offset, object> offsetElements = new Dictionary <Offset, object>(); foreach (var keyValuePair in sortedDict) { string key = keyValuePair.Key; object element = keyValuePair.Value; // Get the index of the key string in the file's name array and write it together with the type. uint keyIndex = (uint)_nameArray.IndexOf(key); ByamlNodeType nodeType = element == null ? ByamlNodeType.Null : GetNodeType(element.GetType()); if (Settings.ByteOrder == ByteOrder.BigEndian) { writer.Write(keyIndex << 8 | (uint)nodeType); } else { writer.Write(keyIndex | (uint)nodeType << 24); } // Write the elements. Complex types are just offsets, primitive types are directly written as values. if (nodeType == ByamlNodeType.Array || nodeType == ByamlNodeType.Dictionary) { offsetElements.Add(writer.ReserveOffset(), element); } else { WritePrimitiveType(writer, nodeType, element); } } // Write the array or dictionary elements and satisfy their offsets. foreach (KeyValuePair <Offset, object> offsetElement in offsetElements) { WriteArrayOrDictionary(writer, offsetElement.Key, offsetElement.Value); } }
public UnamedNode(EndianBinaryReader reader) { Address = reader.BaseStream.Position; Nodes = new Collection <ByamlNode>(); int count = reader.ReadInt32() & 0xffffff; byte[] types = reader.ReadBytes(count); while (reader.BaseStream.Position % 4 != 0) { reader.ReadByte(); } long start = reader.BaseStream.Position; for (int i = 0; i < count; i++) { ByamlNodeType type = (ByamlNodeType)types[i]; switch (type) { case ByamlNodeType.String: Nodes.Add(new String(reader)); break; case ByamlNodeType.Data: Nodes.Add(new Data(reader)); break; case ByamlNodeType.Boolean: Nodes.Add(new Boolean(reader)); break; case ByamlNodeType.Int: Nodes.Add(new Int(reader)); break; case ByamlNodeType.Single: Nodes.Add(new Single(reader)); break; case ByamlNodeType.UnamedNode: reader.BaseStream.Position = reader.ReadInt32(); Nodes.Add(new UnamedNode(reader)); break; case ByamlNodeType.NamedNode: reader.BaseStream.Position = reader.ReadInt32(); Nodes.Add(new NamedNode(reader)); break; case ByamlNodeType.Null: Nodes.Add(new Null(reader)); break; default: throw new InvalidDataException(); } reader.BaseStream.Position = start + (i + 1) * 4; } Length = reader.BaseStream.Position - Length; }
private object ReadValue(BinaryDataReader reader, Type type, ByamlNodeType nodeType = 0) { // Read the node type if it has not been provided from an array or dictionary. bool nodeTypeGiven = nodeType != 0; if (!nodeTypeGiven) { nodeType = (ByamlNodeType)reader.ReadByte(); } if (nodeType >= ByamlNodeType.Array && nodeType <= ByamlNodeType.PathArray) { // Get the length of arrays. If the node type was given, the array value is read from an offset. long?oldPos = null; if (nodeTypeGiven) { uint offset = reader.ReadUInt32(); oldPos = reader.Position; reader.Seek(offset, SeekOrigin.Begin); } else { reader.Seek(-1); } int length = (int)Get3LsbBytes(reader.ReadUInt32()); // Read the array data. object value = null; switch (nodeType) { case ByamlNodeType.Array: value = ReadArray(reader, type, length); break; case ByamlNodeType.Dictionary: value = ReadDictionary(reader, type, length); break; case ByamlNodeType.StringArray: value = ReadStringArray(reader, type, length); break; case ByamlNodeType.PathArray: if (!Settings.SupportPaths) { throw new ByamlException("Path found, but set to be unsupported."); } value = ReadPathArray(reader, type, length); break; } // Seek back to the previous position if this was a value read from an offset. if (oldPos.HasValue) { reader.Seek(oldPos.Value, SeekOrigin.Begin); } return(value); } else { // Read the following uint which is representing the value directly. switch (nodeType) { case ByamlNodeType.StringIndex: return(_stringArray[reader.ReadInt32()]); case ByamlNodeType.PathIndex: if (!Settings.SupportPaths) { throw new ByamlException("Path found, but set to be unsupported."); } return(_pathArray[reader.ReadInt32()]); case ByamlNodeType.Boolean: return(reader.ReadInt32() != 0); case ByamlNodeType.Integer: return(reader.ReadInt32()); case ByamlNodeType.Float: return(reader.ReadSingle()); case ByamlNodeType.Null: int value = reader.ReadInt32(); if (value != 0) { throw new ByamlException($"Null node has unexpected value of {value}."); } return(null); default: throw new ByamlException($"Invalid BYAML node type {nodeType}."); } } }
private object ReadDictionary(BinaryDataReader reader, Type type, int length) { // Get the information required to serialize this type (for Nullables take the underlying type). ByamlObjectInfo objectInfo; Type nullableType = Nullable.GetUnderlyingType(type); if (nullableType != null) { type = nullableType; } if (!_byamlObjectInfos.TryGetValue(type, out objectInfo)) { objectInfo = new ByamlObjectInfo(type); _byamlObjectInfos.Add(type, objectInfo); } // Instantiate the type and read in the elements. Use a given instance as the root if available. object instance; if (_instance == null) { instance = Activator.CreateInstance(type, true); } else { instance = _instance; _instance = null; } // Collect them in a dictionary for custom deserialization. Dictionary <string, object> dictionary = new Dictionary <string, object>(); for (int i = 0; i < length; i++) { uint indexAndType = reader.ReadUInt32(); int nodeNameIndex = (int)Get3MsbBytes(indexAndType); ByamlNodeType nodeType = (ByamlNodeType)Get1MsbByte(indexAndType); string key = _nameArray[nodeNameIndex]; // Find a member for it to map the value to. object value; ByamlMemberInfo member; if (objectInfo.Members.TryGetValue(key, out member)) { // The key could be mapped to a member, read it as the member's type. value = ReadValue(reader, member.Type, nodeType); member.SetValue(instance, value); } else { // If the key could not be mapped to a member, add it to the dictionary for custom deserialization. //Debug.WriteLine($"No member in {type.Name} found to map key \"{key}\" to."); value = ReadValue(reader, nodeType.GetInstanceType(), nodeType); } dictionary.Add(key, value); } // Call IByamlSerializable methods if the interface was implemented. if (objectInfo.ImplementsByamlSerializable) { IByamlSerializable byamlSerializable = (IByamlSerializable)instance; byamlSerializable.DeserializeByaml(dictionary); } // Check if any required fields were not filled. foreach (ByamlMemberInfo member in objectInfo.Members.Values) { if (!member.Optional && member.GetValue(instance) == null) { throw new ByamlException( $"Member {type.Name}.{member.MemberInfo.Name} is not optional, but has not been deserialized."); } } return(instance); }
public ByamlEntry(ByamlNodeType NodeType, object Value) { this.Value = Value; this.NodeType = NodeType; }
// ---- METHODS (PRIVATE) -------------------------------------------------------------------------------------- // ---- Loading ---- private dynamic Read(Stream stream) { // Open a reader on the given stream. using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.UTF8, true)) { reader.ByteOrder = _byteOrder; // Load the header, specifying magic bytes ("BY"), version and main node offsets. if (reader.ReadUInt16() != _magicBytes) { _byteOrder = _byteOrder == ByteOrder.LittleEndian ? ByteOrder.BigEndian : ByteOrder.LittleEndian; reader.ByteOrder = _byteOrder; reader.BaseStream.Position = 0; if (reader.ReadUInt16() != _magicBytes) { throw new Exception("Header mismatch"); } } _version = reader.ReadUInt16(); uint nameArrayOffset = reader.ReadUInt32(); uint stringArrayOffset = reader.ReadUInt32(); using (reader.TemporarySeek()) { // Paths are supported if the third offset is a path array (or null) and the fourth a root. ByamlNodeType thirdNodeType = PeekNodeType(reader); reader.Seek(sizeof(uint)); ByamlNodeType fourthNodeType = PeekNodeType(reader); _supportPaths = (thirdNodeType == ByamlNodeType.None || thirdNodeType == ByamlNodeType.PathArray) && (fourthNodeType == ByamlNodeType.Array || fourthNodeType == ByamlNodeType.Dictionary); } uint pathArrayOffset = 0; if (_supportPaths) { pathArrayOffset = reader.ReadUInt32(); } uint rootNodeOffset = reader.ReadUInt32(); // Read the name array, holding strings referenced by index for the names of other nodes. if (nameArrayOffset != 0) { reader.Seek(nameArrayOffset, SeekOrigin.Begin); _nameArray = ReadNode(reader); } // Read the optional string array, holding strings referenced by index in string nodes. if (stringArrayOffset != 0) { reader.Seek(stringArrayOffset, SeekOrigin.Begin); _stringArray = ReadNode(reader); } // Read the optional path array, holding paths referenced by index in path nodes. if (_supportPaths && pathArrayOffset != 0) { // The third offset is the root node, so just read that and we're done. reader.Seek(pathArrayOffset, SeekOrigin.Begin); _pathArray = ReadNode(reader); } if (rootNodeOffset == 0) //empty byml { return(new List <dynamic>()); } // Read the root node. reader.Seek(rootNodeOffset, SeekOrigin.Begin); return(ReadNode(reader, 0)); } }
public NamedNode(EndianBinaryReader reader) { Address = reader.BaseStream.Position; Nodes = new Collection <KeyValuePair <int, ByamlNode> >(); int count = reader.ReadInt32() & 0xffffff; for (int i = 0; i < count; i++) { uint temp = reader.ReadUInt32(); int name = (int)(temp >> 8); ByamlNodeType type = (ByamlNodeType)(byte)temp; //Console.WriteLine(i.ToString() + "(" + type.ToString() + "): " + temp.ToString()); switch (type) { case ByamlNodeType.String: Nodes.Add(new KeyValuePair <int, ByamlNode>(name, new String(reader))); break; case ByamlNodeType.Data: Nodes.Add(new KeyValuePair <int, ByamlNode>(name, new Data(reader))); break; case ByamlNodeType.Boolean: Nodes.Add(new KeyValuePair <int, ByamlNode>(name, new Boolean(reader))); break; case ByamlNodeType.Int: Nodes.Add(new KeyValuePair <int, ByamlNode>(name, new Int(reader))); break; case ByamlNodeType.Single: Nodes.Add(new KeyValuePair <int, ByamlNode>(name, new Single(reader))); break; case ByamlNodeType.Double: Nodes.Add(new KeyValuePair <int, ByamlNode>(name, new Double(reader))); break; case ByamlNodeType.UnamedNode: reader.BaseStream.Position = reader.ReadInt32(); Nodes.Add(new KeyValuePair <int, ByamlNode>(name, new UnamedNode(reader))); break; case ByamlNodeType.NamedNode: reader.BaseStream.Position = reader.ReadInt32(); Nodes.Add(new KeyValuePair <int, ByamlNode>(name, new NamedNode(reader))); break; case ByamlNodeType.Null: Nodes.Add(new KeyValuePair <int, ByamlNode>(name, new Null(reader))); break; default: throw new InvalidDataException(); } reader.BaseStream.Position = Address + (i + 1) * 8 + 4; } Length = reader.BaseStream.Position - Length; }
protected bool TryStartLoading() { // Load the header, specifying magic bytes ("BY"), version and main node offsets. if (_reader.ReadUInt16() != BYAML_MAGIC) { //switch endian and try again _byteOrder = _byteOrder == ByteOrder.LittleEndian ? ByteOrder.BigEndian : ByteOrder.LittleEndian; _reader = new BinaryDataReader(_reader.BaseStream, ByamlFile.GetEncoding(_byteOrder), true) { ByteOrder = _byteOrder }; _reader.Position = 0; if (_reader.ReadUInt16() != BYAML_MAGIC) { throw new Exception("Header mismatch"); } } _version = _reader.ReadUInt16(); uint nameArrayOffset = _reader.ReadUInt32(); uint stringArrayOffset = _reader.ReadUInt32(); if (_reader.Length == 16) { _supportPaths = false; } else { using (_reader.TemporarySeek()) { // Paths are supported if the third offset is a path array (or unknown) and the fourth a root. ByamlNodeType thirdNodeType = PeekNodeType(_reader); _reader.Seek(sizeof(uint)); ByamlNodeType fourthNodeType = PeekNodeType(_reader); _supportPaths = (thirdNodeType == ByamlNodeType.Unknown || thirdNodeType == ByamlNodeType.PathArray) && (fourthNodeType == ByamlNodeType.Array || fourthNodeType == ByamlNodeType.Dictionary); } } uint pathArrayOffset = 0; if (_supportPaths) { pathArrayOffset = _reader.ReadUInt32(); } uint rootNodeOffset = _reader.ReadUInt32(); if (rootNodeOffset == 0) //empty byml { return(false); } // Read the name array, holding strings referenced by index for the names of other nodes. if (nameArrayOffset != 0) { _reader.Seek(nameArrayOffset, SeekOrigin.Begin); _nameArray = ReadCollectionNode(_reader.ReadUInt32()); } // Read the optional string array, holding strings referenced by index in string nodes. if (stringArrayOffset != 0) { _reader.Seek(stringArrayOffset, SeekOrigin.Begin); _stringArray = ReadCollectionNode(_reader.ReadUInt32()); } // Read the optional path array, holding paths referenced by index in path nodes. if (_supportPaths && pathArrayOffset != 0) { // The third offset is the root node, so just read that and we're done. _reader.Seek(pathArrayOffset, SeekOrigin.Begin); _pathArray = ReadCollectionNode(_reader.ReadUInt32()); } // Read the root node. _reader.Seek(rootNodeOffset, SeekOrigin.Begin); return(true); dynamic ReadCollectionNode(uint lengthAndType) { int length = (int)Get3LsbBytes(lengthAndType); ByamlNodeType nodeType = (ByamlNodeType)Get1MsbByte(lengthAndType); switch (nodeType) { case ByamlNodeType.Array: return(ReadArrayNode(_reader, length)); case ByamlNodeType.Dictionary: return(ReadDictionaryNode(_reader, length)); case ByamlNodeType.StringArray: return(ReadStringArrayNode(_reader, length)); case ByamlNodeType.PathArray: return(ReadPathArrayNode(_reader, length)); default: return(null); //should never happen } } }
protected static bool IsReferenceType(ByamlNodeType nodeType) => (ByamlNodeType.Array <= nodeType && nodeType <= ByamlNodeType.PathArray);
protected dynamic ReadNodeValue(BinaryDataReader _reader, ByamlNodeType nodeType) { if (ByamlNodeType.Array <= nodeType && nodeType <= ByamlNodeType.PathArray) { int length = (int)Get3LsbBytes(_reader.ReadUInt32()); switch (nodeType) { case ByamlNodeType.Array: return(ReadArrayNode(_reader, length)); case ByamlNodeType.Dictionary: return(ReadDictionaryNode(_reader, length)); case ByamlNodeType.StringArray: return(ReadStringArrayNode(_reader, length)); case ByamlNodeType.PathArray: return(ReadPathArrayNode(_reader, length)); default: return(null); //should never happen } } // Read the following UInt32 which is representing the value directly. switch (nodeType) { case ByamlNodeType.StringIndex: return(_stringArray[_reader.ReadInt32()]); case ByamlNodeType.PathIndex: return(_pathArray[_reader.ReadInt32()]); case ByamlNodeType.Boolean: return(_reader.ReadInt32() != 0); case ByamlNodeType.Integer: return(_reader.ReadInt32()); case ByamlNodeType.Float: return(_reader.ReadSingle()); case ByamlNodeType.UInteger: return(_reader.ReadUInt32()); case ByamlNodeType.Long: case ByamlNodeType.ULong: case ByamlNodeType.Double: var pos = _reader.Position; _reader.Position = _reader.ReadUInt32(); dynamic value = readLongValFromOffset(nodeType); _reader.Position = pos + 4; return(value); case ByamlNodeType.Null: _reader.Seek(0x4); return(null); default: throw new Exception($"Unknown node type '{nodeType}'."); } dynamic readLongValFromOffset(ByamlNodeType type) { switch (type) { case ByamlNodeType.Long: return(_reader.ReadInt64()); case ByamlNodeType.ULong: return(_reader.ReadUInt64()); case ByamlNodeType.Double: return(_reader.ReadDouble()); } throw new Exception($"Unknown node type '{nodeType}'."); } }
/// <summary> /// Create from Reading the games files /// </summary> public void Create(string StageDataPath) { string[] Zones = Directory.GetFiles(StageDataPath, "*Map1.szs"); string[] Designs = Directory.GetFiles(StageDataPath, "*Design1.szs"); string[] Sounds = Directory.GetFiles(StageDataPath, "*Sound1.szs"); Dictionary <string, List <ObjectInfo> > MAPinfosByListName = new Dictionary <string, List <ObjectInfo> >() { ["AreaList"] = new List <ObjectInfo>(), ["CheckPointList"] = new List <ObjectInfo>(), ["DemoObjList"] = new List <ObjectInfo>(), ["GoalList"] = new List <ObjectInfo>(), ["ObjectList"] = new List <ObjectInfo>(), ["PlayerList"] = new List <ObjectInfo>(), ["SkyList"] = new List <ObjectInfo>(), ["Links"] = new List <ObjectInfo>() }; Dictionary <string, List <ObjectInfo> > DESIGNinfosByListName = new Dictionary <string, List <ObjectInfo> >() { ["AreaList"] = new List <ObjectInfo>(), ["CheckPointList"] = new List <ObjectInfo>(), ["DemoObjList"] = new List <ObjectInfo>(), ["GoalList"] = new List <ObjectInfo>(), ["ObjectList"] = new List <ObjectInfo>(), ["PlayerList"] = new List <ObjectInfo>(), ["SkyList"] = new List <ObjectInfo>(), ["Links"] = new List <ObjectInfo>() }; Dictionary <string, List <ObjectInfo> > SOUNDinfosByListName = new Dictionary <string, List <ObjectInfo> >() { ["AreaList"] = new List <ObjectInfo>(), ["CheckPointList"] = new List <ObjectInfo>(), ["DemoObjList"] = new List <ObjectInfo>(), ["GoalList"] = new List <ObjectInfo>(), ["ObjectList"] = new List <ObjectInfo>(), ["PlayerList"] = new List <ObjectInfo>(), ["SkyList"] = new List <ObjectInfo>(), ["Links"] = new List <ObjectInfo>() }; for (int i = 0; i < Zones.Length; i++) { GetObjectInfos(Zones[i], MAPinfosByListName); } for (int i = 0; i < Designs.Length; i++) { GetObjectInfos(Designs[i], DESIGNinfosByListName); } for (int i = 0; i < Sounds.Length; i++) { GetObjectInfos(Sounds[i], SOUNDinfosByListName); } void GetParameters <T>(Dictionary <string, List <ObjectInfo> > infosByListName) where T : Parameter, new() { byte ListID = 0; foreach (KeyValuePair <string, List <ObjectInfo> > keyValuePair in infosByListName) { for (int j = 0; j < keyValuePair.Value.Count; j++) { if (keyValuePair.Value[j].ClassName == "Rail") { continue; } ObjectInfo Tmp = keyValuePair.Value[j]; if (ObjectParameters.ContainsKey(Tmp.ClassName)) { if (Tmp.ObjectName != "" && !ObjectParameters[Tmp.ClassName].ObjectNames.Any(O => O == Tmp.ObjectName)) { ObjectParameters[Tmp.ClassName].ObjectNames.Add(Tmp.ObjectName); } if (Tmp.ModelName != "" && !ObjectParameters[Tmp.ClassName].ModelNames.Any(O => O == Tmp.ModelName)) { ObjectParameters[Tmp.ClassName].ModelNames.Add(Tmp.ModelName); } foreach (var propertyEntry in Tmp.PropertyEntries) { if (!ObjectParameters[Tmp.ClassName].Properties.Any(O => O.Key == propertyEntry.Key)) { ByamlNodeType type = propertyEntry.Value.NodeType; if (type == ByamlNodeType.Null) { type = ByamlNodeType.StringIndex; } ObjectParameters[Tmp.ClassName].Properties.Add(new KeyValuePair <string, string>(propertyEntry.Key, type == ByamlNodeType.StringIndex ? "String" : type.ToString())); } } foreach (string key in Tmp.LinkEntries.Keys) { if (!ObjectParameters[Tmp.ClassName].LinkNames.Any(O => O == key)) { ObjectParameters[Tmp.ClassName].LinkNames.Add(key); } } } else { T OP = new T() { ClassName = Tmp.ClassName }; if (Tmp.ObjectName != "") { OP.ObjectNames.Add(Tmp.ObjectName); } if (Tmp.ModelName != "" && Tmp.ModelName != null) { OP.ModelNames.Add(Tmp.ModelName); } foreach (var propertyEntry in Tmp.PropertyEntries) { ByamlNodeType type = propertyEntry.Value.NodeType; if (type == ByamlNodeType.Null) { type = ByamlNodeType.StringIndex; } OP.Properties.Add(new KeyValuePair <string, string>(propertyEntry.Key, type == ByamlNodeType.StringIndex ? "String" : type.ToString())); } foreach (string key in Tmp.LinkEntries.Keys) { OP.LinkNames.Add(key); } OP.ObjList = (ObjList)ListID; ObjectParameters.Add(Tmp.ClassName, OP); } } ListID++; } } GetParameters <ObjectParameter>(MAPinfosByListName); GetParameters <DesignParameter>(DESIGNinfosByListName); GetParameters <SoundFXParameter>(SOUNDinfosByListName); }