DeviceMemory.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. using ARMeilleure.Memory;
  2. using System;
  3. using System.Runtime.InteropServices;
  4. namespace Ryujinx.HLE
  5. {
  6. class DeviceMemory : IDisposable
  7. {
  8. public const long RamSize = 4L * 1024 * 1024 * 1024;
  9. public IntPtr RamPointer { get; }
  10. private unsafe byte* _ramPtr;
  11. public unsafe DeviceMemory()
  12. {
  13. RamPointer = MemoryManagement.AllocateWriteTracked(RamSize);
  14. _ramPtr = (byte*)RamPointer;
  15. }
  16. public sbyte ReadSByte(long position)
  17. {
  18. return (sbyte)ReadByte(position);
  19. }
  20. public short ReadInt16(long position)
  21. {
  22. return (short)ReadUInt16(position);
  23. }
  24. public int ReadInt32(long position)
  25. {
  26. return (int)ReadUInt32(position);
  27. }
  28. public long ReadInt64(long position)
  29. {
  30. return (long)ReadUInt64(position);
  31. }
  32. public unsafe byte ReadByte(long position)
  33. {
  34. return *(_ramPtr + position);
  35. }
  36. public unsafe ushort ReadUInt16(long position)
  37. {
  38. return *((ushort*)(_ramPtr + position));
  39. }
  40. public unsafe uint ReadUInt32(long position)
  41. {
  42. return *((uint*)(_ramPtr + position));
  43. }
  44. public unsafe ulong ReadUInt64(long position)
  45. {
  46. return *((ulong*)(_ramPtr + position));
  47. }
  48. public unsafe T ReadStruct<T>(long position)
  49. {
  50. return Marshal.PtrToStructure<T>((IntPtr)(_ramPtr + position));
  51. }
  52. public void WriteSByte(long position, sbyte value)
  53. {
  54. WriteByte(position, (byte)value);
  55. }
  56. public void WriteInt16(long position, short value)
  57. {
  58. WriteUInt16(position, (ushort)value);
  59. }
  60. public void WriteInt32(long position, int value)
  61. {
  62. WriteUInt32(position, (uint)value);
  63. }
  64. public void WriteInt64(long position, long value)
  65. {
  66. WriteUInt64(position, (ulong)value);
  67. }
  68. public unsafe void WriteByte(long position, byte value)
  69. {
  70. *(_ramPtr + position) = value;
  71. }
  72. public unsafe void WriteUInt16(long position, ushort value)
  73. {
  74. *((ushort*)(_ramPtr + position)) = value;
  75. }
  76. public unsafe void WriteUInt32(long position, uint value)
  77. {
  78. *((uint*)(_ramPtr + position)) = value;
  79. }
  80. public unsafe void WriteUInt64(long position, ulong value)
  81. {
  82. *((ulong*)(_ramPtr + position)) = value;
  83. }
  84. public unsafe void WriteStruct<T>(long position, T value)
  85. {
  86. Marshal.StructureToPtr(value, (IntPtr)(_ramPtr + position), false);
  87. }
  88. public void FillWithZeros(long position, int size)
  89. {
  90. int size8 = size & ~(8 - 1);
  91. for (int offs = 0; offs < size8; offs += 8)
  92. {
  93. WriteInt64(position + offs, 0);
  94. }
  95. for (int offs = size8; offs < (size - size8); offs++)
  96. {
  97. WriteByte(position + offs, 0);
  98. }
  99. }
  100. public void Set(ulong address, byte value, ulong size)
  101. {
  102. if (address + size < address)
  103. {
  104. throw new ArgumentOutOfRangeException(nameof(size));
  105. }
  106. if (address + size > RamSize)
  107. {
  108. throw new ArgumentOutOfRangeException(nameof(address));
  109. }
  110. ulong size8 = size & ~7UL;
  111. ulong valueRep = (ulong)value * 0x0101010101010101;
  112. for (ulong offs = 0; offs < size8; offs += 8)
  113. {
  114. WriteUInt64((long)(address + offs), valueRep);
  115. }
  116. for (ulong offs = size8; offs < (size - size8); offs++)
  117. {
  118. WriteByte((long)(address + offs), value);
  119. }
  120. }
  121. public void Copy(ulong dst, ulong src, ulong size)
  122. {
  123. if (dst + size < dst || src + size < src)
  124. {
  125. throw new ArgumentOutOfRangeException(nameof(size));
  126. }
  127. if (dst + size > RamSize)
  128. {
  129. throw new ArgumentOutOfRangeException(nameof(dst));
  130. }
  131. if (src + size > RamSize)
  132. {
  133. throw new ArgumentOutOfRangeException(nameof(src));
  134. }
  135. ulong size8 = size & ~7UL;
  136. for (ulong offs = 0; offs < size8; offs += 8)
  137. {
  138. WriteUInt64((long)(dst + offs), ReadUInt64((long)(src + offs)));
  139. }
  140. for (ulong offs = size8; offs < (size - size8); offs++)
  141. {
  142. WriteByte((long)(dst + offs), ReadByte((long)(src + offs)));
  143. }
  144. }
  145. public void Dispose()
  146. {
  147. Dispose(true);
  148. }
  149. protected virtual void Dispose(bool disposing)
  150. {
  151. MemoryManagement.Free(RamPointer);
  152. }
  153. }
  154. }