aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-03-15 21:06:24 -0300
committerGitHub <noreply@github.com>2018-03-15 21:06:24 -0300
commit79a59397349b40758fc75cd2e19c67726a77e975 (patch)
tree4597fcdf8d8d6886df88c00650b7d924c7fc16fe
parent92f47d535e7c3b350c25499dec5e91d8be5544bc (diff)
Improvements to audout (#58)
* Some audout refactoring and improvements * More audio improvements * Change ReadAsciiString to use long for the Size, avoids some casting
-rw-r--r--ChocolArm64/Memory/AMemoryHelper.cs38
-rw-r--r--Ryujinx.Audio/AudioFormat.cs13
-rw-r--r--Ryujinx.Audio/IAalOutput.cs18
-rw-r--r--Ryujinx.Audio/OpenAL/OpenALAudioOut.cs283
-rw-r--r--Ryujinx.Audio/PlaybackState.cs8
-rw-r--r--Ryujinx.Audio/Ryujinx.Audio.csproj11
-rw-r--r--Ryujinx.Core/OsHle/Homebrew.cs2
-rw-r--r--Ryujinx.Core/OsHle/Ipc/IpcPtrBuffDesc.cs4
-rw-r--r--Ryujinx.Core/OsHle/ServiceMgr.cs22
-rw-r--r--Ryujinx.Core/OsHle/Services/Aud/AudioOutData.cs14
-rw-r--r--Ryujinx.Core/OsHle/Services/Aud/IAudioDevice.cs2
-rw-r--r--Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs175
-rw-r--r--Ryujinx.Core/OsHle/Services/Aud/ServiceAudOut.cs63
-rw-r--r--Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs12
-rw-r--r--Ryujinx.Core/OsHle/Services/FspSrv/IFile.cs2
-rw-r--r--Ryujinx.Core/OsHle/Services/Lm/ILogger.cs2
-rw-r--r--Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs6
-rw-r--r--Ryujinx.Core/OsHle/Svc/SvcSystem.cs6
-rw-r--r--Ryujinx.Core/Ryujinx.Core.csproj1
-rw-r--r--Ryujinx.Core/Settings/SystemSettings.cs (renamed from Ryujinx.Core/Settings/SetSys.cs)2
-rw-r--r--Ryujinx.Core/Switch.cs41
-rw-r--r--Ryujinx.Core/VirtualFileSystem.cs (renamed from Ryujinx.Core/VirtualFs.cs)2
-rw-r--r--Ryujinx.Graphics/Gpu/NsGpuPGraph.cs2
-rw-r--r--Ryujinx/Ryujinx.csproj1
-rw-r--r--Ryujinx/Ui/Program.cs8
25 files changed, 564 insertions, 174 deletions
diff --git a/ChocolArm64/Memory/AMemoryHelper.cs b/ChocolArm64/Memory/AMemoryHelper.cs
index 219aeebf..1e346298 100644
--- a/ChocolArm64/Memory/AMemoryHelper.cs
+++ b/ChocolArm64/Memory/AMemoryHelper.cs
@@ -1,4 +1,6 @@
+using System;
using System.IO;
+using System.Runtime.InteropServices;
using System.Text;
namespace ChocolArm64.Memory
@@ -20,11 +22,11 @@ namespace ChocolArm64.Memory
}
}
- public static byte[] ReadBytes(AMemory Memory, long Position, int Size)
+ public static byte[] ReadBytes(AMemory Memory, long Position, long Size)
{
byte[] Data = new byte[Size];
- for (int Offs = 0; Offs < Size; Offs++)
+ for (long Offs = 0; Offs < Size; Offs++)
{
Data[Offs] = (byte)Memory.ReadByte(Position + Offs);
}
@@ -40,11 +42,39 @@ namespace ChocolArm64.Memory
}
}
- public static string ReadAsciiString(AMemory Memory, long Position, int MaxSize = -1)
+ public unsafe static T Read<T>(AMemory Memory, long Position) where T : struct
+ {
+ long Size = Marshal.SizeOf<T>();
+
+ if ((ulong)(Position + Size) > AMemoryMgr.AddrSize)
+ {
+ throw new ArgumentOutOfRangeException(nameof(Position));
+ }
+
+ IntPtr Ptr = new IntPtr((byte*)Memory.Ram + Position);
+
+ return Marshal.PtrToStructure<T>(Ptr);
+ }
+
+ public unsafe static void Write<T>(AMemory Memory, long Position, T Value) where T : struct
+ {
+ long Size = Marshal.SizeOf<T>();
+
+ if ((ulong)(Position + Size) > AMemoryMgr.AddrSize)
+ {
+ throw new ArgumentOutOfRangeException(nameof(Position));
+ }
+
+ IntPtr Ptr = new IntPtr((byte*)Memory.Ram + Position);
+
+ Marshal.StructureToPtr<T>(Value, Ptr, false);
+ }
+
+ public static string ReadAsciiString(AMemory Memory, long Position, long MaxSize = -1)
{
using (MemoryStream MS = new MemoryStream())
{
- for (int Offs = 0; Offs < MaxSize || MaxSize == -1; Offs++)
+ for (long Offs = 0; Offs < MaxSize || MaxSize == -1; Offs++)
{
byte Value = (byte)Memory.ReadByte(Position + Offs);
diff --git a/Ryujinx.Audio/AudioFormat.cs b/Ryujinx.Audio/AudioFormat.cs
new file mode 100644
index 00000000..8250d136
--- /dev/null
+++ b/Ryujinx.Audio/AudioFormat.cs
@@ -0,0 +1,13 @@
+namespace Ryujinx.Audio
+{
+ public enum AudioFormat
+ {
+ Invalid = 0,
+ PcmInt8 = 1,
+ PcmInt16 = 2,
+ PcmImt24 = 3,
+ PcmImt32 = 4,
+ PcmFloat = 5,
+ Adpcm = 6
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Audio/IAalOutput.cs b/Ryujinx.Audio/IAalOutput.cs
new file mode 100644
index 00000000..7ed0e0b6
--- /dev/null
+++ b/Ryujinx.Audio/IAalOutput.cs
@@ -0,0 +1,18 @@
+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);
+
+ void Start(int Track);
+ void Stop(int Track);
+
+ PlaybackState GetState(int Track);
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Audio/OpenAL/OpenALAudioOut.cs b/Ryujinx.Audio/OpenAL/OpenALAudioOut.cs
new file mode 100644
index 00000000..7cf30c18
--- /dev/null
+++ b/Ryujinx.Audio/OpenAL/OpenALAudioOut.cs
@@ -0,0 +1,283 @@
+using OpenTK.Audio;
+using OpenTK.Audio.OpenAL;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+
+namespace Ryujinx.Audio.OpenAL
+{
+ public class OpenALAudioOut : IAalOutput
+ {
+ private const int MaxTracks = 256;
+
+ private AudioContext Context;
+
+ private class Track : IDisposable
+ {
+ public int SourceId { get; private set; }
+
+ public int SampleRate { get; private set; }
+
+ public ALFormat Format { get; private set; }
+
+ public PlaybackState State { get; set; }
+
+ private ConcurrentDictionary<long, int> Buffers;
+
+ private Queue<long> QueuedTagsQueue;
+
+ private bool Disposed;
+
+ public Track(int SampleRate, ALFormat Format)
+ {
+ this.SampleRate = SampleRate;
+ this.Format = Format;
+
+ State = PlaybackState.Stopped;
+
+ SourceId = AL.GenSource();
+
+ Buffers = new ConcurrentDictionary<long, int>();
+
+ QueuedTagsQueue = new Queue<long>();
+ }
+
+ public int GetBufferId(long Tag)
+ {
+ if (Disposed)
+ {
+ throw new ObjectDisposedException(nameof(Track));
+ }
+
+ int Id = AL.GenBuffer();
+
+ Buffers.AddOrUpdate(Tag, Id, (Key, OldId) =>
+ {
+ AL.DeleteBuffer(OldId);
+
+ return Id;
+ });
+
+ QueuedTagsQueue.Enqueue(Tag);
+
+ return Id;
+ }
+
+ public long[] GetReleasedBuffers()
+ {
+ ClearReleased();
+
+ List<long> Tags = new List<long>();
+
+ foreach (long Tag in Buffers.Keys)
+ {
+ if (!ContainsBuffer(Tag))
+ {
+ Tags.Add(Tag);
+ }
+ }
+
+ return Tags.ToArray();
+ }
+
+ public void ClearReleased()
+ {
+ SyncQueuedTags();
+
+ AL.GetSource(SourceId, ALGetSourcei.BuffersProcessed, out int ReleasedCount);
+
+ if (ReleasedCount > 0)
+ {
+ 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()
+ {
+ AL.GetSource(SourceId, ALGetSourcei.BuffersQueued, out int QueuedCount);
+ AL.GetSource(SourceId, ALGetSourcei.BuffersProcessed, out int ReleasedCount);
+
+ QueuedCount -= ReleasedCount;
+
+ while (QueuedTagsQueue.Count > QueuedCount)
+ {
+ QueuedTagsQueue.Dequeue();
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool Disposing)
+ {
+ if (Disposing && !Disposed)
+ {
+ Disposed = true;
+
+ AL.DeleteSource(SourceId);
+
+ foreach (int Id in Buffers.Values)
+ {
+ AL.DeleteBuffer(Id);
+ }
+ }
+ }
+ }
+
+ private ConcurrentDictionary<int, Track> Tracks;
+
+ public OpenALAudioOut()
+ {
+ Context = new AudioContext();
+
+ Tracks = new ConcurrentDictionary<int, Track>();
+ }
+
+ public int OpenTrack(int SampleRate, int Channels, out AudioFormat Format)
+ {
+ Format = AudioFormat.PcmInt16;
+
+ Track Td = new Track(SampleRate, GetALFormat(Channels, Format));
+
+ for (int Id = 0; Id < MaxTracks; Id++)
+ {
+ if (Tracks.TryAdd(Id, Td))
+ {
+ return Id;
+ }
+ }
+
+ return -1;
+ }
+
+ private ALFormat GetALFormat(int Channels, AudioFormat Format)
+ {
+ if (Channels < 1 || Channels > 2)
+ {
+ throw new ArgumentOutOfRangeException(nameof(Channels));
+ }
+
+ if (Channels == 1)
+ {
+ switch (Format)
+ {
+ case AudioFormat.PcmInt8: return ALFormat.Mono8;
+ case AudioFormat.PcmInt16: return ALFormat.Mono16;
+ }
+ }
+ else /* if (Channels == 2) */
+ {
+ switch (Format)
+ {
+ case AudioFormat.PcmInt8: return ALFormat.Stereo8;
+ case AudioFormat.PcmInt16: return ALFormat.Stereo16;
+ }
+ }
+
+ throw new ArgumentException(nameof(Format));
+ }
+
+ public void CloseTrack(int Track)
+ {
+ if (Tracks.TryRemove(Track, out Track Td))
+ {
+ Td.Dispose();
+ }
+ }
+
+ 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))
+ {
+ return Td.ContainsBuffer(Tag);
+ }
+
+ return false;
+ }
+
+ public long[] GetReleasedBuffers(int Track)
+ {
+ if (Tracks.TryGetValue(Track, out Track Td))
+ {
+ return Td.GetReleasedBuffers();
+ }
+
+ return null;
+ }
+
+ public void Start(int Track)
+ {
+ if (Tracks.TryGetValue(Track, out Track Td))
+ {
+ Td.State = PlaybackState.Playing;
+
+ StartPlaybackIfNeeded(Td);
+ }
+ }
+
+ private void StartPlaybackIfNeeded(Track Td)
+ {
+ AL.GetSource(Td.SourceId, ALGetSourcei.SourceState, out int StateInt);
+
+ ALSourceState State = (ALSourceState)StateInt;
+
+ if (State != ALSourceState.Playing && Td.State == PlaybackState.Playing)
+ {
+ Td.ClearReleased();
+
+ AL.SourcePlay(Td.SourceId);
+ }
+ }
+
+ public void Stop(int Track)
+ {
+ if (Tracks.TryGetValue(Track, out Track Td))
+ {
+ Td.State = PlaybackState.Stopped;
+
+ AL.SourceStop(Td.SourceId);
+ }
+ }
+
+ public PlaybackState GetState(int Track)
+ {
+ if (Tracks.TryGetValue(Track, out Track Td))
+ {
+ return Td.State;
+ }
+
+ return PlaybackState.Stopped;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Audio/PlaybackState.cs b/Ryujinx.Audio/PlaybackState.cs
new file mode 100644
index 00000000..8b53128a
--- /dev/null
+++ b/Ryujinx.Audio/PlaybackState.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.Audio
+{
+ public enum PlaybackState
+ {
+ Playing = 0,
+ Stopped = 1
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Audio/Ryujinx.Audio.csproj b/Ryujinx.Audio/Ryujinx.Audio.csproj
new file mode 100644
index 00000000..2e7c86fa
--- /dev/null
+++ b/Ryujinx.Audio/Ryujinx.Audio.csproj
@@ -0,0 +1,11 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>netcoreapp2.0</TargetFramework>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="OpenTK.NETCore" Version="1.1.2749.6433" />
+ </ItemGroup>
+
+</Project>
diff --git a/Ryujinx.Core/OsHle/Homebrew.cs b/Ryujinx.Core/OsHle/Homebrew.cs
index 2a717ca7..873dda02 100644
--- a/Ryujinx.Core/OsHle/Homebrew.cs
+++ b/Ryujinx.Core/OsHle/Homebrew.cs
@@ -51,7 +51,7 @@ namespace Ryujinx.Core.OsHle
long Value0 = Memory.ReadInt64(Position + 0x08);
long Value1 = Memory.ReadInt64(Position + 0x10);
- FileName = AMemoryHelper.ReadAsciiString(Memory, Value0, (int)(Value1 - Value0));
+ FileName = AMemoryHelper.ReadAsciiString(Memory, Value0, Value1 - Value0);
break;
}
diff --git a/Ryujinx.Core/OsHle/Ipc/IpcPtrBuffDesc.cs b/Ryujinx.Core/OsHle/Ipc/IpcPtrBuffDesc.cs
index d39f78db..4eb15b9d 100644
--- a/Ryujinx.Core/OsHle/Ipc/IpcPtrBuffDesc.cs
+++ b/Ryujinx.Core/OsHle/Ipc/IpcPtrBuffDesc.cs
@@ -6,7 +6,7 @@ namespace Ryujinx.Core.OsHle.Ipc
{
public long Position { get; private set; }
public int Index { get; private set; }
- public short Size { get; private set; }
+ public long Size { get; private set; }
public IpcPtrBuffDesc(BinaryReader Reader)
{
@@ -20,7 +20,7 @@ namespace Ryujinx.Core.OsHle.Ipc
Index = ((int)Word0 >> 0) & 0x03f;
Index |= ((int)Word0 >> 3) & 0x1c0;
- Size = (short)(Word0 >> 16);
+ Size = (ushort)(Word0 >> 16);
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/ServiceMgr.cs b/Ryujinx.Core/OsHle/ServiceMgr.cs
index f59647af..39f62368 100644
--- a/Ryujinx.Core/OsHle/ServiceMgr.cs
+++ b/Ryujinx.Core/OsHle/ServiceMgr.cs
@@ -37,7 +37,25 @@ namespace Ryujinx.Core.OsHle
{
lock (Services)
{
- if (!Services.TryGetValue(Name, out IIpcService Service))
+ string LookUpName;
+
+ //Same service with different privileges.
+ if (Name.EndsWith(":a") ||
+ Name.EndsWith(":m") ||
+ Name.EndsWith(":s") ||
+ Name.EndsWith(":su") ||
+ Name.EndsWith(":u") ||
+ Name.EndsWith(":u0") ||
+ Name.EndsWith(":u1"))
+ {
+ LookUpName = Name.Substring(0, Name.IndexOf(':'));
+ }
+ else
+ {
+ LookUpName = Name;
+ }
+
+ if (!Services.TryGetValue(LookUpName, out IIpcService Service))
{
switch (Name)
{
@@ -76,7 +94,7 @@ namespace Ryujinx.Core.OsHle
throw new NotImplementedException(Name);
}
- Services.Add(Name, Service);
+ Services.Add(LookUpName, Service);
}
return Service;
diff --git a/Ryujinx.Core/OsHle/Services/Aud/AudioOutData.cs b/Ryujinx.Core/OsHle/Services/Aud/AudioOutData.cs
new file mode 100644
index 00000000..6b27f529
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/Aud/AudioOutData.cs
@@ -0,0 +1,14 @@
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.Core.OsHle.IpcServices.Aud
+{
+ [StructLayout(LayoutKind.Sequential)]
+ struct AudioOutData
+ {
+ public long NextBufferPtr;
+ public long SampleBufferPtr;
+ public long SampleBufferCapacity;
+ public long SampleBufferSize;
+ public long SampleBufferInnerOffset;
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/Aud/IAudioDevice.cs b/Ryujinx.Core/OsHle/Services/Aud/IAudioDevice.cs
index 9ebf140a..863c9a27 100644
--- a/Ryujinx.Core/OsHle/Services/Aud/IAudioDevice.cs
+++ b/Ryujinx.Core/OsHle/Services/Aud/IAudioDevice.cs
@@ -55,7 +55,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud
long Position = Context.Request.SendBuff[0].Position;
long Size = Context.Request.SendBuff[0].Size;
- string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position, (int)Size);
+ string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position, Size);
return 0;
}
diff --git a/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs b/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs
index 2312920f..d0528a6d 100644
--- a/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs
+++ b/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs
@@ -1,11 +1,9 @@
using ChocolArm64.Memory;
+using Ryujinx.Audio;
using Ryujinx.Core.OsHle.Handles;
using Ryujinx.Core.OsHle.Ipc;
-using OpenTK.Audio;
-using OpenTK.Audio.OpenAL;
using System;
using System.Collections.Generic;
-using System.IO;
namespace Ryujinx.Core.OsHle.IpcServices.Aud
{
@@ -15,124 +13,64 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
- public IAudioOut()
+ private IAalOutput AudioOut;
+
+ private int Track;
+
+ public IAudioOut(IAalOutput AudioOut, int Track)
{
m_Commands = new Dictionary<int, ServiceProcessRequest>()
{
- { 0, GetAudioOutState },
- { 1, StartAudioOut },
- { 2, StopAudioOut },
- { 3, AppendAudioOutBuffer },
- { 4, RegisterBufferEvent },
- { 5, GetReleasedAudioOutBuffer },
- { 6, ContainsAudioOutBuffer },
- { 7, AppendAudioOutBuffer_ex },
- { 8, GetReleasedAudioOutBuffer_ex }
+ { 0, GetAudioOutState },
+ { 1, StartAudioOut },
+ { 2, StopAudioOut },
+ { 3, AppendAudioOutBuffer },
+ { 4, RegisterBufferEvent },
+ { 5, GetReleasedAudioOutBuffer },
+ { 6, ContainsAudioOutBuffer },
+ { 7, AppendAudioOutBufferEx },
+ { 8, GetReleasedAudioOutBufferEx }
};
- }
-
- enum AudioOutState
- {
- Started,
- Stopped
- };
- //IAudioOut
- private AudioOutState State = AudioOutState.Stopped;
- private Queue<long> BufferIdQueue = new Queue<long>();
-
- //OpenAL
- private bool OpenALInstalled = true;
- private AudioContext AudioCtx;
- private int Source;
- private int Buffer;
+ this.AudioOut = AudioOut;
+ this.Track = Track;
+ }
- //Return State of IAudioOut
public long GetAudioOutState(ServiceCtx Context)
{
- Context.ResponseData.Write((int)State);
+ Context.ResponseData.Write((int)AudioOut.GetState(Track));
return 0;
}
public long StartAudioOut(ServiceCtx Context)
{
- if (State == AudioOutState.Stopped)
- {
- State = AudioOutState.Started;
-
- try
- {
- AudioCtx = new AudioContext(); //Create the audio context
- }
- catch (Exception)
- {
- Logging.Warn("OpenAL Error! PS: Install OpenAL Core SDK!");
- OpenALInstalled = false;
- }
-
- if (OpenALInstalled) AL.Listener(ALListenerf.Gain, 8.0f); //Add more gain to it
- }
+ AudioOut.Start(Track);
return 0;
}
public long StopAudioOut(ServiceCtx Context)
{
- if (State == AudioOutState.Started)
- {
- if (OpenALInstalled)
- {
- if (AudioCtx == null) //Needed to call the instance of AudioContext()
- return 0;
-
- AL.SourceStop(Source);
- AL.DeleteSource(Source);
- AL.DeleteBuffers(1, ref Buffer);
- }
- State = AudioOutState.Stopped;
- }
+ AudioOut.Stop(Track);
return 0;
}
public long AppendAudioOutBuffer(ServiceCtx Context)
{
- long BufferId = Context.RequestData.ReadInt64();
+ long Tag = Context.RequestData.ReadInt64();
- byte[] AudioOutBuffer = AMemoryHelper.ReadBytes(Context.Memory, Context.Request.SendBuff[0].Position, sizeof(long) * 5);
+ AudioOutData Data = AMemoryHelper.Read<AudioOutData>(
+ Context.Memory,
+ Context.Request.SendBuff[0].Position);
+
+ byte[] Buffer = AMemoryHelper.ReadBytes(
+ Context.Memory,
+ Data.SampleBufferPtr,
+ Data.SampleBufferSize);
- using (MemoryStream MS = new MemoryStream(AudioOutBuffer))
- {
- BinaryReader Reader = new BinaryReader(MS);
- long PointerNextBuffer = Reader.ReadInt64();
- long PointerSampleBuffer = Reader.ReadInt64();
- long CapacitySampleBuffer = Reader.ReadInt64();
- long SizeDataInSampleBuffer = Reader.ReadInt64();
- long OffsetDataInSampleBuffer = Reader.ReadInt64();
-
- if (SizeDataInSampleBuffer > 0)
- {
- BufferIdQueue.Enqueue(BufferId);
-
- byte[] AudioSampleBuffer = AMemoryHelper.ReadBytes(Context.Memory, PointerSampleBuffer + OffsetDataInSampleBuffer, (int)SizeDataInSampleBuffer);
-
- if (OpenALInstalled)
- {
- if (AudioCtx == null) //Needed to call the instance of AudioContext()
- return 0;
-
- EnsureAudioFinalized();
-
- Source = AL.GenSource();
- Buffer = AL.GenBuffer();
-
- AL.BufferData(Buffer, ALFormat.Stereo16, AudioSampleBuffer, AudioSampleBuffer.Length, 48000);
- AL.SourceQueueBuffer(Source, Buffer);
- AL.SourcePlay(Source);
- }
- }
- }
+ AudioOut.AppendBuffer(Track, Tag, Buffer);
return 0;
}
@@ -148,50 +86,51 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud
public long GetReleasedAudioOutBuffer(ServiceCtx Context)
{
- int ReleasedBuffersCount = 0;
+ long Position = Context.Request.ReceiveBuff[0].Position;
+ long Size = Context.Request.ReceiveBuff[0].Size;
+
+ uint Count = (uint)((ulong)Size >> 3);
- for(int i = 0; i < BufferIdQueue.Count; i++)
+ long[] ReleasedBuffers = AudioOut.GetReleasedBuffers(Track);
+
+ for (uint Index = 0; Index < Count; Index++)
{
- long BufferId = BufferIdQueue.Dequeue();
+ long Tag = 0;
- AMemoryHelper.WriteBytes(Context.Memory, Context.Request.ReceiveBuff[0].Position + (8 * i), BitConverter.GetBytes(BufferId));
+ if (Index < ReleasedBuffers.Length)
+ {
+ Tag = ReleasedBuffers[Index];
+ }
- ReleasedBuffersCount++;
+ Context.Memory.WriteInt64(Position + Index * 8, Tag);
}
- Context.ResponseData.Write(ReleasedBuffersCount);
+ Context.ResponseData.Write(ReleasedBuffers.Length);
return 0;
}
public long ContainsAudioOutBuffer(ServiceCtx Context)
{
- return 0;
- }
+ long Tag = Context.RequestData.ReadInt64();
+
+ Context.ResponseData.Write(AudioOut.ContainsBuffer(Track, Tag) ? 1 : 0);
- public long AppendAudioOutBuffer_ex(ServiceCtx Context)
- {
return 0;
}
- public long GetReleasedAudioOutBuffer_ex(ServiceCtx Context)
+ public long AppendAudioOutBufferEx(ServiceCtx Context)
{
+ Logging.Warn("Not implemented!");
+
return 0;
}
- private void EnsureAudioFinalized()
+ public long GetReleasedAudioOutBufferEx(ServiceCtx Context)
{
- if (Source != 0 ||
- Buffer != 0)
- {
- AL.SourceStop(Source);
- AL.SourceUnqueueBuffer(Buffer);
- AL.DeleteSource(Source);
- AL.DeleteBuffers(1, ref Buffer);
+ Logging.Warn("Not implemented!");
- Source = 0;
- Buffer = 0;
- }
+ return 0;
}
public void Dispose()
@@ -199,11 +138,11 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud
Dispose(true);
}
- protected virtual void Dispose(bool disposing)
+ protected virtual void Dispose(bool Disposing)
{
- if (disposing)
+ if (Disposing)
{
- EnsureAudioFinalized();
+ AudioOut.CloseTrack(Track);
}
}
}
diff --git a/Ryujinx.Core/OsHle/Services/Aud/ServiceAudOut.cs b/Ryujinx.Core/OsHle/Services/Aud/ServiceAudOut.cs
index eb923562..19f23d1c 100644
--- a/Ryujinx.Core/OsHle/Services/Aud/ServiceAudOut.cs
+++ b/Ryujinx.Core/OsHle/Services/Aud/ServiceAudOut.cs
@@ -1,4 +1,5 @@
using ChocolArm64.Memory;
+using Ryujinx.Audio;
using Ryujinx.Core.OsHle.Ipc;
using System.Collections.Generic;
using System.Text;
@@ -18,7 +19,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud
m_Commands = new Dictionary<int, ServiceProcessRequest>()
{
{ 0, ListAudioOuts },
- { 1, OpenAudioOut },
+ { 1, OpenAudioOut }
};
}
@@ -35,21 +36,51 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud
public long OpenAudioOut(ServiceCtx Context)
{
- MakeObject(Context, new IAudioOut());
-
- Context.ResponseData.Write(48000); //Sample Rate
- Context.ResponseData.Write(2); //Channel Count
- Context.ResponseData.Write(2); //PCM Format
- /*
- 0 - Invalid
- 1 - INT8
- 2 - INT16
- 3 - INT24
- 4 - INT32
- 5 - PCM Float
- 6 - ADPCM
- */
- Context.ResponseData.Write(0); //Unknown
+ IAalOutput AudioOut = Context.Ns.AudioOut;
+
+ string DeviceName = AMemoryHelper.ReadAsciiString(
+ Context.Memory,
+ Context.Request.SendBuff[0].Position,
+ Context.Request.SendBuff[0].Size);
+
+ if (DeviceName == string.Empty)
+ {
+ DeviceName = "FIXME";
+ }
+
+ long DeviceNamePosition = Context.Request.ReceiveBuff[0].Position;
+ long DeviceNameSize = Context.Request.ReceiveBuff[0].Size;
+
+ byte[] DeviceNameBuffer = Encoding.ASCII.GetBytes(DeviceName);
+
+ if (DeviceName.Length <= DeviceNameSize)
+ {
+ AMemoryHelper.WriteBytes(Context.Memory, DeviceNamePosition, DeviceNameBuffer);
+ }
+
+ int SampleRate = Context.RequestData.ReadInt32();
+ int Channels = Context.RequestData.ReadInt32();
+
+ Channels = (ushort)(Channels >> 16);
+
+ if (SampleRate == 0)
+ {
+ SampleRate = 48000;
+ }
+
+ if (Channels < 1 || Channels > 2)
+ {
+ Channels = 2;
+ }
+
+ int Track = AudioOut.OpenTrack(SampleRate, Channels, out AudioFormat Format);
+
+ MakeObject(Context, new IAudioOut(AudioOut, Track));
+
+ Context.ResponseData.Write(SampleRate);
+ Context.ResponseData.Write(Channels);
+ Context.ResponseData.Write((int)Format);
+ Context.ResponseData.Write((int)PlaybackState.Stopped);
return 0;
}
diff --git a/Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs b/Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs
index da1e51e1..680e8405 100644
--- a/Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs
+++ b/Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs
@@ -151,7 +151,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Bsd
byte[] SentBuffer = AMemoryHelper.ReadBytes(Context.Memory,
Context.Request.SendBuff[0].Position,
- (int)Context.Request.SendBuff[0].Size);
+ Context.Request.SendBuff[0].Size);
int SocketId = Get32(SentBuffer, 0);
short RequestedEvents = (short)Get16(SentBuffer, 4);
short ReturnedEvents = (short)Get16(SentBuffer, 6);
@@ -197,7 +197,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Bsd
int SocketFlags = Context.RequestData.ReadInt32();
byte[] SentBuffer = AMemoryHelper.ReadBytes(Context.Memory,
Context.Request.SendBuff[0].Position,
- (int)Context.Request.SendBuff[0].Size);
+ Context.Request.SendBuff[0].Size);
try
{
@@ -224,10 +224,10 @@ namespace Ryujinx.Core.OsHle.IpcServices.Bsd
int SocketFlags = Context.RequestData.ReadInt32();
byte[] SentBuffer = AMemoryHelper.ReadBytes(Context.Memory,
Context.Request.SendBuff[0].Position,
- (int)Context.Request.SendBuff[0].Size);
+ Context.Request.SendBuff[0].Size);
byte[] AddressBuffer = AMemoryHelper.ReadBytes(Context.Memory,
Context.Request.SendBuff[1].Position,
- (int)Context.Request.SendBuff[1].Size);
+ Context.Request.SendBuff[1].Size);
if (!Sockets[SocketId].Handle.Connected)
{
@@ -333,7 +333,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Bsd
byte[] AddressBuffer = AMemoryHelper.ReadBytes(Context.Memory,
Context.Request.SendBuff[0].Position,
- (int)Context.Request.SendBuff[0].Size);
+ Context.Request.SendBuff[0].Size);
try
{
@@ -358,7 +358,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Bsd
byte[] AddressBuffer = AMemoryHelper.ReadBytes(Context.Memory,
Context.Request.SendBuff[0].Position,
- (int)Context.Request.SendBuff[0].Size);
+ Context.Request.SendBuff[0].Size);
try
{
diff --git a/Ryujinx.Core/OsHle/Services/FspSrv/IFile.cs b/Ryujinx.Core/OsHle/Services/FspSrv/IFile.cs
index ac2100f2..b9973061 100644
--- a/Ryujinx.Core/OsHle/Services/FspSrv/IFile.cs
+++ b/Ryujinx.Core/OsHle/Services/FspSrv/IFile.cs
@@ -62,7 +62,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv
long Offset = Context.RequestData.ReadInt64();
long Size = Context.RequestData.ReadInt64();
- byte[] Data = AMemoryHelper.ReadBytes(Context.Memory, Position, (int)Size);
+ byte[] Data = AMemoryHelper.ReadBytes(Context.Memory, Position, Size);
BaseStream.Seek(Offset, SeekOrigin.Begin);
BaseStream.Write(Data, 0, (int)Size);
diff --git a/Ryujinx.Core/OsHle/Services/Lm/ILogger.cs b/Ryujinx.Core/OsHle/Services/Lm/ILogger.cs
index 5ee097b6..8ef9f3c6 100644
--- a/Ryujinx.Core/OsHle/Services/Lm/ILogger.cs
+++ b/Ryujinx.Core/OsHle/Services/Lm/ILogger.cs
@@ -54,7 +54,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Lm
long BufferPosition = Context.Request.PtrBuff[0].Position;
long BufferLen = Context.Request.PtrBuff[0].Size;
- byte[] LogBuffer = AMemoryHelper.ReadBytes(Context.Memory, BufferPosition, (int)BufferLen);
+ byte[] LogBuffer = AMemoryHelper.ReadBytes(Context.Memory, BufferPosition, BufferLen);
MemoryStream LogMessage = new MemoryStream(LogBuffer);
BinaryReader bReader = new BinaryReader(LogMessage);
diff --git a/Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs b/Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs
index b24a773b..beccbe7d 100644
--- a/Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs
+++ b/Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs
@@ -35,7 +35,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
long DataPos = Context.Request.SendBuff[0].Position;
long DataSize = Context.Request.SendBuff[0].Size;
- byte[] Data = AMemoryHelper.ReadBytes(Context.Memory, DataPos, (int)DataSize);
+ byte[] Data = AMemoryHelper.ReadBytes(Context.Memory, DataPos, DataSize);
Data = Parcel.GetParcelData(Data);
@@ -66,9 +66,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
Dispose(true);
}
- protected virtual void Dispose(bool disposing)
+ protected virtual void Dispose(bool Disposing)
{
- if (disposing)
+ if (Disposing)
{
Flinger.Dispose();
}
diff --git a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs
index 671a32d3..9417473c 100644
--- a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs
+++ b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs
@@ -118,7 +118,7 @@ namespace Ryujinx.Core.OsHle.Svc
Process.Scheduler.Suspend(CurrThread.ProcessorId);
- byte[] CmdData = AMemoryHelper.ReadBytes(Memory, CmdPtr, (int)Size);
+ byte[] CmdData = AMemoryHelper.ReadBytes(Memory, CmdPtr, Size);
HSession Session = Process.HandleTable.GetData<HSession>(Handle);
@@ -136,7 +136,7 @@ namespace Ryujinx.Core.OsHle.Svc
CmdPtr,
Handle);
- byte[] Response = AMemoryHelper.ReadBytes(Memory, CmdPtr, (int)Size);
+ byte[] Response = AMemoryHelper.ReadBytes(Memory, CmdPtr, Size);
ThreadState.X0 = 0;
}
@@ -164,7 +164,7 @@ namespace Ryujinx.Core.OsHle.Svc
long Position = (long)ThreadState.X0;
long Size = (long)ThreadState.X1;
- string Str = AMemoryHelper.ReadAsciiString(Memory, Position, (int)Size);
+ string Str = AMemoryHelper.ReadAsciiString(Memory, Position, Size);
Logging.Info($"SvcOutputDebugString: {Str}");
diff --git a/Ryujinx.Core/Ryujinx.Core.csproj b/Ryujinx.Core/Ryujinx.Core.csproj
index 7d5ad718..b9374af1 100644
--- a/Ryujinx.Core/Ryujinx.Core.csproj
+++ b/Ryujinx.Core/Ryujinx.Core.csproj
@@ -14,6 +14,7 @@
<ItemGroup>
<ProjectReference Include="..\ChocolArm64\ChocolArm64.csproj" />
+ <ProjectReference Include="..\Ryujinx.Audio\Ryujinx.Audio.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics\Ryujinx.Graphics.csproj" />
</ItemGroup>
diff --git a/Ryujinx.Core/Settings/SetSys.cs b/Ryujinx.Core/Settings/SystemSettings.cs
index d8b6eb6e..0f56ef3a 100644
--- a/Ryujinx.Core/Settings/SetSys.cs
+++ b/Ryujinx.Core/Settings/SystemSettings.cs
@@ -1,6 +1,6 @@
namespace Ryujinx.Core.Settings
{
- public class SetSys
+ public class SystemSettings
{
public ColorSet ThemeColor;
}
diff --git a/Ryujinx.Core/Switch.cs b/Ryujinx.Core/Switch.cs
index 487f3bdb..92d78f45 100644
--- a/Ryujinx.Core/Switch.cs
+++ b/Ryujinx.Core/Switch.cs
@@ -1,3 +1,4 @@
+using Ryujinx.Audio;
using Ryujinx.Core.Input;
using Ryujinx.Core.OsHle;
using Ryujinx.Core.Settings;
@@ -9,32 +10,50 @@ namespace Ryujinx.Core
{
public class Switch : IDisposable
{
- internal NsGpu Gpu { get; private set; }
- internal Horizon Os { get; private set; }
- internal VirtualFs VFs { get; private set; }
+ internal IAalOutput AudioOut { get; private set; }
+
+ internal NsGpu Gpu { get; private set; }
+
+ internal Horizon Os { get; private set; }
+
+ internal VirtualFileSystem VFs { get; private set; }
+
+ public SystemSettings Settings { get; private set; }
- public Hid Hid { get; private set; }
- public SetSys Settings { get; private set; }
public PerformanceStatistics Statistics { get; private set; }
+ public Hid Hid { get; private set; }
+
public event EventHandler Finish;
- public Switch(IGalRenderer Renderer)
+ public Switch(IGalRenderer Renderer, IAalOutput AudioOut)
{
+ if (Renderer == null)
+ {
+ throw new ArgumentNullException(nameof(Renderer));
+ }
+
+ if (AudioOut == null)
+ {
+ throw new ArgumentNullException(nameof(AudioOut));
+ }
+
+ this.AudioOut = AudioOut;
+
Gpu = new NsGpu(Renderer);
- VFs = new VirtualFs();
+ Os = new Horizon(this);
- Hid = new Hid();
+ VFs = new VirtualFileSystem();
+
+ Settings = new SystemSettings();
Statistics = new PerformanceStatistics();
- Os = new Horizon(this);
+ Hid = new Hid();
Os.HidSharedMem.MemoryMapped += Hid.ShMemMap;
Os.HidSharedMem.MemoryUnmapped += Hid.ShMemUnmap;
-
- Settings = new SetSys();
}
public void LoadCart(string ExeFsDir, string RomFsFile = null)
diff --git a/Ryujinx.Core/VirtualFs.cs b/Ryujinx.Core/VirtualFileSystem.cs
index c0858e0e..1c717b2c 100644
--- a/Ryujinx.Core/VirtualFs.cs
+++ b/Ryujinx.Core/VirtualFileSystem.cs
@@ -3,7 +3,7 @@ using System.IO;
namespace Ryujinx.Core
{
- class VirtualFs : IDisposable
+ class VirtualFileSystem : IDisposable
{
private const string BasePath = "RyuFs";
private const string NandPath = "nand";
diff --git a/Ryujinx.Graphics/Gpu/NsGpuPGraph.cs b/Ryujinx.Graphics/Gpu/NsGpuPGraph.cs
index eb893f74..6543b1d1 100644
--- a/Ryujinx.Graphics/Gpu/NsGpuPGraph.cs
+++ b/Ryujinx.Graphics/Gpu/NsGpuPGraph.cs
@@ -117,7 +117,7 @@ namespace Ryujinx.Graphics.Gpu
if (Position != -1)
{
- byte[] Buffer = AMemoryHelper.ReadBytes(Memory, Position, (int)Size);
+ byte[] Buffer = AMemoryHelper.ReadBytes(Memory, Position, Size);
int Stride = GetRegister(NsGpuRegister._3dVertexArray0Fetch) & 0xfff;
diff --git a/Ryujinx/Ryujinx.csproj b/Ryujinx/Ryujinx.csproj
index bc5dbe04..f2d9cafe 100644
--- a/Ryujinx/Ryujinx.csproj
+++ b/Ryujinx/Ryujinx.csproj
@@ -11,6 +11,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ChocolArm64\ChocolArm64.csproj" />
+ <ProjectReference Include="..\Ryujinx.Audio\Ryujinx.Audio.csproj" />
<ProjectReference Include="..\Ryujinx.Core\Ryujinx.Core.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics\Ryujinx.Graphics.csproj" />
</ItemGroup>
diff --git a/Ryujinx/Ui/Program.cs b/Ryujinx/Ui/Program.cs
index b67e52bd..062e8bad 100644
--- a/Ryujinx/Ui/Program.cs
+++ b/Ryujinx/Ui/Program.cs
@@ -1,4 +1,6 @@
-using Ryujinx.Core;
+using Ryujinx.Audio;
+using Ryujinx.Audio.OpenAL;
+using Ryujinx.Core;
using Ryujinx.Graphics.Gal;
using Ryujinx.Graphics.Gal.OpenGL;
using System;
@@ -18,7 +20,9 @@ namespace Ryujinx
IGalRenderer Renderer = new OpenGLRenderer();
- Switch Ns = new Switch(Renderer);
+ IAalOutput AudioOut = new OpenALAudioOut();
+
+ Switch Ns = new Switch(Renderer, AudioOut);
if (args.Length == 1)
{