diff --git a/TRLevelControl/Build/TRSFXBuilder.cs b/TRLevelControl/Build/TRSFXBuilder.cs new file mode 100644 index 00000000..625b5ec9 --- /dev/null +++ b/TRLevelControl/Build/TRSFXBuilder.cs @@ -0,0 +1,35 @@ +using TRLevelControl.Model; + +namespace TRLevelControl.Build; + +public static class TRSFXBuilder +{ + public static List ReadSoundMap(TRLevelReader reader) + { + List map = new(); + while (reader.PeekUInt() >= ushort.MaxValue) + { + map.Add(reader.ReadInt16()); + } + + return map; + } + + public static TRDictionary Build(List soundMap, List soundDetails) + where S : Enum + where T : class + { + TRDictionary result = new(); + for (int i = 0; i < soundMap.Count; i++) + { + if (soundMap[i] == -1 || soundMap[i] >= soundDetails.Count) + { + continue; + } + + result[(S)(object)(uint)i] = soundDetails[soundMap[i]]; + } + + return result; + } +} diff --git a/TRLevelControl/Control/TR1/TR1LevelControl.cs b/TRLevelControl/Control/TR1/TR1LevelControl.cs index 26ce0c1c..c3963df1 100644 --- a/TRLevelControl/Control/TR1/TR1LevelControl.cs +++ b/TRLevelControl/Control/TR1/TR1LevelControl.cs @@ -302,8 +302,7 @@ private void WriteDemoData(TRLevelWriter writer) private void ReadSoundEffects(TRLevelReader reader) { - _level.SoundEffects = new(); - short[] soundMap = reader.ReadInt16s(Enum.GetValues().Length); + List soundMap = TRSFXBuilder.ReadSoundMap(reader); uint numSoundDetails = reader.ReadUInt32(); List sfx = new(); @@ -349,15 +348,7 @@ private void ReadSoundEffects(TRLevelReader reader) } } - for (int i = 0; i < soundMap.Length; i++) - { - if (soundMap[i] == -1) - { - continue; - } - - _level.SoundEffects[(TR1SFX)i] = sfx[soundMap[i]]; - } + _level.SoundEffects = TRSFXBuilder.Build(soundMap, sfx); } private void WriteSoundEffects(TRLevelWriter writer) diff --git a/TRLevelControl/Control/TR2/TR2LevelControl.cs b/TRLevelControl/Control/TR2/TR2LevelControl.cs index b2e186c7..d2c0a0ca 100644 --- a/TRLevelControl/Control/TR2/TR2LevelControl.cs +++ b/TRLevelControl/Control/TR2/TR2LevelControl.cs @@ -308,8 +308,7 @@ private void WriteDemoData(TRLevelWriter writer) private void ReadSoundEffects(TRLevelReader reader) { - _level.SoundEffects = new(); - short[] soundMap = reader.ReadInt16s(Enum.GetValues().Length); + List soundMap = TRSFXBuilder.ReadSoundMap(reader); uint numSoundDetails = reader.ReadUInt32(); List sfx = new(); @@ -335,15 +334,7 @@ private void ReadSoundEffects(TRLevelReader reader) sfx[soundID].SampleID = sampleIndices[samplePointer]; } - for (int i = 0; i < soundMap.Length; i++) - { - if (soundMap[i] < 0 || soundMap[i] >= sfx.Count) - { - continue; - } - - _level.SoundEffects[(TR2SFX)i] = sfx[soundMap[i]]; - } + _level.SoundEffects = TRSFXBuilder.Build(soundMap, sfx); } private void WriteSoundEffects(TRLevelWriter writer) diff --git a/TRLevelControl/Control/TR3/TR3LevelControl.cs b/TRLevelControl/Control/TR3/TR3LevelControl.cs index 7caa69c2..55a73326 100644 --- a/TRLevelControl/Control/TR3/TR3LevelControl.cs +++ b/TRLevelControl/Control/TR3/TR3LevelControl.cs @@ -308,8 +308,7 @@ private void WriteDemoData(TRLevelWriter writer) private void ReadSoundEffects(TRLevelReader reader) { - _level.SoundEffects = new(); - short[] soundMap = reader.ReadInt16s(Enum.GetValues().Length); + List soundMap = TRSFXBuilder.ReadSoundMap(reader); uint numSoundDetails = reader.ReadUInt32(); List sfx = new(); @@ -337,15 +336,7 @@ private void ReadSoundEffects(TRLevelReader reader) sfx[soundID].SampleID = sampleIndices[samplePointer]; } - for (int i = 0; i < soundMap.Length; i++) - { - if (soundMap[i] < 0 || soundMap[i] >= sfx.Count) - { - continue; - } - - _level.SoundEffects[(TR3SFX)i] = sfx[soundMap[i]]; - } + _level.SoundEffects = TRSFXBuilder.Build(soundMap, sfx); } private void WriteSoundEffects(TRLevelWriter writer) diff --git a/TRLevelControl/Control/TR4/TR4LevelControl.cs b/TRLevelControl/Control/TR4/TR4LevelControl.cs index d726ec7a..9ddc8282 100644 --- a/TRLevelControl/Control/TR4/TR4LevelControl.cs +++ b/TRLevelControl/Control/TR4/TR4LevelControl.cs @@ -328,8 +328,7 @@ private static void WriteDemoData(TRLevelWriter writer) private void ReadSoundEffects(TRLevelReader reader) { - _level.SoundEffects = new(); - short[] soundMap = reader.ReadInt16s(Enum.GetValues().Length); + List soundMap = TRSFXBuilder.ReadSoundMap(reader); uint numSoundDetails = reader.ReadUInt32(); List sfx = new(); @@ -356,15 +355,7 @@ private void ReadSoundEffects(TRLevelReader reader) uint[] sampleIndices = reader.ReadUInt32s(numSampleIndices); _observer?.OnSampleIndicesRead(sampleIndices); - for (int i = 0; i < soundMap.Length; i++) - { - if (soundMap[i] < 0 || soundMap[i] >= sfx.Count) - { - continue; - } - - _level.SoundEffects[(TR4SFX)i] = sfx[soundMap[i]]; - } + _level.SoundEffects = TRSFXBuilder.Build(soundMap, sfx); } private void WriteSoundEffects(TRLevelWriter writer) diff --git a/TRLevelControl/Control/TR5/TR5LevelControl.cs b/TRLevelControl/Control/TR5/TR5LevelControl.cs index 9963ae8c..f3064201 100644 --- a/TRLevelControl/Control/TR5/TR5LevelControl.cs +++ b/TRLevelControl/Control/TR5/TR5LevelControl.cs @@ -380,8 +380,7 @@ private static void WriteDemoData(TRLevelWriter writer) private void ReadSoundEffects(TRLevelReader reader) { - _level.SoundEffects = new(); - short[] soundMap = reader.ReadInt16s(Enum.GetValues().Length); + List soundMap = TRSFXBuilder.ReadSoundMap(reader); uint numSoundDetails = reader.ReadUInt32(); List sfx = new(); @@ -408,13 +407,7 @@ private void ReadSoundEffects(TRLevelReader reader) uint[] sampleIndices = reader.ReadUInt32s(numSampleIndices); _observer?.OnSampleIndicesRead(sampleIndices); - for (int i = 0; i < soundMap.Length; i++) - { - if (soundMap[i] == -1) - continue; - - _level.SoundEffects[(TR5SFX)i] = sfx[soundMap[i]]; - } + _level.SoundEffects = TRSFXBuilder.Build(soundMap, sfx); reader.ReadBytes(6); // OxCD padding diff --git a/TRLevelControl/IO/TRLevelReader.cs b/TRLevelControl/IO/TRLevelReader.cs index df28696a..854ab03e 100644 --- a/TRLevelControl/IO/TRLevelReader.cs +++ b/TRLevelControl/IO/TRLevelReader.cs @@ -43,6 +43,13 @@ public TRLevelReader Inflate(TRChunkType chunkType) return new(inflatedStream); } + public uint PeekUInt() + { + uint value = ReadUInt32(); + BaseStream.Position -= sizeof(uint); + return value; + } + public void ReadUntil(long position) { long distance = position - BaseStream.Position;