using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using TC = System.ComponentModel.TypeConverterAttribute; using EXP = System.ComponentModel.ExpandableObjectConverter; using SharpDX; namespace CodeWalker.GameFiles { [TC(typeof(EXP))] public class RelFile : PackedFile { public RpfFileEntry FileEntry { get; set; } public string Name { get; set; } public uint Type { get; set; } public uint DataLength { get; set; } public byte[] DataBlock { get; set; } public uint DataUnkVal { get; set; } public uint NameTableLength { get; set; } public uint NameTableCount { get; set; } public uint[] NameTableOffsets { get; set; } public string[] NameTable { get; set; } public uint IndexCount { get; set; } public uint IndexStringFlags { get; set; } public RelIndexHash[] IndexHashes { get; set; } public RelIndexString[] IndexStrings { get; set; } public uint Unk05Count { get; set; } public uint[] Unk05Arr { get; set; } public MetaHash[] Unk05Hashes { get; set; } public uint ContainerCount { get; set; } public uint[] ContainerUnkArr { get; set; } public MetaHash[] ContainerHashes { get; set; } public RelData[] RelDatas { get; set; } public RelData[] RelDatasSorted { get; set; } //testing zone for decoding .rel audio files. public Dictionary RelDataDict { get; set; } = new Dictionary(); public RelFile() { } public RelFile(RpfFileEntry entry) { FileEntry = entry; } public void Load(byte[] data, RpfFileEntry entry) { FileEntry = entry; Name = entry.Name; MemoryStream ms = new MemoryStream(data); BinaryReader br = new BinaryReader(ms); StringBuilder sb = new StringBuilder(); Type = br.ReadUInt32(); //type/version? DataLength = br.ReadUInt32(); //length of data block DataBlock = br.ReadBytes((int)DataLength); //main data block... NameTableLength = br.ReadUInt32(); //length of this nametable block NameTableCount = br.ReadUInt32(); if (NameTableCount > 0) { uint[] d02 = new uint[NameTableCount]; //string offsets for (uint i = 0; i < NameTableCount; i++) { d02[i] = br.ReadUInt32(); } NameTableOffsets = d02; string[] names = new string[NameTableCount]; for (uint i = 0; i < NameTableCount; i++) { sb.Clear(); while (true) { char c = (char)br.ReadByte(); if (c != 0) sb.Append(c); else break; } names[i] = sb.ToString(); //JenkIndex.Ensure(names[i]); //really need both here..? JenkIndex.Ensure(names[i].ToLowerInvariant()); } NameTable = names; } IndexCount = br.ReadUInt32(); //count of index items if (IndexCount > 0) { //checking NameTableLength here doesn't make sense! if ((Type == 4) && (NameTableLength == 4))//audioconfig.dat4.rel { IndexStringFlags = br.ReadUInt32(); //what is this? 2524 RelIndexString[] indexstrs = new RelIndexString[IndexCount]; for (uint i = 0; i < IndexCount; i++) { byte sl = br.ReadByte(); sb.Clear(); for (int j = 0; j < sl; j++) { char c = (char)br.ReadByte(); if (c != 0) sb.Append(c); } RelIndexString cunk01 = new RelIndexString(); cunk01.Name = sb.ToString(); cunk01.Offset = br.ReadUInt32(); cunk01.Length = br.ReadUInt32(); indexstrs[i] = cunk01; } IndexStrings = indexstrs; } else //for all other .rel files... { RelIndexHash[] indexhashes = new RelIndexHash[IndexCount]; for (uint i = 0; i < IndexCount; i++) { RelIndexHash unk01 = new RelIndexHash(); unk01.Name = new MetaHash(br.ReadUInt32()); unk01.Offset = br.ReadUInt32(); unk01.Length = br.ReadUInt32(); indexhashes[i] = unk01; } IndexHashes = indexhashes; } } Unk05Count = br.ReadUInt32(); if (Unk05Count != 0) { uint[] d05 = new uint[Unk05Count]; MetaHash[] d05h = new MetaHash[Unk05Count]; for (uint i = 0; i < Unk05Count; i++) { d05[i] = br.ReadUInt32(); var pos = ms.Position; ms.Position = d05[i]; d05h[i] = new MetaHash(br.ReadUInt32()); ms.Position = pos; } Unk05Arr = d05; Unk05Hashes = d05h; } ContainerCount = br.ReadUInt32(); if (ContainerCount != 0) { uint[] cunks = new uint[ContainerCount]; MetaHash[] chashes = new MetaHash[ContainerCount]; for (uint i = 0; i < ContainerCount; i++) { cunks[i] = br.ReadUInt32(); var pos = ms.Position; ms.Position = cunks[i]; chashes[i] = new MetaHash(br.ReadUInt32()); ms.Position = pos; } ContainerUnkArr = cunks; ContainerHashes = chashes; } if (ms.Position != ms.Length) { } //EOF! br.Dispose(); ms.Dispose(); ParseDataBlock(); } private void ParseDataBlock() { MemoryStream ms = new MemoryStream(DataBlock); BinaryReader br = new BinaryReader(ms); DataUnkVal = br.ReadUInt32(); //3 bytes used... for? ..version? flags? //switch (DataUnkVal) //{ // case 5252715: //dlcbusiness_amp.dat10.rel // case 5301323: //dlcbeach_game.dat149.rel // case 5378673: //dlcmpheist_game.dat150.rel // case 5750395: //dlcbeach_game.dat150.rel // case 6353778: //dlcbeach_game.dat151.rel // case 6894089: //dlcpilotschool_game.dat151.rel // case 6978435: //dlcxmas2_amp.dat10.rel // case 7126027: //audioconfig.dat4.rel // case 7314721: //dlcmpheist_amp.dat10.rel // case 7516460: //dlcpd03_game.dat151.rel // case 7917027: //dlcluxe_amp.dat10.rel // case 7921508: //dlcluxe_game.dat151.rel // case 8149475: //dlcluxe2_amp.dat10.rel // case 8751734: //dlcsfx1_game.dat151.rel // case 9028036: //dlchalloween_amp.dat10.rel // case 9037528: //dlclowrider_amp.dat10.rel // case 9458585: //dlcapartment_amp.dat10.rel // case 9486222: //dlcapartment_mix.dat15.rel // case 9806108: //mpvalentines2_amp.dat10.rel // case 9813679: //dlcjanuary2016_amp.dat10.rel // case 10269543://dlclow2_amp.dat10.rel // case 10891463://dlcexec1_amp.dat10.rel // case 11171338://dlcstunt_amp.dat10.rel // case 11918985://dlcbiker_amp.dat10.rel // case 12470522://dlcimportexport_amp.dat10.rel // case 12974726://audioconfig.dat4.rel // case 13117164://dlcspecialraces_amp.dat10.rel // break; // default: // break; //} List reldatas = new List(); if (IndexHashes != null) { foreach (var indexhash in IndexHashes) { reldatas.Add(ReadRelData(br, indexhash)); } } else if (IndexStrings != null) { foreach (var indexstr in IndexStrings) { reldatas.Add(ReadRelData(br, indexstr)); } } RelDatas = reldatas.ToArray(); reldatas.Sort((d1, d2) => d1.DataOffset.CompareTo(d2.DataOffset)); RelDatasSorted = reldatas.ToArray(); br.Dispose(); ms.Dispose(); RelDataDict.Clear(); foreach (var reldata in RelDatas) { if ((reldata.NameHash == 0) && !string.IsNullOrEmpty(reldata.Name)) { reldata.NameHash = JenkHash.GenHash(reldata.Name); //should this be lower case? JenkIndex.Ensure(reldata.Name); JenkIndex.Ensure(reldata.Name.ToLowerInvariant()); //which one to use? } //if (reldata.NameHash == 0) //{ }//no hits here //if (RelDataDict.ContainsKey(reldata.NameHash)) //{ }//no hits here RelDataDict[reldata.NameHash] = reldata; } foreach (var reldata in RelDatas) { RelSound snd = reldata as RelSound; if (snd != null) { if (snd.AudioTracksCount > 0) { snd.AudioTracks = new RelData[snd.AudioTracksCount]; for (int i = 0; i < snd.AudioTracksCount; i++) { var audhash = snd.AudioTrackHashes[i]; RelData auddata = null; if (RelDataDict.TryGetValue(audhash, out auddata)) { snd.AudioTracks[i] = auddata; } else { } } } if (snd.AudioContainers != null) { foreach (var cnt in snd.AudioContainers) { string cname = JenkIndex.TryGetString(cnt.Hash); if (!string.IsNullOrEmpty(cname)) { } else { } } } } } #region test //foreach (var d in RelDatas) //{ // using (BinaryReader dbr = new BinaryReader(new MemoryStream(d.Data))) // { // switch (Type) // { // case 4: //00000100 //speech.dat4.rel, audioconfig.dat4.rel // ParseData4(d, dbr); // break; // case 10: //00001010 //amp.dat10.rel // ParseData10(d, dbr); // break; // case 15: //00001111 //mix.dat15.rel // ParseData15(d, dbr); // break; // case 16: //00010000 //curves.dat16.rel // ParseData16(d, dbr); // break; // case 22: //00010110 //categories.dat22.rel // ParseData22(d, dbr); // break; // case 54: //00110110 //sounds.dat54.rel // ParseData54(d, dbr); // break; // case 149: //10010101 //game.dat149.rel // ParseData149(d, dbr); // break; // case 150: //10010110 //game.dat150.rel // ParseData150(d, dbr); // break; // case 151: //10010111 //game.dat151.rel // ParseData151(d, dbr); // break; // default: // break; // } // } //} #endregion } private RelData ReadRelData(BinaryReader br, RelIndexHash h) { return ReadRelData(br, null, h.Name, h.Offset, h.Length); } private RelData ReadRelData(BinaryReader br, RelIndexString s) { return ReadRelData(br, s.Name, 0, s.Offset, s.Length); } private RelData ReadRelData(BinaryReader br, string name, MetaHash hash, uint offset, uint length) { br.BaseStream.Position = offset; byte[] data = br.ReadBytes((int)length); RelData d = new RelData(); //use this base object to construct the derived one... d.Name = name; d.NameHash = hash; d.DataOffset = offset; d.DataLength = length; d.Data = data; using (BinaryReader dbr = new BinaryReader(new MemoryStream(data))) { d.ReadType(dbr); switch (Type) { case 4: //speech.dat4.rel, audioconfig.dat4.rel return ReadData4(d, dbr); case 10: //amp.dat10.rel return ReadData10(d, dbr); case 15: //mix.dat15.rel return ReadData15(d, dbr); case 16: //curves.dat16.rel return ReadData16(d, dbr); case 22: //categories.dat22.rel return ReadData22(d, dbr); case 54: //sounds.dat54.rel return ReadData54(d, dbr); case 149: //game.dat149.rel return ReadData149(d, dbr); case 150: //game.dat150.rel return ReadData150(d, dbr); case 151: //game.dat151.rel return ReadData151(d, dbr); default: return d; //shouldn't get here... } } } private RelData ReadData4(RelData d, BinaryReader br) { if (NameTableLength == 4) //(for audioconfig.dat4.rel) { } else //(for eg speech.dat4.rel) { } return d; } private RelData ReadData10(RelData d, BinaryReader br) { return d; } private RelData ReadData15(RelData d, BinaryReader br) { return d; } private RelData ReadData16(RelData d, BinaryReader br) { return d; } private RelData ReadData22(RelData d, BinaryReader br) { //RelSound s = new RelSound(d, br); //return s; return d; } private RelData ReadData54(RelData d, BinaryReader br) { switch ((Dat54SoundType)d.TypeID) { case Dat54SoundType.LoopingSound: return new Dat54LoopingSound(d, br); case Dat54SoundType.EnvelopeSound: return new Dat54EnvelopeSound(d, br); case Dat54SoundType.TwinLoopSound: return new Dat54TwinLoopSound(d, br); case Dat54SoundType.SpeechSound: return new Dat54SpeechSound(d, br); case Dat54SoundType.OnStopSound: return new Dat54OnStopSound(d, br); case Dat54SoundType.WrapperSound: return new Dat54WrapperSound(d, br); case Dat54SoundType.SequentialSound: return new Dat54SequentialSound(d, br); case Dat54SoundType.StreamingSound: return new Dat54StreamingSound(d, br); case Dat54SoundType.RetriggeredOverlappedSound: return new Dat54RetriggeredOverlappedSound(d, br); case Dat54SoundType.CrossfadeSound: return new Dat54CrossfadeSound(d, br); case Dat54SoundType.CollapsingStereoSound: return new Dat54CollapsingStereoSound(d, br); case Dat54SoundType.SimpleSound: return new Dat54SimpleSound(d, br); case Dat54SoundType.MultitrackSound: return new Dat54MultitrackSound(d, br); case Dat54SoundType.RandomizedSound: return new Dat54RandomizedSound(d, br); case Dat54SoundType.EnvironmentSound: return new Dat54EnvironmentSound(d, br); case Dat54SoundType.DynamicEntitySound: return new Dat54DynamicEntitySound(d, br); case Dat54SoundType.SequentialOverlapSound: return new Dat54SequentialOverlapSound(d, br); case Dat54SoundType.ModularSynthSound: return new Dat54ModularSynthSound(d, br); case Dat54SoundType.GranularSound: return new Dat54GranularSound(d, br); case Dat54SoundType.DirectionalSound: return new Dat54DirectionalSound(d, br); case Dat54SoundType.KineticSound: return new Dat54KineticSound(d, br); case Dat54SoundType.SwitchSound: return new Dat54SwitchSound(d, br); case Dat54SoundType.VariableCurveSound: return new Dat54VariableCurveSound(d, br); case Dat54SoundType.VariablePrintValueSound: return new Dat54VariablePrintValueSound(d, br); case Dat54SoundType.VariableBlockSound: return new Dat54VariableBlockSound(d, br); case Dat54SoundType.IfSound: return new Dat54IfSound(d, br); case Dat54SoundType.MathOperationSound: return new Dat54MathOperationSound(d, br); case Dat54SoundType.ParameterTransformSound: return new Dat54ParameterTransformSound(d, br); case Dat54SoundType.FluctuatorSound: return new Dat54FluctuatorSound(d, br); case Dat54SoundType.AutomationSound: return new Dat54AutomationSound(d, br); case Dat54SoundType.ExternalStreamSound: return new Dat54ExternalStreamSound(d, br); case Dat54SoundType.SoundSet: return new Dat54SoundSet(d, br); case Dat54SoundType.Unknown: return new Dat54UnknownSound(d, br); case Dat54SoundType.Unknown2: return new Dat54UnknownSound2(d, br); case Dat54SoundType.SoundList: return new Dat54SoundList(d, br); default: return new Dat54Sound(d, br); //shouldn't get here } } private RelData ReadData149(RelData d, BinaryReader br) { //RelSound s = new RelSound(d, br); //return s; return d; } private RelData ReadData150(RelData d, BinaryReader br) { return d; } private RelData ReadData151(RelData d, BinaryReader br) { switch ((Dat151RelType)d.TypeID) { case Dat151RelType.AmbientZone: return new Dat151AmbientZone(d, br); case Dat151RelType.AmbientEmitter: return new Dat151AmbientEmitter(d, br); default: return new Dat151RelData(d, br); } } #region first research private void ParseData4(RelData d, BinaryReader br) { //speech.dat4.rel, audioconfig.dat4.rel if (d.DataLength == 1) { byte b = br.ReadByte(); switch (b) { case 0: case 25: case 28: case 34: case 89: case 94: case 178: break; default: break; } return; } if (d.DataLength == 2) { byte b = br.ReadByte(); switch (b) { case 4: case 1: case 15: case 12: case 3: case 2: case 7: case 5: case 158: case 25: case 16: case 64: case 6: case 8: case 14: case 22: case 18: case 20: case 32: case 17: case 30: case 9: case 0: case 47: case 224: case 200: case 136: case 45: case 54: case 28: case 19: case 37: case 61: case 38: case 128: case 24: case 26: case 40: case 13: case 36: case 78: case 34: case 10: case 21: case 192: case 60: case 29: case 33: case 72: case 57: case 133: case 11: break; default: break; } return; } if (d.DataLength == 4) { uint h = br.ReadUInt32(); return; } byte b00 = br.ReadByte(); switch (b00) { case 4: case 1: case 0: case 6: case 3: case 2: case 5: case 7: case 15: case 10: case 8: case 9: break; case 23: case 12: case 11: case 16: case 13: case 36: case 30: case 31: case 27: case 20: case 19: case 14: case 40: case 46: case 22: case 18: case 21: case 45: case 17: case 48: case 87: case 38: case 28: case 29: case 43: case 69: case 50: case 25: case 32: case 35: case 34: break; default: break; } } private void ParseData10(RelData d, BinaryReader br) { //amp.dat10.rel byte b00 = br.ReadByte(); switch (b00) { case 1: case 3: break; default: break; } } private void ParseData15(RelData d, BinaryReader br) { //mix.dat15.rel byte b00 = br.ReadByte(); switch (b00) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: break; default: break; } } private void ParseData16(RelData d, BinaryReader br) { //curves.dat16.rel byte b00 = br.ReadByte(); switch (b00) { case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 12: case 13: case 15: break; default: break; } } private void ParseData22(RelData d, BinaryReader br) { //categories.dat22.rel byte b00 = br.ReadByte(); switch (b00) { case 0: break; default: break; } } private void ParseData54(RelData d, BinaryReader br) { //sounds.dat54.rel byte b00 = br.ReadByte(); switch (b00) { case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31: case 32: case 33: case 34: case 35: break; default: break; } } private void ParseData149(RelData d, BinaryReader br) { //game.dat149.rel byte b00 = br.ReadByte(); switch (b00) { case 3: case 4: case 17: case 50: case 57: case 62: case 63: case 66: case 76: case 88: case 90: break; default: break; } } private void ParseData150(RelData d, BinaryReader br) { //game.dat150.rel byte b00 = br.ReadByte(); switch (b00) { case 3: case 4: case 6: case 8: case 17: case 32: case 37: case 38: case 39: case 47: case 50: case 52: case 57: case 62: case 63: case 64: case 65: case 66: case 76: case 88: case 90: case 117: break; default: break; } } private void ParseData151(RelData d, BinaryReader br) { //game.dat151.rel byte b00 = br.ReadByte(); //??? switch (b00) { case 1://new case 2://new case 3: case 4: case 5://new case 6: case 7://new case 8:// case 9://new case 11://new case 12://new case 13://new case 14://new case 15://new case 16://new case 17: case 18://new case 22://new case 23://new case 24://new case 25://new case 26://new case 27://new case 28://new case 29://new case 30://new case 31://new case 32:// case 33://new case 35://new case 36://new case 37:// case 38:// case 39:// case 40://new case 41://new case 42://new case 44://new case 45://new case 46://new case 47:// case 48://new case 49://new case 50: case 51://new case 52:// case 53://new case 54://new case 55://new case 56://new case 57: case 59://new case 62: case 63: case 64: case 65:// case 66: case 67://new case 68://new case 69://new case 70://new case 71://new case 72://new case 73://new case 74://new case 75://new case 76: case 77://new case 78://new case 79://new case 80://new case 81://new case 82://new case 83://new case 84://new case 85://new case 86://new case 87://new case 88: case 90: case 91://new case 92://new case 93://new case 94://new case 95://new case 96://new case 98://new case 99://new case 100://new case 101://new case 102://new case 103://new case 104://new case 105://new case 106://new case 107://new case 108://new case 109://new case 110://new case 111://new case 112://new case 113://new case 114://new case 115://new case 116://new case 117: case 118://new case 119://new case 120://new case 121://new break; default: break; } } #endregion public override string ToString() { return Name; } } [TC(typeof(EXP))] public struct RelIndexHash { public MetaHash Name { get; set; } public uint Offset { get; set; } public uint Length { get; set; } public override string ToString() { return Name.ToString() + ", " + Offset.ToString() + ", " + Length.ToString(); } } [TC(typeof(EXP))] public struct RelIndexString { public string Name { get; set; } public uint Offset { get; set; } public uint Length { get; set; } public override string ToString() { return Name + ", " + Offset.ToString() + ", " + Length.ToString(); } } [TC(typeof(EXP))] public class RelData { public MetaHash NameHash { get; set; } public string Name { get; set; } public uint DataOffset { get; set; } public uint DataLength { get; set; } public byte[] Data { get; set; } public byte TypeID { get; set; } public RelData() { } public RelData(RelData d) { NameHash = d.NameHash; Name = d.Name; DataOffset = d.DataOffset; DataLength = d.DataLength; Data = d.Data; TypeID = d.TypeID; } public void ReadType(BinaryReader br) { TypeID = br.ReadByte(); } public string GetNameString() { return (string.IsNullOrEmpty(Name)) ? NameHash.ToString() : Name; } public string GetBaseString() { return DataOffset.ToString() + ", " + DataLength.ToString() + ": " + GetNameString(); } public override string ToString() { return GetBaseString() + ": " + TypeID.ToString(); } public static bool Bit(uint f, int b) { return ((f & (1u << b)) != 0); //just for handyness... maybe move this? } public static bool BadF(float f) { return ((f < -15000) || (f > 15000)); } } [TC(typeof(EXP))] public class RelSoundHeader { public FlagsUint Flags { get; set; } public FlagsUint UnkFlags { get; set; } public ushort Unk01 { get; set; } public ushort Unk02 { get; set; } public ushort Unk03 { get; set; } //0xD-0xF public ushort Unk04 { get; set; } //0xF-0x11 public ushort Unk05 { get; set; } //0x11-0x13 public ushort Unk06 { get; set; } //0x13-0x15 public ushort Unk07 { get; set; } //0x15-0x17 public ushort Unk08 { get; set; } //0x17-0x19 public ushort Unk09 { get; set; } //0x19-0x1B public MetaHash UnkHash1 { get; set; } //0x1B-0x1F public MetaHash UnkHash2 { get; set; } //0x1F-0x23 public ushort Unk10 { get; set; } //0x23-0x25 public ushort Unk11 { get; set; } //0x25-0x27 public ushort Unk12 { get; set; } //0x27-0x29 public MetaHash CategoryHash { get; set; } //0x29-0x2D public ushort Unk14 { get; set; } //0x2D-0x2F public ushort Unk15 { get; set; } //0x2F-0x31 public ushort Unk16 { get; set; } //0x31-0x33 public ushort Unk17 { get; set; } //0x33-0x35 public MetaHash UnkHash3 { get; set; } //0x35-0x39 public ushort Unk18 { get; set; } //0x39-0x3B public byte Unk19 { get; set; } //0x3B-0x3C public byte Unk20 { get; set; } //0x3C-0x3D public byte Unk21 { get; set; } //0x3D-0x3E public MetaHash UnkHash4 { get; set; } //0x3E-0x42 public MetaHash UnkHash5 { get; set; } //0x42-0x46 public ushort Unk22 { get; set; } //0x46-0x48 public ushort Unk23 { get; set; } //0x48-0x4A public ushort Unk24 { get; set; } //0x4A-0x4C public ushort Unk25 { get; set; } //0x4A-0x4C public ushort Unk26 { get; set; } //0x4A-0x4C public RelSoundHeader(BinaryReader br) { Flags = br.ReadUInt32(); //if (Flags.Value != 0xAAAAAAAA) if ((Flags.Value & 0xFF) != 0xAA) { if (Bit(0)) UnkFlags = br.ReadUInt32(); if (Bit(1)) Unk01 = br.ReadUInt16(); if (Bit(2)) Unk02 = br.ReadUInt16(); if (Bit(3)) Unk03 = br.ReadUInt16(); if (Bit(4)) Unk04 = br.ReadUInt16(); if (Bit(5)) Unk05 = br.ReadUInt16(); if (Bit(6)) Unk06 = br.ReadUInt16(); if (Bit(7)) Unk07 = br.ReadUInt16(); } if ((Flags.Value & 0xFF00) != 0xAA00) { if (Bit(8)) Unk08 = br.ReadUInt16(); if (Bit(9)) Unk09 = br.ReadUInt16(); if (Bit(10)) UnkHash1 = br.ReadUInt32(); if (Bit(11)) UnkHash2 = br.ReadUInt32(); if (Bit(12)) Unk10 = br.ReadUInt16(); if (Bit(13)) Unk11 = br.ReadUInt16(); if (Bit(14)) Unk12 = br.ReadUInt16(); if (Bit(15)) CategoryHash = br.ReadUInt32(); } if ((Flags.Value & 0xFF0000) != 0xAA0000) { if (Bit(16)) Unk14 = br.ReadUInt16(); if (Bit(17)) Unk15 = br.ReadUInt16(); if (Bit(18)) Unk16 = br.ReadUInt16(); if (Bit(19)) Unk17 = br.ReadUInt16(); if (Bit(20)) UnkHash3 = br.ReadUInt32(); if (Bit(21)) Unk18 = br.ReadUInt16(); if (Bit(22)) Unk19 = br.ReadByte(); if (Bit(23)) Unk20 = br.ReadByte(); } if ((Flags.Value & 0xFF000000) != 0xAA000000) { if (Bit(24)) Unk21 = br.ReadByte(); if (Bit(25)) UnkHash4 = br.ReadUInt32(); if (Bit(26)) UnkHash5 = br.ReadUInt32(); if (Bit(27)) Unk22 = br.ReadUInt16(); if (Bit(28)) Unk23 = br.ReadUInt16(); if (Bit(29)) Unk24 = br.ReadUInt16(); if (Bit(30)) Unk25 = br.ReadUInt16(); //maybe not if (Bit(31)) Unk26 = br.ReadUInt16(); //maybe not } } private bool Bit(int b) { return ((Flags.Value & (1u << b)) != 0); } public override string ToString() { return string.Format("{0}: {1}, {2}, {3}, {4}, {5}, {6}, {7}", Flags.Hex, UnkFlags.Hex, CategoryHash, UnkHash1, UnkHash2, UnkHash3, UnkHash4, UnkHash5); } } [TC(typeof(EXP))] public class RelSound : RelData { public RelSoundHeader Header { get; set; } public byte AudioTracksCount { get; set; } public RelData[] AudioTracks { get; set; } public MetaHash[] AudioTrackHashes { get; set; } public MetaHash[] AudioContainers { get; set; } //Relative path to parent wave container (i.e. "RESIDENT/animals") public RelSound(RelData d, BinaryReader br) : base(d) { Header = new RelSoundHeader(br); } public void ReadAudioTrackHashes(BinaryReader br) { AudioTracksCount = br.ReadByte(); AudioTrackHashes = new MetaHash[AudioTracksCount]; for (int i = 0; i < AudioTracksCount; i++) { AudioTrackHashes[i] = br.ReadUInt32(); } } } public enum Dat54SoundType : byte { LoopingSound = 1, EnvelopeSound = 2, TwinLoopSound = 3, SpeechSound = 4, OnStopSound = 5, WrapperSound = 6, SequentialSound = 7, StreamingSound = 8, RetriggeredOverlappedSound = 9, CrossfadeSound = 10, CollapsingStereoSound = 11, SimpleSound = 12, MultitrackSound = 13, RandomizedSound = 14, EnvironmentSound = 15, DynamicEntitySound = 16, SequentialOverlapSound = 17, ModularSynthSound = 18, GranularSound = 19, DirectionalSound = 20, KineticSound = 21, SwitchSound = 22, VariableCurveSound = 23, VariablePrintValueSound = 24, VariableBlockSound = 25, IfSound = 26, MathOperationSound = 27, ParameterTransformSound = 28, FluctuatorSound = 29, AutomationSound = 30, ExternalStreamSound = 31, SoundSet = 32, Unknown = 33, Unknown2 = 34, SoundList = 35 } [TC(typeof(EXP))] public class Dat54Sound : RelSound { public Dat54SoundType Type { get; set; } public Dat54Sound(RelData d, BinaryReader br) : base(d, br) { Type = (Dat54SoundType)TypeID; } public override string ToString() { return GetBaseString() + ": " + Type.ToString(); } } [TC(typeof(EXP))] public class Dat54LoopingSound : Dat54Sound { public short UnkShort0 { get; set; } //0x0-0x2 public short UnkShort1 { get; set; } //0x2-0x4 public short UnkShort2 { get; set; } //0x4-0x6 public MetaHash AudioHash { get; set; } //0x6-0xA public MetaHash ParameterHash { get; set; } //0xA-0xE public Dat54LoopingSound(RelData d, BinaryReader br) : base(d, br) { UnkShort0 = br.ReadInt16(); UnkShort1 = br.ReadInt16(); UnkShort2 = br.ReadInt16(); AudioHash = br.ReadUInt32(); AudioTrackHashes = new[] { AudioHash }; ParameterHash = br.ReadUInt32(); } } [TC(typeof(EXP))] public class Dat54EnvelopeSound : Dat54Sound { public ushort UnkShortA { get; set; } //0x0-0x2 public ushort UnkShortA1 { get; set; } //0x2-0x4 public ushort UnkShortB { get; set; } //0x4-0x6 public ushort UnkShortB1 { get; set; } //0x6-0x8 public byte UnkByteA { get; set; } //0x8-0x9 public byte UnkByteA1 { get; set; } //0x9-0xA public int UnkInt { get; set; } //0xA-0xE public ushort UnkShortC { get; set; } //0xE-0x10 public int UnkIntA { get; set; } //0x10-0x14 public int UnkIntA1 { get; set; } //0x14-0x18 public MetaHash CurvesUnkHash0 { get; set; } //0x18-0x1C public MetaHash CurvesUnkHash1 { get; set; } //0x1C-0x20 public MetaHash CurvesUnkHash2 { get; set; } //0x20-0x24 public MetaHash ParameterHash0 { get; set; } //0x24-0x28 public MetaHash ParameterHash1 { get; set; } //0x28-0x2C public MetaHash ParameterHash2 { get; set; } //0x2C-0x30 public MetaHash ParameterHash3 { get; set; } //0x30-0x34 public MetaHash ParameterHash4 { get; set; } //0x34-0x38 public MetaHash AudioHash { get; set; }// audio track 0x38-0x3C public int UnkIntC { get; set; } //0x3C-0x40 public MetaHash ParameterHash5 { get; set; } //0x40-0x44 public float UnkFloat0 { get; set; } //0x44-0x48 public float UnkFloat1 { get; set; } //0x48-0x4C public Dat54EnvelopeSound(RelData d, BinaryReader br) : base(d, br) { UnkShortA = br.ReadUInt16(); //0x0-0x2 UnkShortA1 = br.ReadUInt16(); //0x2-0x4 UnkShortB = br.ReadUInt16(); //0x4-0x6 UnkShortB1 = br.ReadUInt16(); //0x6-0x8 UnkByteA = br.ReadByte(); //0x8-0x9 UnkByteA1 = br.ReadByte(); //0x9-0xA UnkInt = br.ReadInt32(); //0xA-0xE UnkShortC = br.ReadUInt16(); //0xE-0x10 UnkIntA = br.ReadInt32(); //0x10-0x14 UnkIntA1 = br.ReadInt32(); //0x14-0x18 CurvesUnkHash0 = br.ReadUInt32(); //0x18-0x1C CurvesUnkHash1 = br.ReadUInt32(); //0x1C-0x20 CurvesUnkHash2 = br.ReadUInt32(); //0x20-0x24 ParameterHash0 = br.ReadUInt32(); //0x24-0x28 ParameterHash1 = br.ReadUInt32(); //0x28-0x2C ParameterHash2 = br.ReadUInt32(); //0x2C-0x30 ParameterHash3 = br.ReadUInt32(); //0x30-0x34 ParameterHash4 = br.ReadUInt32(); //0x34-0x38 AudioHash = br.ReadUInt32(); //0x38-0x3C UnkIntC = br.ReadInt32(); //0x3C-0x40 ParameterHash5 = br.ReadUInt32(); //0x40-0x44 UnkFloat0 = br.ReadSingle(); //0x44-0x48 UnkFloat1 = br.ReadSingle(); //0x48-0x4C AudioTrackHashes = new[] { AudioHash }; } } [TC(typeof(EXP))] public class Dat54TwinLoopSound : Dat54Sound { public ushort UnkShort0 { get; set; } //0x0-0x2 public ushort UnkShort1 { get; set; } //0x2-0x4 public ushort UnkShort2 { get; set; } //0x4-0x6 public ushort UnkShort3 { get; set; } //0x6-0x8 public MetaHash UnkHash { get; set; } //0x8-0xC public MetaHash ParameterHash0 { get; set; } //0xC-0x10 public MetaHash ParameterHash1 { get; set; } //0x10-0x14 public MetaHash ParameterHash2 { get; set; } //0x14-0x18 public MetaHash ParameterHash3 { get; set; } //0x18-0x1C public Dat54TwinLoopSound(RelData d, BinaryReader br) : base(d, br) { UnkShort0 = br.ReadUInt16(); UnkShort1 = br.ReadUInt16(); UnkShort2 = br.ReadUInt16(); UnkShort3 = br.ReadUInt16(); UnkHash = br.ReadUInt32(); ParameterHash0 = br.ReadUInt32(); ParameterHash1 = br.ReadUInt32(); ParameterHash2 = br.ReadUInt32(); ParameterHash3 = br.ReadUInt32(); ReadAudioTrackHashes(br); } } [TC(typeof(EXP))] public class Dat54SpeechSound : Dat54Sound { public int UnkInt0 { get; set; } //maybe file index? public int UnkInt1 { get; set; } //ox4-0x8 public MetaHash VoiceDataHash { get; set; } //0x8-0xC public string SpeechName { get; set; } //0xD-... public Dat54SpeechSound(RelData d, BinaryReader br) : base(d, br) { UnkInt0 = br.ReadInt32(); UnkInt1 = br.ReadInt32(); VoiceDataHash = br.ReadUInt32(); SpeechName = br.ReadString(); } } [TC(typeof(EXP))] public class Dat54OnStopSound : Dat54Sound { public MetaHash AudioHash0 { get; set; } public MetaHash AudioHash1 { get; set; } public MetaHash AudioHash2 { get; set; } public Dat54OnStopSound(RelData d, BinaryReader br) : base(d, br) { AudioHash0 = br.ReadUInt32(); AudioHash1 = br.ReadUInt32(); AudioHash2 = br.ReadUInt32(); AudioTrackHashes = new[] { AudioHash0, AudioHash1, AudioHash2 }; } } [TC(typeof(EXP))] public class Dat54WrapperSound : Dat54Sound { public MetaHash AudioHash0 { get; set; } //0x0-0x4 public int FrameStartTime { get; set; } //0x4-0x8 // maybe start delay? public MetaHash AudioHash1 { get; set; } //0x8-0xC public short FrameTimeInterval { get; set; } //0xC-0xE // [camxx:] My guess is that this is related to the time at which a child sound should start playin (or the length of the sound). public byte ItemCount { get; set; } public MetaHash[] Variables { get; set; } //0xF public byte[] UnkByteData { get; set; } // ... public Dat54WrapperSound(RelData d, BinaryReader br) : base(d, br) { AudioHash0 = br.ReadUInt32(); FrameStartTime = br.ReadInt32(); AudioHash1 = br.ReadUInt32(); FrameTimeInterval = br.ReadInt16(); ItemCount = br.ReadByte(); Variables = new MetaHash[ItemCount]; for (int i = 0; i < ItemCount; i++) { Variables[i] = br.ReadUInt32(); } UnkByteData = br.ReadBytes(ItemCount); AudioTrackHashes = new[] { AudioHash0, AudioHash1 }; } } [TC(typeof(EXP))] public class Dat54SequentialSound : Dat54Sound { public Dat54SequentialSound(RelData d, BinaryReader br) : base(d, br) { ReadAudioTrackHashes(br); } } [TC(typeof(EXP))] public class Dat54StreamingSound : Dat54Sound { int UnkInt { get; set; } //0x0-0x4 public Dat54StreamingSound(RelData d, BinaryReader br) : base(d, br) { UnkInt = br.ReadInt32(); ReadAudioTrackHashes(br); } } [TC(typeof(EXP))] public class Dat54RetriggeredOverlappedSound : Dat54Sound { public ushort UnkShort0 { get; set; } //0x0-0x2 public ushort UnkShort1 { get; set; } //0x2-0x4 public ushort UnkShort2 { get; set; } //0x4-0x6 public ushort UnkShort3 { get; set; } // 0x6-0x8 public MetaHash ParameterHash0 { get; set; } //0x8-0xC public MetaHash ParameterHash1 { get; set; } //0xC-0x10 public MetaHash AudioHash0 { get; set; } public MetaHash AudioHash1 { get; set; } public MetaHash AudioHash2 { get; set; } public Dat54RetriggeredOverlappedSound(RelData d, BinaryReader br) : base(d, br) { UnkShort0 = br.ReadUInt16(); UnkShort1 = br.ReadUInt16(); UnkShort2 = br.ReadUInt16(); UnkShort3 = br.ReadUInt16(); ParameterHash0 = br.ReadUInt32(); ParameterHash1 = br.ReadUInt32(); AudioHash0 = br.ReadUInt32(); AudioHash1 = br.ReadUInt32(); AudioHash2 = br.ReadUInt32(); AudioTrackHashes = new[] { AudioHash0, AudioHash1, AudioHash2 }; } } [TC(typeof(EXP))] public class Dat54CrossfadeSound : Dat54Sound { public MetaHash AudioHash0 { get; set; } public MetaHash AudioHash1 { get; set; } public byte UnkByte { get; set; } //0x8-0x9 public float UnkFloat0 { get; set; } //0x9-0xD public float UnkFloat1 { get; set; } //0xD-0x11 public int UnkInt2 { get; set; } //0xD-0x15 public MetaHash UnkCurvesHash { get; set; } //0x15-0x19 public MetaHash ParameterHash0 { get; set; } //0x19-0x1D public MetaHash ParameterHash1 { get; set; } //0x1D-0x21 public MetaHash ParameterHash2 { get; set; } //0x21-0x25 public MetaHash ParameterHash3 { get; set; } //0x25-0x29 public MetaHash ParameterHash4 { get; set; } //0x29-0x2D public Dat54CrossfadeSound(RelData d, BinaryReader br) : base(d, br) { AudioHash0 = br.ReadUInt32(); AudioHash1 = br.ReadUInt32(); AudioTrackHashes = new[] { AudioHash0, AudioHash1 }; UnkByte = br.ReadByte(); UnkFloat0 = br.ReadSingle(); UnkFloat1 = br.ReadSingle(); UnkInt2 = br.ReadInt32(); UnkCurvesHash = br.ReadUInt32(); ParameterHash0 = br.ReadUInt32(); ParameterHash1 = br.ReadUInt32(); ParameterHash2 = br.ReadUInt32(); ParameterHash3 = br.ReadUInt32(); ParameterHash4 = br.ReadUInt32(); } } [TC(typeof(EXP))] public class Dat54CollapsingStereoSound : Dat54Sound { public MetaHash AudioHash0 { get; set; } public MetaHash AudioHash1 { get; set; } public float UnkFloat0 { get; set; } public float UnkFloat1 { get; set; } public MetaHash ParameterHash0 { get; set; } //0x10-0x14 public MetaHash ParameterHash1 { get; set; } //0x14-0x18 public MetaHash ParameterHash2 { get; set; } //0x18-0x1C public MetaHash ParameterHash3 { get; set; } //0x1C-0x20 public MetaHash ParameterHash4 { get; set; } //0x20-0x24 public MetaHash ParameterHash5 { get; set; } //0x28-0x2C public int UnkInt { get; set; } //0x24-0x28 public byte UnkByte { get; set; } //0x2c-0x2D public Dat54CollapsingStereoSound(RelData d, BinaryReader br) : base(d, br) { AudioHash0 = br.ReadUInt32(); AudioHash1 = br.ReadUInt32(); AudioTrackHashes = new[] { AudioHash0, AudioHash1 }; UnkFloat0 = br.ReadSingle(); //0x8 UnkFloat1 = br.ReadSingle(); //0xC ParameterHash0 = br.ReadUInt32(); //0x10 ParameterHash1 = br.ReadUInt32(); //0x14 ParameterHash2 = br.ReadUInt32(); //0x18 ParameterHash3 = br.ReadUInt32(); //0x1C ParameterHash4 = br.ReadUInt32(); //0x20 UnkInt = br.ReadInt32(); //0x24-0x28 ParameterHash5 = br.ReadUInt32(); //0x28-0x2C UnkByte = br.ReadByte(); //0x2C-0x2D } } [TC(typeof(EXP))] public class Dat54SimpleSound : Dat54Sound { public MetaHash ContainerName { get; set; } //Relative path to parent wave container (i.e. "RESIDENT/animals") public MetaHash FileName { get; set; } //Name of the .wav file public byte WaveSlotNum { get; set; } //Internal index of wave (.awc) container public Dat54SimpleSound(RelData d, BinaryReader br) : base(d, br) { ContainerName = br.ReadUInt32(); AudioContainers = new[] { ContainerName }; FileName = br.ReadUInt32(); WaveSlotNum = br.ReadByte(); } } [TC(typeof(EXP))] public class Dat54MultitrackSound : Dat54Sound { public Dat54MultitrackSound(RelData d, BinaryReader br) : base(d, br) { ReadAudioTrackHashes(br); } } [TC(typeof(EXP))] public class Dat54RandomizedSound : Dat54Sound { public byte UnkByte { get; set; } //0x0-0x1 something count? public byte UnkBytesCount { get; set; } //0x1-0x2 public byte[] UnkBytes { get; set; } public byte ItemCount { get; set; } public float[] AudioTrackUnkFloats { get; set; } //probability..? public Dat54RandomizedSound(RelData d, BinaryReader br) : base(d, br) { UnkByte = br.ReadByte(); UnkBytesCount = br.ReadByte(); UnkBytes = br.ReadBytes(UnkBytesCount); ItemCount = br.ReadByte(); AudioTrackHashes = new MetaHash[ItemCount]; AudioTrackUnkFloats = new float[ItemCount]; for (int i = 0; i < ItemCount; i++) { AudioTrackHashes[i] = br.ReadUInt32(); AudioTrackUnkFloats[i] = br.ReadSingle(); } } } [TC(typeof(EXP))] public class Dat54EnvironmentSound : Dat54Sound { public byte UnkByte { get; set; } public Dat54EnvironmentSound(RelData d, BinaryReader br) : base(d, br) { UnkByte = br.ReadByte(); } } [TC(typeof(EXP))] public class Dat54DynamicEntitySound : Dat54Sound { public byte ItemCount { get; set; } public MetaHash[] UnkHashes { get; set; } public Dat54DynamicEntitySound(RelData d, BinaryReader br) : base(d, br) { ItemCount = br.ReadByte(); UnkHashes = new MetaHash[ItemCount]; for (int i = 0; i < ItemCount; i++) { UnkHashes[i] = br.ReadUInt32(); } } } [TC(typeof(EXP))] public class Dat54SequentialOverlapSound : Dat54Sound { public ushort UnkShort { get; set; } public MetaHash ParameterHash0 { get; set; } //0x2-0x6 public MetaHash ParameterHash1 { get; set; } //0x6-0xA public Dat54SequentialOverlapSound(RelData d, BinaryReader br) : base(d, br) { UnkShort = br.ReadUInt16(); ParameterHash0 = br.ReadUInt32(); ParameterHash1 = br.ReadUInt32(); ReadAudioTrackHashes(br); } } [TC(typeof(EXP))] public class Dat54ModularSynthSound : Dat54Sound { public MetaHash OptAmpUnkHash { get; set; } //0x0-0x4 public MetaHash UnkHash { get; set; } //0x4-0x8 public float UnkFloat { get; set; } //0x8-0xC public int UnkInt { get; set; } //0xC-0x10 public int TrackCount { get; set; } public int UnkItemCount { get; set; } public Dat54ModularSynthSoundData[] UnkItems { get; set; } //0x28-.. public Dat54ModularSynthSound(RelData d, BinaryReader br) : base(d, br) { OptAmpUnkHash = br.ReadUInt32(); //0x0-0x4 UnkHash = br.ReadUInt32(); //0x4-0x8 UnkFloat = br.ReadSingle(); //0x8-0xC UnkInt = br.ReadInt32(); //0xC-0x10 TrackCount = br.ReadInt32(); //0x10-0x14 AudioTrackHashes = new MetaHash[4]; for (int i = 0; i < 4; i++) { AudioTrackHashes[i] = br.ReadUInt32(); } UnkItemCount = br.ReadInt32(); UnkItems = new Dat54ModularSynthSoundData[UnkItemCount]; for (int i = 0; i < UnkItemCount; i++) { UnkItems[i] = new Dat54ModularSynthSoundData(br); } } } [TC(typeof(EXP))] public class Dat54ModularSynthSoundData { public MetaHash UnkHash { get; set; } public MetaHash ParameterHash { get; set; } public float Value { get; set; } public Dat54ModularSynthSoundData(BinaryReader br) { UnkHash = br.ReadUInt32(); ParameterHash = br.ReadUInt32(); Value = br.ReadSingle(); } public override string ToString() { return UnkHash.ToString() + ": " + ParameterHash.ToString() + ": " + FloatUtil.ToString(Value); } } [TC(typeof(EXP))] public class Dat54GranularSound : Dat54Sound { public int WaveSlotIndex { get; set; } //0x0-0x4 public Dat54GranularSoundFile Wave1 { get; set; } public Dat54GranularSoundFile Wave2 { get; set; } public Dat54GranularSoundFile Wave3 { get; set; } public Dat54GranularSoundFile Wave4 { get; set; } public Dat54GranularSoundFile Wave5 { get; set; } public Dat54GranularSoundFile Wave6 { get; set; } public Dat54GranularSoundData DataItem1 { get; set; } //0x34-0x3C public Dat54GranularSoundData DataItem2 { get; set; } //0x3C-0x44 public Dat54GranularSoundData DataItem3 { get; set; } //0x44-0x4C public Dat54GranularSoundData DataItem4 { get; set; } //0x4C-0x54 public Dat54GranularSoundData DataItem5 { get; set; } //0x54-0x5C public Dat54GranularSoundData DataItem6 { get; set; } //0x5C-0x64 public int UnkInt0 { get; set; } //0x64-0x68 public int UnkInt1 { get; set; } //0x68-0x6C public ushort UnkShort0 { get; set; } //0x6C-0x6E public ushort UnkShort1 { get; set; } //0x6E-0x70 public ushort UnkShort2 { get; set; } //0x70-0x72 public ushort UnkShort3 { get; set; } //0x72-0x74 public ushort UnkShort4 { get; set; } //0x74-0x76 public ushort UnkShort5 { get; set; } //0x76-0x78 public MetaHash TrackName { get; set; } //0x78-0x7C public byte UnkVecCount { get; set; } //0x7C-0x7D public Vector2[] UnkVecData { get; set; } //0x7D-... public Dat54GranularSound(RelData d, BinaryReader br) : base(d, br) { WaveSlotIndex = br.ReadInt32(); Wave1 = new Dat54GranularSoundFile(br); Wave2 = new Dat54GranularSoundFile(br); Wave3 = new Dat54GranularSoundFile(br); Wave4 = new Dat54GranularSoundFile(br); Wave5 = new Dat54GranularSoundFile(br); Wave6 = new Dat54GranularSoundFile(br); AudioContainers = new[] { Wave1.ContainerName, Wave2.ContainerName, Wave3.ContainerName, Wave4.ContainerName, Wave5.ContainerName, Wave6.ContainerName }; DataItem1 = new Dat54GranularSoundData(br); DataItem2 = new Dat54GranularSoundData(br); DataItem3 = new Dat54GranularSoundData(br); DataItem4 = new Dat54GranularSoundData(br); DataItem5 = new Dat54GranularSoundData(br); DataItem6 = new Dat54GranularSoundData(br); UnkInt0 = br.ReadInt32(); UnkInt1 = br.ReadInt32(); UnkShort0 = br.ReadUInt16(); UnkShort1 = br.ReadUInt16(); UnkShort2 = br.ReadUInt16(); UnkShort3 = br.ReadUInt16(); UnkShort4 = br.ReadUInt16(); UnkShort5 = br.ReadUInt16(); TrackName = br.ReadUInt32(); AudioTrackHashes = new[] { TrackName }; UnkVecCount = br.ReadByte(); UnkVecData = new Vector2[UnkVecCount]; for (int i = 0; i < UnkVecCount; i++) { UnkVecData[i] = new Vector2(br.ReadSingle(), br.ReadSingle()); } } } [TC(typeof(EXP))] public class Dat54GranularSoundFile { public MetaHash ContainerName { get; set; } //0x0-0x4 public MetaHash FileName { get; set; } //0x4-0x8 public Dat54GranularSoundFile(BinaryReader br) { ContainerName = br.ReadUInt32(); FileName = br.ReadUInt32(); } public override string ToString() { return ContainerName.ToString() + ": " + FileName.ToString(); } } [TC(typeof(EXP))] public class Dat54GranularSoundData { public byte UnkFlags0 { get; set; } //0x0-0x1 public byte UnkFlags1 { get; set; } //0x1-0x2 public byte UnkByte0 { get; set; } //0x2-0x3 public byte UnkByte1 { get; set; } //0x3-0x4 public float UnkFloat { get; set; } //0x4-0x8 public Dat54GranularSoundData(BinaryReader br) { UnkFlags0 = br.ReadByte(); UnkFlags1 = br.ReadByte(); UnkByte0 = br.ReadByte(); UnkByte1 = br.ReadByte(); UnkFloat = br.ReadSingle(); } public override string ToString() { return UnkFlags0.ToString() + ": " + UnkFlags1.ToString() + ": " + UnkByte0.ToString() + ": " + UnkByte1.ToString() + ": " + FloatUtil.ToString(UnkFloat); } } [TC(typeof(EXP))] public class Dat54DirectionalSound : Dat54Sound { public MetaHash AudioHash { get; set; } public float UnkFloat0 { get; set; } //0x4-0x8 public float UnkFloat1 { get; set; } //0x8-0xC public float UnkFloat2 { get; set; } //0xC-0x10 public float UnkFloat3 { get; set; } //0x10-0x14 public float UnkFloat4 { get; set; } //0x14-0x18 public Dat54DirectionalSound(RelData d, BinaryReader br) : base(d, br) { AudioHash = br.ReadUInt32(); AudioTrackHashes = new[] { AudioHash }; UnkFloat0 = br.ReadSingle(); UnkFloat1 = br.ReadSingle(); UnkFloat2 = br.ReadSingle(); UnkFloat3 = br.ReadSingle(); UnkFloat4 = br.ReadSingle(); } } [TC(typeof(EXP))] public class Dat54KineticSound : Dat54Sound { public MetaHash AudioHash { get; set; } public float UnkFloat0 { get; set; } //Maybe kinetic force vector? public float UnkFloat1 { get; set; } public float UnkFloat2 { get; set; } public Dat54KineticSound(RelData d, BinaryReader br) : base(d, br) { AudioHash = br.ReadUInt32(); AudioTrackHashes = new[] { AudioHash }; UnkFloat0 = br.ReadSingle(); UnkFloat1 = br.ReadSingle(); UnkFloat2 = br.ReadSingle(); } } [TC(typeof(EXP))] public class Dat54SwitchSound : Dat54Sound { public MetaHash ParameterHash { get; set; } //0x0-0x4 public Dat54SwitchSound(RelData d, BinaryReader br) : base(d, br) { ParameterHash = br.ReadUInt32(); ReadAudioTrackHashes(br); } } [TC(typeof(EXP))] public class Dat54VariableCurveSound : Dat54Sound { public MetaHash AudioHash { get; set; } public MetaHash ParameterHash0 { get; set; } //0x4-0x8 public MetaHash ParameterHash1 { get; set; } //0x8-0xC public MetaHash UnkCurvesHash { get; set; } //0xC-0x10 public Dat54VariableCurveSound(RelData d, BinaryReader br) : base(d, br) { AudioHash = br.ReadUInt32(); AudioTrackHashes = new[] { AudioHash }; ParameterHash0 = br.ReadUInt32(); ParameterHash1 = br.ReadUInt32(); UnkCurvesHash = br.ReadUInt32(); } } [TC(typeof(EXP))] public class Dat54VariablePrintValueSound : Dat54Sound { public MetaHash ParameterHash { get; set; } //0x0-0x4 public string VariableString { get; set; } public Dat54VariablePrintValueSound(RelData d, BinaryReader br) : base(d, br) { ParameterHash = br.ReadUInt32(); VariableString = br.ReadString(); } } [TC(typeof(EXP))] public class Dat54VariableBlockSound : Dat54Sound { public MetaHash AudioHash { get; set; } public byte VariableCount { get; set; } public Dat54VariableData[] Variables { get; set; } public Dat54VariableBlockSound(RelData d, BinaryReader br) : base(d, br) { AudioHash = br.ReadUInt32(); AudioTrackHashes = new[] { AudioHash }; VariableCount = br.ReadByte(); Variables = new Dat54VariableData[VariableCount]; for (int i = 0; i < VariableCount; i++) { Variables[i] = new Dat54VariableData(br); } } } [TC(typeof(EXP))] public class Dat54VariableData { public MetaHash Name { get; set; } public float Value { get; set; } public float UnkFloat { get; set; } public byte Flags { get; set; } public Dat54VariableData(BinaryReader br) { Name = br.ReadUInt32(); Value = br.ReadSingle(); UnkFloat = br.ReadSingle(); Flags = br.ReadByte(); } public override string ToString() { return Name + ": " + FloatUtil.ToString(Value) + ": " + FloatUtil.ToString(UnkFloat) + ": " + Flags.ToString(); } } [TC(typeof(EXP))] public class Dat54IfSound : Dat54Sound { public MetaHash AudioHash1 { get; set; } public MetaHash AudioHash2 { get; set; } public MetaHash ParameterHash1 { get; set; } public byte UnkByte { get; set; } public float UnkFloat { get; set; } public MetaHash ParameterHash2 { get; set; } public Dat54IfSound(RelData d, BinaryReader br) : base(d, br) { AudioHash1 = br.ReadUInt32(); AudioHash2 = br.ReadUInt32(); AudioTrackHashes = new[] { AudioHash1, AudioHash2 }; ParameterHash1 = br.ReadUInt32(); UnkByte = br.ReadByte(); UnkFloat = br.ReadSingle(); ParameterHash2 = br.ReadUInt32(); } } [TC(typeof(EXP))] public class Dat54MathOperationSound : Dat54Sound { public MetaHash AudioHash { get; set; } public byte UnkDataCount { get; set; } public Dat54MathOperationSoundData[] UnkData { get; set; } public Dat54MathOperationSound(RelData d, BinaryReader br) : base(d, br) { AudioHash = br.ReadUInt32(); AudioTrackHashes = new[] { AudioHash }; UnkDataCount = br.ReadByte(); UnkData = new Dat54MathOperationSoundData[UnkDataCount]; for (int i = 0; i < UnkDataCount; i++) { UnkData[i] = new Dat54MathOperationSoundData(br); } } } [TC(typeof(EXP))] public class Dat54MathOperationSoundData { public byte UnkByte { get; set; } //0x0-0x1 public int UnkInt0 { get; set; } //0x1-0x5 public int UnkInt1 { get; set; } //0x5-0x9 public int UnkInt2 { get; set; } //0x9-0xD public int UnkInt3 { get; set; } //0xD-0x11 public int UnkInt4 { get; set; } //0x11-0x15 public MetaHash ParameterHash0 { get; set; } //0x15-0x19 public MetaHash ParameterHash1 { get; set; } //0x19-0x1D public Dat54MathOperationSoundData(BinaryReader br) { UnkByte = br.ReadByte(); UnkInt0 = br.ReadInt32(); UnkInt1 = br.ReadInt32(); UnkInt2 = br.ReadInt32(); UnkInt3 = br.ReadInt32(); UnkInt4 = br.ReadInt32(); ParameterHash0 = br.ReadUInt32(); ParameterHash1 = br.ReadUInt32(); } public override string ToString() { return ParameterHash0.ToString() + ", " + ParameterHash1.ToString(); } } [TC(typeof(EXP))] public class Dat54ParameterTransformSound : Dat54Sound { public MetaHash AudioHash { get; set; } public int ItemCount { get; set; } public Dat54ParameterTransformSoundData[] Items { get; set; } public Dat54ParameterTransformSound(RelData d, BinaryReader br) : base(d, br) { AudioHash = br.ReadUInt32(); AudioTrackHashes = new[] { AudioHash }; ItemCount = br.ReadInt32(); //0x4-0x8 Items = new Dat54ParameterTransformSoundData[ItemCount]; for (int i = 0; i < ItemCount; i++) { Items[i] = new Dat54ParameterTransformSoundData(br); } } } [TC(typeof(EXP))] public class Dat54ParameterTransformSoundData { public MetaHash ParameterHash { get; set; } //0x0-0x4 public float UnkFloat0 { get; set; } //0x4-0x8 public float UnkFloat1 { get; set; } //0x8-0xC public int NestedDataCount { get; set; } public Dat54ParameterTransformSoundData2[] NestedData { get; set; } //0x10.. public Dat54ParameterTransformSoundData(BinaryReader br) { ParameterHash = br.ReadUInt32(); UnkFloat0 = br.ReadSingle(); UnkFloat1 = br.ReadSingle(); NestedDataCount = br.ReadInt32(); NestedData = new Dat54ParameterTransformSoundData2[NestedDataCount]; for (int i = 0; i < NestedDataCount; i++) { NestedData[i] = new Dat54ParameterTransformSoundData2(br); } } public override string ToString() { return ParameterHash.ToString() + ", " + NestedDataCount.ToString(); } } [TC(typeof(EXP))] public class Dat54ParameterTransformSoundData2 { public float UnkFloat0 { get; set; } //0x0-0x4 public int UnkInt { get; set; } //0x4 public MetaHash ParameterHash { get; set; } //0x8-0xC public float UnkFloat1 { get; set; } //0xC public float UnkFloat2 { get; set; } //0x10-0x14 public int NestedItemCount { get; set; } public Vector2[] NestedItems { get; set; } //0x18-... public Dat54ParameterTransformSoundData2(BinaryReader br) { UnkFloat0 = br.ReadSingle(); UnkInt = br.ReadInt32(); ParameterHash = br.ReadUInt32(); UnkFloat1 = br.ReadSingle(); UnkFloat2 = br.ReadSingle(); NestedItemCount = br.ReadInt32(); NestedItems = new Vector2[NestedItemCount]; for (int i = 0; i < NestedItemCount; i++) { NestedItems[i] = new Vector2(br.ReadSingle(), br.ReadSingle()); } } public override string ToString() { return ParameterHash.ToString() + ", " + NestedItemCount.ToString(); } } [TC(typeof(EXP))] public class Dat54FluctuatorSound : Dat54Sound { public MetaHash AudioHash { get; set; } public int ItemCount { get; set; } public Dat54FluctuatorSoundData[] Items { get; set; } public Dat54FluctuatorSound(RelData d, BinaryReader br) : base(d, br) { AudioHash = br.ReadUInt32(); AudioTrackHashes = new[] { AudioHash }; ItemCount = br.ReadInt32(); //0x4-0x8 Items = new Dat54FluctuatorSoundData[ItemCount]; for (int i = 0; i < ItemCount; i++) { Items[i] = new Dat54FluctuatorSoundData(br); } } } [TC(typeof(EXP))] public class Dat54FluctuatorSoundData { public byte UnkByte0 { get; set; } //0x0-0x1 public byte UnkByte1 { get; set; } //0x1-0x2 public MetaHash ParameterHash { get; set; } //0x2-0x6 public float UnkFloat00 { get; set; } //0x6-0xA public float UnkFloat01 { get; set; } //0xA-0xE public float UnkFloat02 { get; set; } //0xE-0x12 public float UnkFloat03 { get; set; } //0x12-0x16 public float UnkFloat04 { get; set; } //0x16-0x1A public float UnkFloat05 { get; set; } //0x1A-0x1E public float UnkFloat06 { get; set; } //0x1E-0x22 public float UnkFloat07 { get; set; } //0x22-0x26 public float UnkFloat08 { get; set; } //0x26-0x2A public float UnkFloat09 { get; set; } //0x2A-0x2E public float UnkFloat10 { get; set; } //0x2E-0x32 public Dat54FluctuatorSoundData(BinaryReader br) { UnkByte0 = br.ReadByte(); UnkByte1 = br.ReadByte(); ParameterHash = br.ReadUInt32(); UnkFloat00 = br.ReadSingle(); UnkFloat01 = br.ReadSingle(); UnkFloat02 = br.ReadSingle(); UnkFloat03 = br.ReadSingle(); UnkFloat04 = br.ReadSingle(); UnkFloat05 = br.ReadSingle(); UnkFloat06 = br.ReadSingle(); UnkFloat07 = br.ReadSingle(); UnkFloat08 = br.ReadSingle(); UnkFloat09 = br.ReadSingle(); UnkFloat10 = br.ReadSingle(); } public override string ToString() { return ParameterHash.ToString(); } } [TC(typeof(EXP))] public class Dat54AutomationSound : Dat54Sound { public MetaHash AudioHash0 { get; set; } public float UnkFloat0 { get; set; } //0x4-0x8 public float UnkFloat1 { get; set; } //0x8-0xC public MetaHash ParameterHash { get; set; } //0xC-0x10 public MetaHash AudioHash1 { get; set; } public int WaveSlotId { get; set; } //0x14-0x18 public MetaHash UnkHash1 { get; set; } //0x18-0x1C public int UnkDataCount { get; set; } // array data count 0x1C-0x20 public Dat54AutomationSoundData[] UnkData { get; set; } //0x20- public Dat54AutomationSound(RelData d, BinaryReader br) : base(d, br) { AudioHash0 = br.ReadUInt32(); UnkFloat0 = br.ReadSingle(); UnkFloat1 = br.ReadSingle(); ParameterHash = br.ReadUInt32(); AudioHash1 = br.ReadUInt32(); AudioTrackHashes = new[] { AudioHash0, AudioHash1 }; WaveSlotId = br.ReadInt32(); UnkHash1 = br.ReadUInt32(); UnkDataCount = br.ReadInt32(); UnkData = new Dat54AutomationSoundData[UnkDataCount]; for (int i = 0; i < UnkDataCount; i++) { UnkData[i] = new Dat54AutomationSoundData(br); } } } [TC(typeof(EXP))] public class Dat54AutomationSoundData { public int UnkInt { get; set; } //0x0-0x1 public MetaHash UnkHash { get; set; } //0x2-0x6 public Dat54AutomationSoundData(BinaryReader br) { UnkInt = br.ReadInt32(); UnkHash = br.ReadUInt32(); } public override string ToString() { return UnkInt.ToString() + ", " + UnkHash.ToString(); } } [TC(typeof(EXP))] public class Dat54ExternalStreamSound : Dat54Sound { public Dat54ExternalStreamSound(RelData d, BinaryReader br) : base(d, br) { ReadAudioTrackHashes(br); //FlagsUint u1 = br.ReadUInt32(); //FlagsUint u2 = br.ReadUInt32(); //FlagsUint u3 = br.ReadUInt32(); //FlagsUint u4 = br.ReadUInt32(); //TODO: could be more to read! if (br.BaseStream.Position != br.BaseStream.Length) { } //hits here! } } [TC(typeof(EXP))] public class Dat54SoundSet : Dat54Sound { public int ItemCount { get; set; } public Dat54SoundSetItem[] Items { get; set; } public Dat54SoundSet(RelData d, BinaryReader br) : base(d, br) { ItemCount = br.ReadInt32(); Items = new Dat54SoundSetItem[ItemCount]; AudioTrackHashes = new MetaHash[ItemCount]; for (int i = 0; i < ItemCount; i++) { Items[i] = new Dat54SoundSetItem(br); AudioTrackHashes[i] = Items[i].SoundName; } } } [TC(typeof(EXP))] public class Dat54SoundSetItem { public MetaHash ScriptName { get; set; } public MetaHash SoundName { get; set; } public Dat54SoundSetItem(BinaryReader br) { ScriptName = br.ReadUInt32(); SoundName = br.ReadUInt32(); } public override string ToString() { return ScriptName.ToString() + ": " + SoundName.ToString(); } } [TC(typeof(EXP))] public class Dat54UnknownSound : Dat54Sound { public byte UnkDataCount { get; set; } public Dat54UnknownSoundData[] UnkData { get; set; } public Dat54UnknownSound(RelData d, BinaryReader br) : base(d, br) { UnkDataCount = br.ReadByte(); UnkData = new Dat54UnknownSoundData[UnkDataCount]; AudioTrackHashes = new MetaHash[UnkDataCount]; for (int i = 0; i < UnkDataCount; i++) { UnkData[i] = new Dat54UnknownSoundData(br); AudioTrackHashes[i] = br.ReadUInt32(); } } } [TC(typeof(EXP))] public class Dat54UnknownSoundData { public byte UnkByte0 { get; set; } public byte UnkByte1 { get; set; } public byte UnkByte2 { get; set; } public Dat54UnknownSoundData(BinaryReader br) { UnkByte0 = br.ReadByte(); UnkByte1 = br.ReadByte(); UnkByte2 = br.ReadByte(); } public override string ToString() { return UnkByte0.ToString() + ": " + UnkByte1.ToString() + ": " + UnkByte2.ToString(); } } [TC(typeof(EXP))] public class Dat54UnknownSound2 : Dat54Sound { public uint UnkCount { get; set; } public MetaHash[] UnkItems { get; set; } public Dat54UnknownSound2(RelData d, BinaryReader br) : base(d, br) { UnkCount = br.ReadUInt32(); UnkItems = new MetaHash[UnkCount]; for (int i = 0; i < UnkCount; i++) { UnkItems[i] = br.ReadUInt32(); } } } [TC(typeof(EXP))] public class Dat54SoundList : Dat54Sound { public ushort UnkShort { get; set; } public uint Count { get; set; } public MetaHash[] Items { get; set; } public Dat54SoundList(RelData d, BinaryReader br) : base(d, br) { UnkShort = br.ReadUInt16(); Count = br.ReadUInt32(); Items = new MetaHash[Count]; for (int i = 0; i < Count; i++) { Items[i] = br.ReadUInt32(); } if (br.BaseStream.Position != br.BaseStream.Length) { } } } public enum Dat151RelType : byte //not sure how correct these are? { Collision = 1, //maybe for vehicle Vehicle = 3, VehicleEngine = 4, VehicleEntity = 5, //not sure about this RadioStream = 6,//possibly, generic audio stream Helicopter = 8, //maybe SpeechParams = 14, Weapon = 17, RadioStationsDLC = 24, // RadioDLC = 25, DLCMusic = 26, PedPVG = 30, //maybe Ped Voice Group? AmbientEmitterList = 32, AmbientZone = 37, AmbientEmitter = 38, AmbientZoneList = 39, WeaponAudioItem = 50, Aeroplane = 57, Mood = 62, StartTrackAction = 63, StopTrackAction = 64, SetMoodAction = 65, PlayerAction = 66, StartOneShotAction = 67, StopOneShotAction = 68, AnimalParams = 73, VehicleScannerParams = 76, //maybe not just vehicle Explosion = 87, VehicleEngineGranular = 88, //maybe not just vehicle ShoreLinePool = 90, ShoreLineLake = 91, ShoreLineRiver = 92, ShoreLineOcean = 93, ShoreLineList = 94, RadioDjSpeechAction = 98, FadeOutRadioAction = 102, FadeInRadioAction = 103, ForceRadioTrackAction = 104 } [TC(typeof(EXP))] public class Dat151RelData : RelData { public Dat151RelType Type { get; set; } public static int TotCount = 0; //###############DEBUGG public static List FoundCoords = new List(); //###############DEBUGG public void RecVec(Vector3 v) { float tol = 20.0f; if ((Math.Abs(v.X)>tol) || (Math.Abs(v.Y)>tol) || (Math.Abs(v.Z)>tol)) { FoundCoords.Add(FloatUtil.GetVector3String(v) + ", " + GetNameString()); } } public Dat151RelData() { } public Dat151RelData(RelData d, BinaryReader br) : base(d) { Type = (Dat151RelType)TypeID; } public override string ToString() { return GetBaseString() + ": " + Type.ToString(); } } [TC(typeof(EXP))] public class Dat151Sound : RelSound { public Dat151RelType Type { get; set; } public Dat151Sound(RelData d, BinaryReader br) : base(d, br) { Type = (Dat151RelType)TypeID; } public override string ToString() { return GetBaseString() + ": " + Type.ToString(); } } public enum Dat151ZoneShape : uint { Box = 0, Sphere = 1, Line = 2, } [TC(typeof(EXP))] public class Dat151AmbientZone : Dat151RelData { public uint UnkOffset0 { get; set; } public FlagsUint Flags00 { get; set; } public Dat151ZoneShape Shape { get; set; } public FlagsUint Flags02 { get; set; } public Vector3 OuterPos { get; set; } public float Unused01 { get; set; } public Vector3 OuterSize { get; set; } public float Unused02 { get; set; } public Vector4 OuterVec1 { get; set; } public Vector4 OuterVec2 { get; set; } public uint OuterAngle { get; set; } public Vector3 OuterVec3 { get; set; } public Vector3 InnerPos { get; set; } public float Unused06 { get; set; } public Vector3 InnerSize { get; set; } public float Unused07 { get; set; } public Vector4 InnerVec1 { get; set; } public Vector4 InnerVec2 { get; set; } public uint InnerAngle { get; set; } public Vector3 InnerVec3 { get; set; } public Vector4 Vec11 { get; set; } public Vector4 Vec12 { get; set; } public Vector4 Vec13 { get; set; } public FlagsUint Flags05 { get; set; } public byte Unk14 { get; set; } public byte Unk15 { get; set; } public ushort HashesCount { get; set; } public byte Unk16 { get; set; } public MetaHash[] Hashes { get; set; } public uint ExtParamsCount { get; set; } public ExtParam[] ExtParams { get; set; } public struct ExtParam { public MetaHash Hash { get; set; } public float Value { get; set; } public ExtParam(BinaryReader br) { Hash = br.ReadUInt32(); Value = br.ReadSingle(); } public override string ToString() { return Hash.ToString() + ": " + FloatUtil.ToString(Value); } } public Dat151AmbientZone(RelData d, BinaryReader br) : base(d, br) { br.BaseStream.Position = 0; //1 byte was read already (TypeID) UnkOffset0 = ((br.ReadUInt32() >> 8) & 0xFFFFFF); Flags00 = br.ReadUInt32(); Shape = (Dat151ZoneShape)br.ReadUInt32(); Flags02 = br.ReadUInt32(); OuterPos = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); Unused01 = br.ReadSingle(); OuterSize = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); Unused02 = br.ReadSingle(); OuterVec1 = new Vector4(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); OuterVec2 = new Vector4(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); OuterAngle = br.ReadUInt32();//### OuterVec3 = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); InnerPos = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); Unused06 = br.ReadSingle(); InnerSize = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); Unused07 = br.ReadSingle(); InnerVec1 = new Vector4(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); InnerVec2 = new Vector4(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); InnerAngle = br.ReadUInt32();//### InnerVec3 = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); Vec11 = new Vector4(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); Vec12 = new Vector4(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); Vec13 = new Vector4(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); Flags05 = br.ReadUInt32(); Unk14 = br.ReadByte(); Unk15 = br.ReadByte(); HashesCount = br.ReadByte(); Unk16 = br.ReadByte(); Hashes = new MetaHash[HashesCount]; for (int i = 0; i < HashesCount; i++) { Hashes[i] = br.ReadUInt32(); } ExtParamsCount = br.ReadUInt32(); ExtParams = new ExtParam[ExtParamsCount]; for (int i = 0; i < ExtParamsCount; i++) { ExtParams[i] = new ExtParam(br); } if (ExtParamsCount != 0) { } var data = this.Data; long bytesleft = br.BaseStream.Length - br.BaseStream.Position; if (bytesleft != 0) { //byte[] remainder = br.ReadBytes((int)bytesleft); //for (int i = 0; i < remainder.Length; i++) //{ // if (remainder[i] != 0) // { } //no hits here! probably got everything, i'm assuming the block is padded to 0x10 or something. //} } //RecVec(Pos01);//debug coords output //RecVec(Pos06); if (Unused01 != 0) { }//no hit if (Unused02 != 0) { }//no hit if (Unused06 != 0) { }//no hit if (Unused07 != 0) { }//no hit if (Shape != 0) { }//eg 1, 2 if (Flags02.Value != 0) { }//no hit if (OuterAngle > 360) { }//no hit if (InnerAngle > 360) { }//no hit if (Flags05.Value != 0) { }//eg 0xAE64583B, 0x61083310, 0xCAE96294, 0x1C376176 } } [TC(typeof(EXP))] public class Dat151AmbientEmitter : Dat151RelData { public uint UnkOffset0 { get; set; } public FlagsUint Unk00 { get; set; } public FlagsUint Unk01 { get; set; } public FlagsUint Unk02 { get; set; } public Vector3 Position { get; set; } public FlagsUint Unk03 { get; set; } //0 public MetaHash Unk04 { get; set; } public MetaHash Unk05 { get; set; } public FlagsUint Unk06 { get; set; } //0 public FlagsUint Unk07 { get; set; } //0xFFFFFFFF public FlagsUint Unk08 { get; set; } //0 public float Unk09 { get; set; } //1, 5, 100, ... public float InnerRad { get; set; } //0, 4, ... 100 ... min value? public float OuterRad { get; set; } //15, 16, 12, 10, 20, 300 ... max value? public FlagsByte Unk12 { get; set; } public FlagsByte Unk13 { get; set; } //0,1,2,3,4,5 public FlagsByte Unk14 { get; set; } public FlagsByte Unk15 { get; set; } //0,1,2,3,4,5 public FlagsUshort Unk16 { get; set; } //0..600 public FlagsUshort Unk17 { get; set; } //0..150 public FlagsByte Unk18 { get; set; } //0,1,2 public FlagsByte Unk19 { get; set; } //0,1,2 public FlagsByte Unk20 { get; set; } //1,2,3,4,8,255 public FlagsByte Unk21 { get; set; } //1,2,3,4,5,6,8,10,255 public FlagsByte Unk22 { get; set; } //0, 50, 80, 100 public FlagsByte Unk23 { get; set; } //1,2,3,5 public ushort ExtParamCount { get; set; } //0,1,2,4 public ExtParam[] ExtParams { get; set; } public struct ExtParam { public MetaHash Hash; public float Value; public uint Flags; public ExtParam(BinaryReader br) { Hash = br.ReadUInt32(); Value = br.ReadSingle(); Flags = br.ReadUInt32(); } public override string ToString() { return Hash.ToString() + ": " + FloatUtil.ToString(Value) + ": " + Flags.ToString(); } } public Dat151AmbientEmitter(RelData d, BinaryReader br) : base(d, br) { br.BaseStream.Position = 0; //1 byte was read already (TypeID) UnkOffset0 = ((br.ReadUInt32() >> 8) & 0xFFFFFF); Unk00 = br.ReadUInt32(); Unk01 = br.ReadUInt32(); Unk02 = br.ReadUInt32(); Position = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); Unk03 = br.ReadUInt32(); //0 Unk04 = br.ReadUInt32(); Unk05 = br.ReadUInt32(); Unk06 = br.ReadUInt32(); //0 Unk07 = br.ReadUInt32(); //0xFFFFFFFF Unk08 = br.ReadUInt32(); //0 Unk09 = br.ReadSingle(); //1, 5, 100, ... InnerRad = br.ReadSingle(); //0, 4, ... 100 ... min value? OuterRad = br.ReadSingle(); //15, 16, 12, 10, 20, 300 ... max value? Unk12 = br.ReadByte(); Unk13 = br.ReadByte(); //0,1,2,3,4,5 Unk14 = br.ReadByte(); Unk15 = br.ReadByte(); //0,1,2,3,4,5 Unk16 = br.ReadUInt16(); //0..600 Unk17 = br.ReadUInt16(); //0..150 Unk18 = br.ReadByte(); //0,1,2 Unk19 = br.ReadByte(); //0,1,2 Unk20 = br.ReadByte(); //1,2,3,4,8,255 Unk21 = br.ReadByte(); //1,2,3,4,5,6,8,10,255 Unk22 = br.ReadByte(); //0, 50, 80, 100 Unk23 = br.ReadByte(); //1,2,3,5 ExtParamCount = br.ReadUInt16(); //0,1,2,4 if (ExtParamCount > 0) { ExtParams = new ExtParam[ExtParamCount]; for (int i = 0; i < ExtParamCount; i++) { ExtParams[i] = new ExtParam(br); } //array seems to be padded to multiples of 16 bytes. (read the rest here) int brem = (16 - ((ExtParamCount * 12) % 16)) % 16; if (brem > 0) { byte[] brema = br.ReadBytes(brem); //for (int i = 0; i < brem; i++) //{ // if (brema[i] != 0) // { } //check all remaining bytes are 0 - never hit here //} } } switch (Unk12.Value)//no pattern? { default: break; } switch (Unk13.Value) { case 0: case 1: case 2: case 3: case 4: case 5: break; default: break; } switch (Unk14.Value)//no pattern? { default: break; } switch (Unk15.Value) { case 0: case 1: case 2: case 3: case 4: case 5: break; default: break; } switch (Unk16.Value) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 18: case 20: case 22: case 24: case 25: case 26: case 30: case 32: case 35: case 40: case 45: case 48: case 50: case 51: case 54: case 55: case 57: case 60: case 64: case 65: case 70: case 75: case 80: case 90: case 95: case 97: case 100: case 120: case 125: case 130: case 135: case 140: case 145: case 150: case 160: case 170: case 178: case 180: case 190: case 200: case 220: case 225: case 240: case 245: case 250: case 300: case 350: case 500: case 600: break; default: break; } switch (Unk17.Value) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 12: case 15: case 17: case 20: case 21: case 22: case 25: case 27: case 30: case 32: case 35: case 40: case 50: case 60: case 100: case 150: break; default: break; } switch (Unk18.Value) { case 0: case 1: case 2: break; default: break; } switch (Unk19.Value) { case 0: case 1: case 2: break; default: break; } switch (Unk20.Value) { case 1: case 2: case 3: case 4: case 8: case 255: break; default: break; } switch (Unk21.Value) { case 1: case 2: case 3: case 4: case 5: case 6: case 8: case 10: case 255: break; default: break; } switch (Unk22.Value) { case 0: case 50: case 80: case 100: break; default: break; } switch (Unk23.Value) { case 1: case 2: case 3: case 5: break; default: break; } switch (ExtParamCount) { case 0: case 1: case 2: case 4: break; default: break; } //if ((Position.X != 0) || (Position.Y != 0) || (Position.Z != 0)) //{ // FoundCoords.Add(FloatUtil.GetVector3String(Position) + ", " + GetNameString()); //} long bytesleft = br.BaseStream.Length - br.BaseStream.Position; if (bytesleft != 0) { } } } }