From 43ce53cab4d356c652b011388b62200e961dcbda Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Wed, 17 Sep 2025 15:26:49 +0100 Subject: [PATCH 1/3] Handle TRX injection data Adds TRX injection awareness to levels as standard. Initial implementation allows injecting sound effect replacements directly. --- TRLevelControl/IO/TRXInjector.cs | 199 +++++++++++++++++++ TRLevelControl/Model/TRLevelBase.cs | 5 +- TRLevelControl/Model/TRX/TRSFXData.cs | 44 ++++ TRLevelControl/Model/TRX/TRXInjectionData.cs | 6 + TRLevelControl/TRLevelControlBase.cs | 3 + TRLevelControlTests/TRX/IOTests.cs | 44 ++++ 6 files changed, 300 insertions(+), 1 deletion(-) create mode 100644 TRLevelControl/IO/TRXInjector.cs create mode 100644 TRLevelControl/Model/TRX/TRSFXData.cs create mode 100644 TRLevelControl/Model/TRX/TRXInjectionData.cs create mode 100644 TRLevelControlTests/TRX/IOTests.cs diff --git a/TRLevelControl/IO/TRXInjector.cs b/TRLevelControl/IO/TRXInjector.cs new file mode 100644 index 000000000..ecc13f7b3 --- /dev/null +++ b/TRLevelControl/IO/TRXInjector.cs @@ -0,0 +1,199 @@ +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; +using TRLevelControl.Model; +using TRLevelControl.Model.TRX; + +namespace TRLevelControl.IO; + +public static class TRXInjector +{ + private const uint _magic = 'T' | 'R' << 8 | 'X' << 16 | 'J' << 24; + private const uint _version = 4; + + public static TRXInjectionData Read(TRLevelReader reader) + { + try + { + if (reader.ReadUInt32() != _magic) + { + return null; + } + } + catch (EndOfStreamException) + { + return null; + } + + // Skip version and config option value + reader.BaseStream.Position += 2 * sizeof(uint); + + var zipReader = reader.Inflate(TRChunkType.LevelData); + + // Ignore tests + zipReader.BaseStream.Position += sizeof(int); + var testLength = zipReader.ReadInt32(); + zipReader.BaseStream.Position += testLength; + + var chunkCount = zipReader.ReadInt32(); + var data = new TRXInjectionData(); + for (int i = 0; i < chunkCount; i++) + { + var chunk = TRXChunk.Read(zipReader); + using var chunkMS = new MemoryStream(chunk.Data); + using var chunkReader = new TRLevelReader(chunkMS); + ReadChunk(data, chunk, chunkReader); + } + + return data; + } + + private static void ReadChunk(TRXInjectionData data, TRXChunk chunk, TRLevelReader reader) + { + for (int i = 0; i < chunk.BlockCount; i++) + { + var blockType = (TRXBlockType)reader.ReadInt32(); + var blockCount = reader.ReadInt32(); + reader.BaseStream.Position += sizeof(int); // Skip total length + + for (int j = 0; j < blockCount; j++) + { + switch (blockType) + { + case TRXBlockType.SampleInfos: + data.SFX.Add(TRSFXData.Read(reader)); + break; + } + } + } + } + + public static void Write(TRXInjectionData data, TRLevelWriter outWriter) + { + var chunks = Chunkify(data); + if (chunks == null || chunks.Count == 0) + { + return; + } + + using var injStream = new MemoryStream(); + using var injWriter = new TRLevelWriter(injStream); + + injWriter.Write(0); // Number of tests + injWriter.Write(0); // Total length of tests + injWriter.Write(chunks.Count); + chunks.ForEach(c => c.Serialize(injWriter)); + + var inflatedData = injStream.ToArray(); + using var outStream = new MemoryStream(); + using var deflater = new DeflaterOutputStream(outStream); + using var inStream = new MemoryStream(inflatedData); + + inStream.CopyTo(deflater); + deflater.Finish(); + + var deflatedData = outStream.ToArray(); + + outWriter.Write(_magic); + outWriter.Write(_version); + outWriter.Write(0); // Normally a value to link to a config option + + outWriter.Write(inflatedData.Length); + outWriter.Write(deflatedData.Length); + outWriter.Write(deflatedData); + } + + private static List Chunkify(TRXInjectionData data) + { + if (data == null) + { + return null; + } + + var chunks = new List + { + CreateChunk(TRXChunkType.SFXData, data, WriteSFXData), + }; + + chunks.RemoveAll(c => c.BlockCount == 0); + return chunks; + } + + private static TRXChunk CreateChunk(TRXChunkType type, + TRXInjectionData data, Func process) + { + using var stream = new MemoryStream(); + using var writer = new TRLevelWriter(stream); + int blockCount = process(data, writer); + + return new() + { + Type = type, + BlockCount = blockCount, + Data = stream.ToArray(), + }; + } + + private static int WriteSFXData(TRXInjectionData data, TRLevelWriter writer) + { + return WriteBlock(TRXBlockType.SampleInfos, data.SFX.Count, writer, + s => data.SFX.ForEach(f => f.Write(s))); + } + + private static int WriteBlock(TRXBlockType type, int elementCount, + TRLevelWriter writer, Action subCallback) + { + if (elementCount == 0) + { + return 0; + } + + using var stream = new MemoryStream(); + using var subWriter = new TRLevelWriter(stream); + subCallback(subWriter); + subWriter.Flush(); + + var data = stream.ToArray(); + writer.Write((int)type); + writer.Write(elementCount); + writer.Write(data.Length); + writer.Write(data); + + return 1; + } + + private class TRXChunk + { + public TRXChunkType Type { get; set; } + public int BlockCount { get; set; } + public byte[] Data { get; set; } + + public void Serialize(TRLevelWriter writer) + { + writer.Write((int)Type); + writer.Write(BlockCount); + writer.Write(Data.Length); + writer.Write(Data); + } + + public static TRXChunk Read(TRLevelReader reader) + { + var chunk = new TRXChunk + { + Type = (TRXChunkType)reader.ReadInt32(), + BlockCount = reader.ReadInt32(), + }; + int blockLength = reader.ReadInt32(); + chunk.Data = reader.ReadBytes(blockLength); + return chunk; + } + } + + private enum TRXChunkType + { + SFXData = 5, + } + + private enum TRXBlockType + { + SampleInfos = 14, + } +} diff --git a/TRLevelControl/Model/TRLevelBase.cs b/TRLevelControl/Model/TRLevelBase.cs index d1d7dcb64..c4f41e5fb 100644 --- a/TRLevelControl/Model/TRLevelBase.cs +++ b/TRLevelControl/Model/TRLevelBase.cs @@ -1,4 +1,6 @@ -namespace TRLevelControl.Model; +using TRLevelControl.Model.TRX; + +namespace TRLevelControl.Model; public abstract class TRLevelBase { @@ -9,4 +11,5 @@ public abstract class TRLevelBase public List ObjectTextures { get; set; } public List AnimatedTextures { get; set; } public abstract IEnumerable DistinctMeshes { get; } + public TRXInjectionData TRXData { get; set; } } diff --git a/TRLevelControl/Model/TRX/TRSFXData.cs b/TRLevelControl/Model/TRX/TRSFXData.cs new file mode 100644 index 000000000..7c84409ba --- /dev/null +++ b/TRLevelControl/Model/TRX/TRSFXData.cs @@ -0,0 +1,44 @@ +namespace TRLevelControl.Model.TRX; + +public class TRSFXData +{ + public short ID { get; set; } + public ushort Volume { get; set; } + public ushort Chance { get; set; } + public ushort Flags { get; set; } + public List Data { get; set; } + + public static TRSFXData Read(TRLevelReader reader) + { + var sfx = new TRSFXData + { + ID = reader.ReadInt16(), + Volume = reader.ReadUInt16(), + Chance = reader.ReadUInt16(), + Flags = reader.ReadUInt16(), + Data = [], + }; + + int sampleCount = (sfx.Flags & 0xFC) >> 2; + for (int i = 0; i < sampleCount; i++) + { + var length = reader.ReadInt32(); + sfx.Data.Add(reader.ReadBytes(length)); + } + + return sfx; + } + + public void Write(TRLevelWriter writer) + { + writer.Write(ID); + writer.Write(Volume); + writer.Write(Chance); + writer.Write(Flags); + Data.ForEach(wav => + { + writer.Write(wav.Length); + writer.Write(wav); + }); + } +} diff --git a/TRLevelControl/Model/TRX/TRXInjectionData.cs b/TRLevelControl/Model/TRX/TRXInjectionData.cs new file mode 100644 index 000000000..33a0943d6 --- /dev/null +++ b/TRLevelControl/Model/TRX/TRXInjectionData.cs @@ -0,0 +1,6 @@ +namespace TRLevelControl.Model.TRX; + +public class TRXInjectionData +{ + public List SFX { get; set; } = []; +} diff --git a/TRLevelControl/TRLevelControlBase.cs b/TRLevelControl/TRLevelControlBase.cs index 12c39be4d..9ca25103a 100644 --- a/TRLevelControl/TRLevelControlBase.cs +++ b/TRLevelControl/TRLevelControlBase.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using TRLevelControl.IO; using TRLevelControl.Model; namespace TRLevelControl; @@ -24,6 +25,7 @@ public L Read(Stream stream) _level = CreateLevel((TRFileVersion)reader.ReadUInt32()); Initialise(); Read(reader); + _level.TRXData = TRXInjector.Read(reader); Debug.Assert(reader.BaseStream.Position == reader.BaseStream.Length); return _level; @@ -41,6 +43,7 @@ public void Write(L level, Stream outputStream) _level = level; Initialise(); Write(writer); + TRXInjector.Write(level.TRXData, writer); } protected abstract L CreateLevel(TRFileVersion version); diff --git a/TRLevelControlTests/TRX/IOTests.cs b/TRLevelControlTests/TRX/IOTests.cs new file mode 100644 index 000000000..2a4c828d0 --- /dev/null +++ b/TRLevelControlTests/TRX/IOTests.cs @@ -0,0 +1,44 @@ +using TRLevelControl.Model; +using TRLevelControl.Model.TRX; + +namespace TRLevelControlTests.TRX; + +[TestClass] +[TestCategory("TRXInjection")] +public class IOTests : TestBase +{ + [TestMethod] + public void TestSFX() + { + var level = GetTR1TestLevel(); + Assert.IsNull(level.TRXData); + + var sfxA = new TRSFXData + { + ID = (short)TR1SFX.NatlaDeath, + Chance = 4, + Flags = 1 << 2, + Volume = 16384, + Data = [[.. Enumerable.Range(0, 256).Select(i => (byte)i)]], + }; + level.TRXData = new(); + level.TRXData.SFX.Add(sfxA); + level.TRXData.SFX.Add(sfxA); + + level = WriteReadTempLevel(level); + + Assert.IsNotNull(level.TRXData); + Assert.HasCount(2, level.TRXData.SFX); + Assert.AreNotEqual(level.TRXData.SFX[0], level.TRXData.SFX[1]); + + for (int i = 0; i < 2; i++) + { + var sfxB = level.TRXData.SFX[i]; + Assert.AreEqual(sfxA.ID, sfxB.ID); + Assert.AreEqual(sfxA.Chance, sfxB.Chance); + Assert.AreEqual(sfxA.Flags, sfxB.Flags); + Assert.AreEqual(sfxA.Volume, sfxB.Volume); + CollectionAssert.AreEqual(sfxA.Data, sfxB.Data); + } + } +} From 89a95e6f959a2cc0f52adef1b3c9cadcfc20a508 Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Fri, 3 Oct 2025 12:42:48 +0100 Subject: [PATCH 2/3] Embed TR2X sound effects To avoid issues with using main.sfx when heavily randomizing audio, this ensures that the sample data is appended to the end of the level files instead. --- TRRandomizerCore/Editors/TR2ClassicEditor.cs | 25 ++++--- .../TR2/Classic/TR2AudioRandomizer.cs | 65 ++++++++++++++++++- 2 files changed, 80 insertions(+), 10 deletions(-) diff --git a/TRRandomizerCore/Editors/TR2ClassicEditor.cs b/TRRandomizerCore/Editors/TR2ClassicEditor.cs index 634230055..7f9b2aab2 100644 --- a/TRRandomizerCore/Editors/TR2ClassicEditor.cs +++ b/TRRandomizerCore/Editors/TR2ClassicEditor.cs @@ -276,18 +276,19 @@ protected override void SaveImpl(AbstractTRScriptEditor scriptEditor, TRSaveMoni environmentRandomizer.FinalizeEnvironment(); } + var audioRandomizer = new TR2AudioRandomizer + { + ScriptEditor = scriptEditor, + Levels = levels, + BasePath = wipDirectory, + BackupPath = backupDirectory, + SaveMonitor = monitor, + Settings = Settings + }; if (!monitor.IsCancelled && Settings.RandomizeAudio) { monitor.FireSaveStateBeginning(TRSaveCategory.Custom, "Randomizing audio tracks"); - new TR2AudioRandomizer - { - ScriptEditor = scriptEditor, - Levels = levels, - BasePath = wipDirectory, - BackupPath = backupDirectory, - SaveMonitor = monitor, - Settings = Settings - }.Randomize(Settings.AudioSeed); + audioRandomizer.Randomize(Settings.AudioSeed); } if (!monitor.IsCancelled && Settings.RandomizeOutfits) @@ -358,6 +359,12 @@ protected override void SaveImpl(AbstractTRScriptEditor scriptEditor, TRSaveMoni itemRandomizer.RandomizeSprites(); } + if (!monitor.IsCancelled && Settings.RandomizeAudio) + { + monitor.FireSaveStateBeginning(TRSaveCategory.Custom, "Embedding sound effects"); + audioRandomizer.EmbedSamples(); + } + AmendTitleAndCredits(scriptEditor, monitor); } diff --git a/TRRandomizerCore/Randomizers/TR2/Classic/TR2AudioRandomizer.cs b/TRRandomizerCore/Randomizers/TR2/Classic/TR2AudioRandomizer.cs index 23eaafd5f..0aec05f46 100644 --- a/TRRandomizerCore/Randomizers/TR2/Classic/TR2AudioRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR2/Classic/TR2AudioRandomizer.cs @@ -1,4 +1,6 @@ -namespace TRRandomizerCore.Randomizers; +using TRLevelControl; + +namespace TRRandomizerCore.Randomizers; public class TR2AudioRandomizer : BaseTR2Randomizer { @@ -29,4 +31,65 @@ public override void Randomize(int seed) } } } + + public void EmbedSamples() + { + var mainSFX = ReadMainSFX(); + if (mainSFX.Count == 0) + { + return; + } + + Parallel.ForEach(Levels, l => + { + var level = LoadCombinedLevel(l); + level.Data.TRXData ??= new(); + + foreach (var (sfxID, sfx) in level.Data.SoundEffects) + { + if (level.Data.TRXData.SFX.Any(s => s.ID == (short)sfxID)) + { + continue; + } + + level.Data.TRXData.SFX.Add(new() + { + ID = (short)sfxID, + Chance = sfx.Chance, + Flags = sfx.GetFlags(), + Volume = sfx.Volume, + Data = mainSFX.GetRange((int)sfx.SampleID, sfx.SampleCount), + }); + } + + SaveLevel(level); + }); + } + + private List ReadMainSFX() + { + var targetDir = Path.GetDirectoryName(ScriptEditor.OriginalFile.FullName); + var sfxFile = Path.GetFullPath(Path.Combine(targetDir, "../../data/main.sfx")); + var result = new List(_numSamples); + if (!File.Exists(sfxFile)) + { + return result; + } + + using var reader = new TRLevelReader(File.Open(sfxFile, FileMode.Open)); + while (reader.BaseStream.Position < reader.BaseStream.Length) + { + using var stream = new MemoryStream(); + using var writer = new TRLevelWriter(stream); + + var header = reader.ReadUInt32s(11); + var data = reader.ReadUInt8s(header[10]); + writer.Write(header); + writer.Write(data); + + result.Add(stream.ToArray()); + } + + return result; + } } From 4dfdc1d824890212534aac5c2fa27b52952c0a55 Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Fri, 3 Oct 2025 13:06:26 +0100 Subject: [PATCH 3/3] Embed TR2X barefoot SFX Embeds Lara's barefoot SFX if the diving suit or HSH outfit is picked. --- .../TR2/Classic/TR2OutfitRandomizer.cs | 15 +++++++++++++++ .../Resources/TR2/Audio/Barefoot/0.wav | Bin 0 -> 12372 bytes .../Resources/TR2/Audio/Barefoot/1.wav | Bin 0 -> 8672 bytes .../Resources/TR2/Audio/Barefoot/2.wav | Bin 0 -> 10598 bytes .../Resources/TR2/Audio/Barefoot/3.wav | Bin 0 -> 10598 bytes 5 files changed, 15 insertions(+) create mode 100644 TRRandomizerCore/Resources/TR2/Audio/Barefoot/0.wav create mode 100644 TRRandomizerCore/Resources/TR2/Audio/Barefoot/1.wav create mode 100644 TRRandomizerCore/Resources/TR2/Audio/Barefoot/2.wav create mode 100644 TRRandomizerCore/Resources/TR2/Audio/Barefoot/3.wav diff --git a/TRRandomizerCore/Randomizers/TR2/Classic/TR2OutfitRandomizer.cs b/TRRandomizerCore/Randomizers/TR2/Classic/TR2OutfitRandomizer.cs index be47046b5..dfc05623d 100644 --- a/TRRandomizerCore/Randomizers/TR2/Classic/TR2OutfitRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR2/Classic/TR2OutfitRandomizer.cs @@ -389,6 +389,21 @@ private void AdjustOutfit(TR2CombinedLevel level, TR2Type lara) actorLara.MeshTrees = realLara.MeshTrees; actorLara.Meshes = realLara.Meshes; } + + if ((lara == TR2Type.LaraUnwater || lara == TR2Type.LaraHome) + && level.Data.SoundEffects.TryGetValue(TR2SFX.LaraFeet, out var feet)) + { + level.Data.TRXData ??= new(); + level.Data.TRXData.SFX.RemoveAll(s => s.ID == (short)TR2SFX.LaraFeet); + level.Data.TRXData.SFX.Add(new() + { + ID = (short)TR2SFX.LaraFeet, + Chance = feet.Chance, + Flags = feet.GetFlags(), + Volume = feet.Volume, + Data = [.. Enumerable.Range(0, 4).Select(i => File.ReadAllBytes($"Resources/TR2/Audio/Barefoot/{i}.wav"))], + }); + } } } } diff --git a/TRRandomizerCore/Resources/TR2/Audio/Barefoot/0.wav b/TRRandomizerCore/Resources/TR2/Audio/Barefoot/0.wav new file mode 100644 index 0000000000000000000000000000000000000000..ca939a3d7eac0a355da492804dbdc318dd99b5a2 GIT binary patch literal 12372 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 literal 0 HcmV?d00001 diff --git a/TRRandomizerCore/Resources/TR2/Audio/Barefoot/1.wav b/TRRandomizerCore/Resources/TR2/Audio/Barefoot/1.wav new file mode 100644 index 0000000000000000000000000000000000000000..f135e19f51b827706cc7c8d5ea41b801ee6ebc8a GIT binary patch literal 8672 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 Hc?A9s1Y!9; literal 0 HcmV?d00001 diff --git a/TRRandomizerCore/Resources/TR2/Audio/Barefoot/3.wav b/TRRandomizerCore/Resources/TR2/Audio/Barefoot/3.wav new file mode 100644 index 0000000000000000000000000000000000000000..8bb38db6ced5715d51cb684af1e62de2cdd336fc GIT binary patch literal 10598 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 YnlB#s;(;$7_~L;t9{A#c|BVO!3)&dV`~Uy| literal 0 HcmV?d00001