diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs index 9240c0a7..c28abe5c 100644 --- a/ChocolArm64/AOpCodeTable.cs +++ b/ChocolArm64/AOpCodeTable.cs @@ -139,6 +139,7 @@ namespace ChocolArm64 Set("0x001110001xxxxx000111xxxxxxxxxx", AInstEmit.And_V, typeof(AOpCodeSimdReg)); Set("0x001110011xxxxx000111xxxxxxxxxx", AInstEmit.Bic_V, typeof(AOpCodeSimdReg)); Set("0x10111100000xxx<101110<<1xxxxx100011xxxxxxxxxx", AInstEmit.Cmeq_V, typeof(AOpCodeSimdReg)); Set("0>001110<<100000100110xxxxxxxxxx", AInstEmit.Cmeq_V, typeof(AOpCodeSimd)); diff --git a/ChocolArm64/Instruction/AInstEmitSimdLogical.cs b/ChocolArm64/Instruction/AInstEmitSimdLogical.cs index 5b71a0bb..8fd8ea4d 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdLogical.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdLogical.cs @@ -32,6 +32,36 @@ namespace ChocolArm64.Instruction }); } + public static void Bif_V(AILEmitterCtx Context) + { + AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + + int Bytes = Context.CurrOp.GetBitsCount() >> 3; + + for (int Index = 0; Index < (Bytes >> Op.Size); Index++) + { + EmitVectorExtractZx(Context, Op.Rd, Index, Op.Size); + EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size); + + Context.Emit(OpCodes.Xor); + + EmitVectorExtractZx(Context, Op.Rm, Index, Op.Size); + + Context.Emit(OpCodes.And); + + EmitVectorExtractZx(Context, Op.Rd, Index, Op.Size); + + Context.Emit(OpCodes.Xor); + + EmitVectorInsert(Context, Op.Rd, Index, Op.Size); + } + + if (Op.RegisterSize == ARegisterSize.SIMD64) + { + EmitVectorZeroUpper(Context, Op.Rd); + } + } + public static void Bsl_V(AILEmitterCtx Context) { EmitVectorTernaryOpZx(Context, () => diff --git a/Ryujinx.Audio/IAalOutput.cs b/Ryujinx.Audio/IAalOutput.cs index 7ed0e0b6..5ffeebdd 100644 --- a/Ryujinx.Audio/IAalOutput.cs +++ b/Ryujinx.Audio/IAalOutput.cs @@ -3,12 +3,14 @@ namespace Ryujinx.Audio public interface IAalOutput { int OpenTrack(int SampleRate, int Channels, out AudioFormat Format); + void CloseTrack(int Track); - void AppendBuffer(int Track, long Tag, byte[] Buffer); bool ContainsBuffer(int Track, long Tag); - long[] GetReleasedBuffers(int Track); + long[] GetReleasedBuffers(int Track, int MaxCount); + + void AppendBuffer(int Track, long Tag, byte[] Buffer); void Start(int Track); void Stop(int Track); diff --git a/Ryujinx.Audio/OpenAL/OpenALAudioOut.cs b/Ryujinx.Audio/OpenAL/OpenALAudioOut.cs index 7cf30c18..48dcd199 100644 --- a/Ryujinx.Audio/OpenAL/OpenALAudioOut.cs +++ b/Ryujinx.Audio/OpenAL/OpenALAudioOut.cs @@ -10,6 +10,8 @@ namespace Ryujinx.Audio.OpenAL { private const int MaxTracks = 256; + private const int MaxReleased = 32; + private AudioContext Context; private class Track : IDisposable @@ -26,6 +28,8 @@ namespace Ryujinx.Audio.OpenAL private Queue QueuedTagsQueue; + private Queue ReleasedTagsQueue; + private bool Disposed; public Track(int SampleRate, ALFormat Format) @@ -40,9 +44,45 @@ namespace Ryujinx.Audio.OpenAL Buffers = new ConcurrentDictionary(); QueuedTagsQueue = new Queue(); + + ReleasedTagsQueue = new Queue(); } - public int GetBufferId(long Tag) + public bool ContainsBuffer(long Tag) + { + SyncQueuedTags(); + + foreach (long QueuedTag in QueuedTagsQueue) + { + if (QueuedTag == Tag) + { + return true; + } + } + + return false; + } + + public long[] GetReleasedBuffers(int MaxCount) + { + ClearReleased(); + + List Tags = new List(); + + HashSet Unique = new HashSet(); + + while (MaxCount-- > 0 && ReleasedTagsQueue.TryDequeue(out long Tag)) + { + if (Unique.Add(Tag)) + { + Tags.Add(Tag); + } + } + + return Tags.ToArray(); + } + + public int AppendBuffer(long Tag) { if (Disposed) { @@ -63,23 +103,6 @@ namespace Ryujinx.Audio.OpenAL return Id; } - public long[] GetReleasedBuffers() - { - ClearReleased(); - - List Tags = new List(); - - foreach (long Tag in Buffers.Keys) - { - if (!ContainsBuffer(Tag)) - { - Tags.Add(Tag); - } - } - - return Tags.ToArray(); - } - public void ClearReleased() { SyncQueuedTags(); @@ -91,21 +114,6 @@ namespace Ryujinx.Audio.OpenAL AL.SourceUnqueueBuffers(SourceId, ReleasedCount); } } - - public bool ContainsBuffer(long Tag) - { - SyncQueuedTags(); - - foreach (long QueuedTag in QueuedTagsQueue) - { - if (QueuedTag == Tag) - { - return true; - } - } - - return false; - } private void SyncQueuedTags() { @@ -116,7 +124,12 @@ namespace Ryujinx.Audio.OpenAL while (QueuedTagsQueue.Count > QueuedCount) { - QueuedTagsQueue.Dequeue(); + ReleasedTagsQueue.Enqueue(QueuedTagsQueue.Dequeue()); + } + + while (ReleasedTagsQueue.Count > MaxReleased) + { + ReleasedTagsQueue.Dequeue(); } } @@ -202,20 +215,6 @@ namespace Ryujinx.Audio.OpenAL } } - public void AppendBuffer(int Track, long Tag, byte[] Buffer) - { - if (Tracks.TryGetValue(Track, out Track Td)) - { - int BufferId = Td.GetBufferId(Tag); - - AL.BufferData(BufferId, Td.Format, Buffer, Buffer.Length, Td.SampleRate); - - AL.SourceQueueBuffer(Td.SourceId, BufferId); - - StartPlaybackIfNeeded(Td); - } - } - public bool ContainsBuffer(int Track, long Tag) { if (Tracks.TryGetValue(Track, out Track Td)) @@ -226,16 +225,30 @@ namespace Ryujinx.Audio.OpenAL return false; } - public long[] GetReleasedBuffers(int Track) + public long[] GetReleasedBuffers(int Track, int MaxCount) { if (Tracks.TryGetValue(Track, out Track Td)) { - return Td.GetReleasedBuffers(); + return Td.GetReleasedBuffers(MaxCount); } return null; } + public void AppendBuffer(int Track, long Tag, byte[] Buffer) + { + if (Tracks.TryGetValue(Track, out Track Td)) + { + int BufferId = Td.AppendBuffer(Tag); + + AL.BufferData(BufferId, Td.Format, Buffer, Buffer.Length, Td.SampleRate); + + AL.SourceQueueBuffer(Td.SourceId, BufferId); + + StartPlaybackIfNeeded(Td); + } + } + public void Start(int Track) { if (Tracks.TryGetValue(Track, out Track Td)) diff --git a/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs b/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs index d0528a6d..8cd013f8 100644 --- a/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs +++ b/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs @@ -91,7 +91,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud uint Count = (uint)((ulong)Size >> 3); - long[] ReleasedBuffers = AudioOut.GetReleasedBuffers(Track); + long[] ReleasedBuffers = AudioOut.GetReleasedBuffers(Track, (int)Count); for (uint Index = 0; Index < Count; Index++) {