diff --git a/Ryujinx.HLE/OsHle/Services/Aud/AudioRendererParameter.cs b/Ryujinx.HLE/OsHle/Services/Aud/AudioRendererParameter.cs new file mode 100644 index 00000000..0a0792ec --- /dev/null +++ b/Ryujinx.HLE/OsHle/Services/Aud/AudioRendererParameter.cs @@ -0,0 +1,22 @@ +using System.Runtime.InteropServices; + +namespace Ryujinx.HLE.OsHle.Services.Aud +{ + [StructLayout(LayoutKind.Sequential)] + struct AudioRendererParameter + { + public int SampleRate; + public int SampleCount; + public int Unknown8; + public int UnknownC; + public int VoiceCount; + public int SinkCount; + public int EffectCount; + public int Unknown1C; + public int Unknown20; + public int SplitterCount; + public int Unknown28; + public int Unknown2C; + public int Revision; + } +} diff --git a/Ryujinx.HLE/OsHle/Services/Aud/IAudioRenderer.cs b/Ryujinx.HLE/OsHle/Services/Aud/IAudioRenderer.cs index 9c495db5..70601202 100644 --- a/Ryujinx.HLE/OsHle/Services/Aud/IAudioRenderer.cs +++ b/Ryujinx.HLE/OsHle/Services/Aud/IAudioRenderer.cs @@ -1,8 +1,10 @@ +using ChocolArm64.Memory; using Ryujinx.HLE.Logging; using Ryujinx.HLE.OsHle.Handles; using Ryujinx.HLE.OsHle.Ipc; using System; using System.Collections.Generic; +using System.Runtime.InteropServices; namespace Ryujinx.HLE.OsHle.Services.Aud { @@ -14,7 +16,9 @@ namespace Ryujinx.HLE.OsHle.Services.Aud private KEvent UpdateEvent; - public IAudioRenderer() + private AudioRendererParameter Params; + + public IAudioRenderer(AudioRendererParameter Params) { m_Commands = new Dictionary() { @@ -25,26 +29,50 @@ namespace Ryujinx.HLE.OsHle.Services.Aud }; UpdateEvent = new KEvent(); + + this.Params = Params; } public long RequestUpdateAudioRenderer(ServiceCtx Context) { - //(buffer) -> (buffer, buffer) + long OutputPosition = Context.Request.ReceiveBuff[0].Position; - long Position = Context.Request.ReceiveBuff[0].Position; + long InputPosition = Context.Request.SendBuff[0].Position; - //0x40 bytes header - Context.Memory.WriteInt32(Position + 0x4, 0xb0); //Behavior Out State Size? (note: this is the last section) - Context.Memory.WriteInt32(Position + 0x8, 0x18e0); //Memory Pool Out State Size? - Context.Memory.WriteInt32(Position + 0xc, 0x600); //Voice Out State Size? - Context.Memory.WriteInt32(Position + 0x14, 0xe0); //Effect Out State Size? - Context.Memory.WriteInt32(Position + 0x1c, 0x20); //Sink Out State Size? - Context.Memory.WriteInt32(Position + 0x20, 0x10); //Performance Out State Size? - Context.Memory.WriteInt32(Position + 0x3c, 0x20e0); //Total Size (including 0x40 bytes header) + UpdateDataHeader InputDataHeader = AMemoryHelper.Read(Context.Memory, InputPosition); - for (int Offset = 0x40; Offset < 0x40 + 0x18e0; Offset += 0x10) + int MemoryPoolOffset = Marshal.SizeOf(InputDataHeader) + InputDataHeader.BehaviorSize; + + UpdateDataHeader OutputDataHeader = new UpdateDataHeader(); + + OutputDataHeader.Revision = Params.Revision; + OutputDataHeader.BehaviorSize = 0xb0; + OutputDataHeader.MemoryPoolsSize = (Params.EffectCount + (Params.VoiceCount * 4)) * 0x10; + OutputDataHeader.VoicesSize = Params.VoiceCount * 0x10; + OutputDataHeader.EffectsSize = Params.EffectCount * 0x10; + OutputDataHeader.SinksSize = Params.SinkCount * 0x20; + OutputDataHeader.PerformanceManagerSize = 0x10; + OutputDataHeader.TotalSize = Marshal.SizeOf(OutputDataHeader) + OutputDataHeader.BehaviorSize + OutputDataHeader.MemoryPoolsSize + + OutputDataHeader.VoicesSize + OutputDataHeader.EffectsSize + OutputDataHeader.SinksSize + OutputDataHeader.PerformanceManagerSize; + + AMemoryHelper.Write(Context.Memory, OutputPosition, OutputDataHeader); + + for (int Offset = 0x40; Offset < 0x40 + OutputDataHeader.MemoryPoolsSize; Offset += 0x10, MemoryPoolOffset += 0x20) { - Context.Memory.WriteInt32(Position + Offset, 5); + MemoryPoolStates PoolState = (MemoryPoolStates) Context.Memory.ReadInt32(InputPosition + MemoryPoolOffset + 0x10); + + if (PoolState == MemoryPoolStates.RequestAttach) + { + Context.Memory.WriteInt32(OutputPosition + Offset, (int)MemoryPoolStates.Attached); + } + else if (PoolState == MemoryPoolStates.RequestDetach) + { + Context.Memory.WriteInt32(OutputPosition + Offset, (int)MemoryPoolStates.Detached); + } + else + { + Context.Memory.WriteInt32(OutputPosition + Offset, (int)PoolState); + } } //TODO: We shouldn't be signaling this here. @@ -89,4 +117,5 @@ namespace Ryujinx.HLE.OsHle.Services.Aud } } } -} \ No newline at end of file +} + \ No newline at end of file diff --git a/Ryujinx.HLE/OsHle/Services/Aud/IAudioRendererManager.cs b/Ryujinx.HLE/OsHle/Services/Aud/IAudioRendererManager.cs index 6c0ba870..a7daeedd 100644 --- a/Ryujinx.HLE/OsHle/Services/Aud/IAudioRendererManager.cs +++ b/Ryujinx.HLE/OsHle/Services/Aud/IAudioRendererManager.cs @@ -1,6 +1,7 @@ using Ryujinx.HLE.Logging; using Ryujinx.HLE.OsHle.Ipc; using System.Collections.Generic; +using System.Runtime.InteropServices; namespace Ryujinx.HLE.OsHle.Services.Aud { @@ -29,7 +30,23 @@ namespace Ryujinx.HLE.OsHle.Services.Aud { //Same buffer as GetAudioRendererWorkBufferSize is receive here. - MakeObject(Context, new IAudioRenderer()); + AudioRendererParameter Params = new AudioRendererParameter(); + + Params.SampleRate = Context.RequestData.ReadInt32(); + Params.SampleCount = Context.RequestData.ReadInt32(); + Params.Unknown8 = Context.RequestData.ReadInt32(); + Params.UnknownC = Context.RequestData.ReadInt32(); + Params.VoiceCount = Context.RequestData.ReadInt32(); + Params.SinkCount = Context.RequestData.ReadInt32(); + Params.EffectCount = Context.RequestData.ReadInt32(); + Params.Unknown1C = Context.RequestData.ReadInt32(); + Params.Unknown20 = Context.RequestData.ReadInt32(); + Params.SplitterCount = Context.RequestData.ReadInt32(); + Params.Unknown28 = Context.RequestData.ReadInt32(); + Params.Unknown2C = Context.RequestData.ReadInt32(); + Params.Revision = Context.RequestData.ReadInt32(); + + MakeObject(Context, new IAudioRenderer(Params)); return 0; } @@ -48,7 +65,7 @@ namespace Ryujinx.HLE.OsHle.Services.Aud long Unknown24 = Context.RequestData.ReadUInt32(); long Unknown28 = Context.RequestData.ReadUInt32(); //SplitterCount long Unknown2c = Context.RequestData.ReadUInt32(); //Not used here in FW3.0.1 - int RevMagic = Context.RequestData.ReadInt32(); + int RevMagic = Context.RequestData.ReadInt32(); int Version = (RevMagic - Rev0Magic) >> 24; diff --git a/Ryujinx.HLE/OsHle/Services/Aud/MemoryPoolStates.cs b/Ryujinx.HLE/OsHle/Services/Aud/MemoryPoolStates.cs new file mode 100644 index 00000000..20f9ce79 --- /dev/null +++ b/Ryujinx.HLE/OsHle/Services/Aud/MemoryPoolStates.cs @@ -0,0 +1,13 @@ +namespace Ryujinx.HLE.OsHle.Services.Aud +{ + enum MemoryPoolStates : int + { + Invalid = 0x0, + Unknown = 0x1, + RequestDetach = 0x2, + Detached = 0x3, + RequestAttach = 0x4, + Attached = 0x5, + Released = 0x6, + } +} diff --git a/Ryujinx.HLE/OsHle/Services/Aud/UpdateDataHeader.cs b/Ryujinx.HLE/OsHle/Services/Aud/UpdateDataHeader.cs new file mode 100644 index 00000000..f944b302 --- /dev/null +++ b/Ryujinx.HLE/OsHle/Services/Aud/UpdateDataHeader.cs @@ -0,0 +1,22 @@ +namespace Ryujinx.HLE.OsHle.Services.Aud +{ + struct UpdateDataHeader + { + public int Revision; + public int BehaviorSize; + public int MemoryPoolsSize; + public int VoicesSize; + public int VoiceResourceSize; + public int EffectsSize; + public int MixesSize; + public int SinksSize; + public int PerformanceManagerSize; + public int Unknown24; + public int Unknown28; + public int Unknown2C; + public int Unknown30; + public int Unknown34; + public int Unknown38; + public int TotalSize; + } +}