Allow changing CPU emulators with a config entry

This commit is contained in:
gdkchan 2019-08-01 17:55:27 -03:00
commit 15dc188dc4
23 changed files with 167 additions and 54 deletions

View file

@ -0,0 +1,42 @@
using ARMeilleure.State;
using System;
namespace ARMeilleure.Memory
{
public interface IMemoryManager : IMemory, IDisposable
{
void Map(long va, long pa, long size);
void Unmap(long position, long size);
bool IsMapped(long position);
long GetPhysicalAddress(long virtualAddress);
bool IsRegionModified(long position, long size);
bool TryGetHostAddress(long position, long size, out IntPtr ptr);
bool IsValidPosition(long position);
bool AtomicCompareExchangeInt32(long position, int expected, int desired);
int AtomicIncrementInt32(long position);
int AtomicDecrementInt32(long position);
V128 ReadVector128(long position);
byte[] ReadBytes(long position, long size);
void ReadBytes(long position, byte[] data, int startIndex, int size);
void WriteVector128(long position, V128 value);
void WriteBytes(long position, byte[] data);
void WriteBytes(long position, byte[] data, int startIndex, int size);
void CopyBytes(long src, long dst, long size);
}
}

View file

@ -7,7 +7,7 @@ namespace ARMeilleure.Memory
{ {
public static class MemoryHelper public static class MemoryHelper
{ {
public static void FillWithZeros(MemoryManager memory, long position, int size) public static void FillWithZeros(IMemoryManager memory, long position, int size)
{ {
int size8 = size & ~(8 - 1); int size8 = size & ~(8 - 1);
@ -22,7 +22,7 @@ namespace ARMeilleure.Memory
} }
} }
public unsafe static T Read<T>(MemoryManager memory, long position) where T : struct public unsafe static T Read<T>(IMemoryManager memory, long position) where T : struct
{ {
long size = Marshal.SizeOf<T>(); long size = Marshal.SizeOf<T>();
@ -34,7 +34,7 @@ namespace ARMeilleure.Memory
} }
} }
public unsafe static void Write<T>(MemoryManager memory, long position, T value) where T : struct public unsafe static void Write<T>(IMemoryManager memory, long position, T value) where T : struct
{ {
long size = Marshal.SizeOf<T>(); long size = Marshal.SizeOf<T>();
@ -48,7 +48,7 @@ namespace ARMeilleure.Memory
memory.WriteBytes(position, data); memory.WriteBytes(position, data);
} }
public static string ReadAsciiString(MemoryManager memory, long position, long maxSize = -1) public static string ReadAsciiString(IMemoryManager memory, long position, long maxSize = -1)
{ {
using (MemoryStream ms = new MemoryStream()) using (MemoryStream ms = new MemoryStream())
{ {

View file

@ -7,7 +7,7 @@ using static ARMeilleure.Memory.MemoryManagement;
namespace ARMeilleure.Memory namespace ARMeilleure.Memory
{ {
public unsafe class MemoryManager : IMemory, IDisposable public unsafe class MemoryManager : IMemoryManager
{ {
public const int PageBits = 12; public const int PageBits = 12;
public const int PageSize = 1 << PageBits; public const int PageSize = 1 << PageBits;

View file

@ -3,7 +3,7 @@ using System.Diagnostics;
namespace ARMeilleure.State namespace ARMeilleure.State
{ {
public class ExecutionContext : IDisposable public class ExecutionContext : IExecutionContext
{ {
private const int MinCountForCheck = 40000; private const int MinCountForCheck = 40000;
@ -90,7 +90,7 @@ namespace ARMeilleure.State
public bool GetPstateFlag(PState flag) => _nativeContext.GetPstateFlag(flag); public bool GetPstateFlag(PState flag) => _nativeContext.GetPstateFlag(flag);
public void SetPstateFlag(PState flag, bool value) => _nativeContext.SetPstateFlag(flag, value); public void SetPstateFlag(PState flag, bool value) => _nativeContext.SetPstateFlag(flag, value);
public void CheckInterrupt() internal void CheckInterrupt()
{ {
if (_interrupted) if (_interrupted)
{ {

View file

@ -0,0 +1,39 @@
using System;
namespace ARMeilleure.State
{
public interface IExecutionContext : IDisposable
{
uint CtrEl0 { get; }
uint DczidEl0 { get; }
ulong CntfrqEl0 { get; set; }
ulong CntpctEl0 { get; }
long TpidrEl0 { get; set; }
long Tpidr { get; set; }
FPCR Fpcr { get; set; }
FPSR Fpsr { get; set; }
bool IsAarch32 { get; set; }
bool Running { get; set; }
event EventHandler<EventArgs> Interrupt;
event EventHandler<InstExceptionEventArgs> Break;
event EventHandler<InstExceptionEventArgs> SupervisorCall;
event EventHandler<InstUndefinedEventArgs> Undefined;
ulong GetX(int index);
void SetX(int index, ulong value);
V128 GetV(int index);
void SetV(int index, V128 value);
bool GetPstateFlag(PState flag);
void SetPstateFlag(PState flag, bool value);
void RequestInterrupt();
}
}

View file

@ -0,0 +1,9 @@
using ARMeilleure.State;
namespace ARMeilleure.Translation
{
public interface ITranslator
{
void Execute(IExecutionContext context, ulong address);
}
}

View file

@ -12,7 +12,7 @@ using static ARMeilleure.IntermediateRepresentation.OperandHelper;
namespace ARMeilleure.Translation namespace ARMeilleure.Translation
{ {
public class Translator public class Translator : ITranslator
{ {
private const ulong CallFlag = InstEmitFlowHelper.CallFlag; private const ulong CallFlag = InstEmitFlowHelper.CallFlag;
@ -54,8 +54,10 @@ namespace ARMeilleure.Translation
} }
} }
public void Execute(State.ExecutionContext context, ulong address) public void Execute(IExecutionContext ctx, ulong address)
{ {
State.ExecutionContext context = (State.ExecutionContext)ctx;
if (Interlocked.Increment(ref _threadCount) == 1) if (Interlocked.Increment(ref _threadCount) == 1)
{ {
Thread backgroundTranslatorThread = new Thread(TranslateQueuedSubs); Thread backgroundTranslatorThread = new Thread(TranslateQueuedSubs);

View file

@ -8,7 +8,7 @@ namespace Ryujinx.HLE.HOS
public const string TemporaryNroSuffix = ".ryu_tmp.nro"; public const string TemporaryNroSuffix = ".ryu_tmp.nro";
// http://switchbrew.org/index.php?title=Homebrew_ABI // http://switchbrew.org/index.php?title=Homebrew_ABI
public static void WriteHbAbiData(MemoryManager memory, long position, int mainThreadHandle, string switchPath) public static void WriteHbAbiData(IMemoryManager memory, long position, int mainThreadHandle, string switchPath)
{ {
// MainThreadHandle. // MainThreadHandle.
WriteConfigEntry(memory, ref position, 1, 0, mainThreadHandle); WriteConfigEntry(memory, ref position, 1, 0, mainThreadHandle);
@ -31,7 +31,7 @@ namespace Ryujinx.HLE.HOS
} }
private static void WriteConfigEntry( private static void WriteConfigEntry(
MemoryManager memory, IMemoryManager memory,
ref long position, ref long position,
int key, int key,
int flags = 0, int flags = 0,
@ -46,7 +46,7 @@ namespace Ryujinx.HLE.HOS
position += 0x18; position += 0x18;
} }
public static string ReadHbAbiNextLoadPath(MemoryManager memory, long position) public static string ReadHbAbiNextLoadPath(IMemoryManager memory, long position)
{ {
string fileName = null; string fileName = null;

View file

@ -110,6 +110,8 @@ namespace Ryujinx.HLE.HOS
public int GlobalAccessLogMode { get; set; } public int GlobalAccessLogMode { get; set; }
public bool UseLegacyJit { get; set; }
internal long HidBaseAddress { get; private set; } internal long HidBaseAddress { get; private set; }
public Horizon(Switch device) public Horizon(Switch device)

View file

@ -13,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Ipc
public static KernelResult IpcCall( public static KernelResult IpcCall(
Switch device, Switch device,
KProcess process, KProcess process,
MemoryManager memory, IMemoryManager memory,
KThread thread, KThread thread,
KClientSession session, KClientSession session,
IpcMessage request, IpcMessage request,

View file

@ -29,7 +29,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
private LinkedList<KMemoryBlock> _blocks; private LinkedList<KMemoryBlock> _blocks;
private MemoryManager _cpuMemory; private IMemoryManager _cpuMemory;
private Horizon _system; private Horizon _system;
@ -72,7 +72,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
private MersenneTwister _randomNumberGenerator; private MersenneTwister _randomNumberGenerator;
public KMemoryManager(Horizon system, MemoryManager cpuMemory) public KMemoryManager(Horizon system, IMemoryManager cpuMemory)
{ {
_system = system; _system = system;
_cpuMemory = cpuMemory; _cpuMemory = cpuMemory;

View file

@ -1,4 +1,5 @@
using ARMeilleure.Memory; using ARMeilleure.Memory;
using ARMeilleure.State;
using Ryujinx.HLE.HOS.Diagnostics.Demangler; using Ryujinx.HLE.HOS.Diagnostics.Demangler;
using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.HOS.Kernel.Memory;
using Ryujinx.HLE.Loaders.Elf; using Ryujinx.HLE.Loaders.Elf;
@ -39,7 +40,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
_images = new List<Image>(); _images = new List<Image>();
} }
public string GetGuestStackTrace(ARMeilleure.State.ExecutionContext context) public string GetGuestStackTrace(IExecutionContext context)
{ {
EnsureLoaded(); EnsureLoaded();
@ -217,7 +218,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
} }
} }
private void LoadMod0Symbols(MemoryManager memory, long textOffset) private void LoadMod0Symbols(IMemoryManager memory, long textOffset)
{ {
long mod0Offset = textOffset + memory.ReadUInt32(textOffset + 4); long mod0Offset = textOffset + memory.ReadUInt32(textOffset + 4);
@ -287,7 +288,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
} }
} }
private ElfSymbol GetSymbol(MemoryManager memory, long address, long strTblAddr) private ElfSymbol GetSymbol(IMemoryManager memory, long address, long strTblAddr)
{ {
int nameIndex = memory.ReadInt32(address + 0); int nameIndex = memory.ReadInt32(address + 0);
int info = memory.ReadByte (address + 4); int info = memory.ReadByte (address + 4);

View file

@ -78,9 +78,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public bool IsPaused { get; private set; } public bool IsPaused { get; private set; }
public MemoryManager CpuMemory { get; private set; } public IMemoryManager CpuMemory { get; private set; }
public Translator Translator { get; private set; } public ITranslator Translator { get; private set; }
private SvcHandler _svcHandler; private SvcHandler _svcHandler;
@ -791,7 +791,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
} }
} }
public void SubscribeThreadEventHandlers(ARMeilleure.State.ExecutionContext context) public void SubscribeThreadEventHandlers(IExecutionContext context)
{ {
context.Interrupt += InterruptHandler; context.Interrupt += InterruptHandler;
context.SupervisorCall += _svcHandler.SvcCall; context.SupervisorCall += _svcHandler.SvcCall;
@ -1022,11 +1022,20 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
bool useFlatPageTable = memRegion == MemoryRegion.Application; bool useFlatPageTable = memRegion == MemoryRegion.Application;
if (_system.UseLegacyJit)
{
CpuMemory = new ChocolArm64.Memory.MemoryManager(_system.Device.Memory.RamPointer, addrSpaceBits, useFlatPageTable);
Translator = new ChocolArm64.Translation.Translator((ChocolArm64.Memory.MemoryManager)CpuMemory);
}
else
{
CpuMemory = new MemoryManager(_system.Device.Memory.RamPointer, addrSpaceBits, useFlatPageTable); CpuMemory = new MemoryManager(_system.Device.Memory.RamPointer, addrSpaceBits, useFlatPageTable);
MemoryManager = new KMemoryManager(_system, CpuMemory); Translator = new Translator((MemoryManager)CpuMemory);
}
Translator = new Translator(CpuMemory); MemoryManager = new KMemoryManager(_system, CpuMemory);
} }
public void PrintCurrentThreadStackTrace() public void PrintCurrentThreadStackTrace()

View file

@ -19,14 +19,14 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
public void SvcCall(object sender, InstExceptionEventArgs e) public void SvcCall(object sender, InstExceptionEventArgs e)
{ {
Action<SvcHandler, ExecutionContext> svcFunc = SvcTable.GetSvcFunc(e.Id); Action<SvcHandler, IExecutionContext> svcFunc = SvcTable.GetSvcFunc(e.Id);
if (svcFunc == null) if (svcFunc == null)
{ {
throw new NotImplementedException($"SVC 0x{e.Id:X4} is not implemented."); throw new NotImplementedException($"SVC 0x{e.Id:X4} is not implemented.");
} }
ExecutionContext context = (ExecutionContext)sender; IExecutionContext context = (IExecutionContext)sender;
svcFunc(this, context); svcFunc(this, context);
} }

View file

@ -14,7 +14,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
private static Dictionary<int, string> _svcFuncs64; private static Dictionary<int, string> _svcFuncs64;
private static Action<SvcHandler, ExecutionContext>[] _svcTable64; private static Action<SvcHandler, IExecutionContext>[] _svcTable64;
static SvcTable() static SvcTable()
{ {
@ -77,10 +77,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
{ 0x78, nameof(SvcHandler.UnmapProcessCodeMemory64) } { 0x78, nameof(SvcHandler.UnmapProcessCodeMemory64) }
}; };
_svcTable64 = new Action<SvcHandler, ExecutionContext>[0x80]; _svcTable64 = new Action<SvcHandler, IExecutionContext>[0x80];
} }
public static Action<SvcHandler, ExecutionContext> GetSvcFunc(int svcId) public static Action<SvcHandler, IExecutionContext> GetSvcFunc(int svcId)
{ {
if (_svcTable64[svcId] != null) if (_svcTable64[svcId] != null)
{ {
@ -95,9 +95,9 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return null; return null;
} }
private static Action<SvcHandler, ExecutionContext> GenerateMethod(string svcName) private static Action<SvcHandler, IExecutionContext> GenerateMethod(string svcName)
{ {
Type[] argTypes = new Type[] { typeof(SvcHandler), typeof(ExecutionContext) }; Type[] argTypes = new Type[] { typeof(SvcHandler), typeof(IExecutionContext) };
DynamicMethod method = new DynamicMethod(svcName, null, argTypes); DynamicMethod method = new DynamicMethod(svcName, null, argTypes);
@ -185,7 +185,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Ldarg_1);
generator.Emit(OpCodes.Ldc_I4, byRefArgsCount + index); generator.Emit(OpCodes.Ldc_I4, byRefArgsCount + index);
MethodInfo info = typeof(ExecutionContext).GetMethod(nameof(ExecutionContext.GetX)); MethodInfo info = typeof(IExecutionContext).GetMethod(nameof(IExecutionContext.GetX));
generator.Emit(OpCodes.Call, info); generator.Emit(OpCodes.Call, info);
@ -233,7 +233,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Ldarg_1);
generator.Emit(OpCodes.Ldc_I4, byRefArgsCount + index); generator.Emit(OpCodes.Ldc_I4, byRefArgsCount + index);
MethodInfo info = typeof(ExecutionContext).GetMethod(nameof(ExecutionContext.GetX)); MethodInfo info = typeof(IExecutionContext).GetMethod(nameof(IExecutionContext.GetX));
generator.Emit(OpCodes.Call, info); generator.Emit(OpCodes.Call, info);
@ -271,7 +271,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
ConvertToFieldType(retType); ConvertToFieldType(retType);
MethodInfo info = typeof(ExecutionContext).GetMethod(nameof(ExecutionContext.SetX)); MethodInfo info = typeof(IExecutionContext).GetMethod(nameof(IExecutionContext.SetX));
generator.Emit(OpCodes.Call, info); generator.Emit(OpCodes.Call, info);
} }
@ -284,7 +284,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
ConvertToFieldType(locals[index].LocalType); ConvertToFieldType(locals[index].LocalType);
MethodInfo info = typeof(ExecutionContext).GetMethod(nameof(ExecutionContext.SetX)); MethodInfo info = typeof(IExecutionContext).GetMethod(nameof(IExecutionContext.SetX));
generator.Emit(OpCodes.Call, info); generator.Emit(OpCodes.Call, info);
} }
@ -296,14 +296,14 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
generator.Emit(OpCodes.Ldc_I4, outRegIndex++); generator.Emit(OpCodes.Ldc_I4, outRegIndex++);
generator.Emit(OpCodes.Ldc_I8, 0L); generator.Emit(OpCodes.Ldc_I8, 0L);
MethodInfo info = typeof(ExecutionContext).GetMethod(nameof(ExecutionContext.SetX)); MethodInfo info = typeof(IExecutionContext).GetMethod(nameof(IExecutionContext.SetX));
generator.Emit(OpCodes.Call, info); generator.Emit(OpCodes.Call, info);
} }
generator.Emit(OpCodes.Ret); generator.Emit(OpCodes.Ret);
return (Action<SvcHandler, ExecutionContext>)method.CreateDelegate(typeof(Action<SvcHandler, ExecutionContext>)); return (Action<SvcHandler, IExecutionContext>)method.CreateDelegate(typeof(Action<SvcHandler, IExecutionContext>));
} }
private static void CheckIfTypeIsSupported(Type type, string svcName) private static void CheckIfTypeIsSupported(Type type, string svcName)

View file

@ -348,7 +348,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return KernelResult.InvalidThread; return KernelResult.InvalidThread;
} }
MemoryManager memory = currentProcess.CpuMemory; IMemoryManager memory = currentProcess.CpuMemory;
memory.WriteUInt64((long)address + 0x0, thread.Context.GetX(0)); memory.WriteUInt64((long)address + 0x0, thread.Context.GetX(0));
memory.WriteUInt64((long)address + 0x8, thread.Context.GetX(1)); memory.WriteUInt64((long)address + 0x8, thread.Context.GetX(1));
@ -427,7 +427,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return KernelResult.Success; return KernelResult.Success;
} }
private static int GetPsr(ExecutionContext context) private static int GetPsr(IExecutionContext context)
{ {
return (context.GetPstateFlag(PState.NFlag) ? (1 << 31) : 0) | return (context.GetPstateFlag(PState.NFlag) ? (1 << 31) : 0) |
(context.GetPstateFlag(PState.ZFlag) ? (1 << 30) : 0) | (context.GetPstateFlag(PState.ZFlag) ? (1 << 30) : 0) |

View file

@ -1,4 +1,5 @@
using ARMeilleure.Memory; using ARMeilleure.Memory;
using ARMeilleure.State;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Kernel.Process;
@ -16,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
public Thread HostThread { get; private set; } public Thread HostThread { get; private set; }
public ARMeilleure.State.ExecutionContext Context { get; private set; } public IExecutionContext Context { get; private set; }
public long AffinityMask { get; set; } public long AffinityMask { get; set; }
@ -158,7 +159,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
HostThread = new Thread(() => ThreadStart(entrypoint)); HostThread = new Thread(() => ThreadStart(entrypoint));
if (System.UseLegacyJit)
{
Context = new ChocolArm64.State.CpuThreadState();
}
else
{
Context = new ARMeilleure.State.ExecutionContext(); Context = new ARMeilleure.State.ExecutionContext();
}
bool isAarch32 = (Owner.MmuFlags & 1) == 0; bool isAarch32 = (Owner.MmuFlags & 1) == 0;

View file

@ -11,7 +11,7 @@ namespace Ryujinx.HLE.HOS
{ {
public Switch Device { get; } public Switch Device { get; }
public KProcess Process { get; } public KProcess Process { get; }
public MemoryManager Memory { get; } public IMemoryManager Memory { get; }
public KThread Thread { get; } public KThread Thread { get; }
public KClientSession Session { get; } public KClientSession Session { get; }
public IpcMessage Request { get; } public IpcMessage Request { get; }
@ -22,7 +22,7 @@ namespace Ryujinx.HLE.HOS
public ServiceCtx( public ServiceCtx(
Switch device, Switch device,
KProcess process, KProcess process,
MemoryManager memory, IMemoryManager memory,
KThread thread, KThread thread,
KClientSession session, KClientSession session,
IpcMessage request, IpcMessage request,

View file

@ -24,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
private KEvent _updateEvent; private KEvent _updateEvent;
private MemoryManager _memory; private IMemoryManager _memory;
private IAalOutput _audioOut; private IAalOutput _audioOut;
@ -40,7 +40,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
public IAudioRenderer( public IAudioRenderer(
Horizon system, Horizon system,
MemoryManager memory, IMemoryManager memory,
IAalOutput audioOut, IAalOutput audioOut,
AudioRendererParameter Params) AudioRendererParameter Params)
{ {

View file

@ -65,7 +65,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
_outStatus.VoiceDropsCount = 0; _outStatus.VoiceDropsCount = 0;
} }
public int[] GetBufferData(MemoryManager memory, int maxSamples, out int samplesCount) public int[] GetBufferData(IMemoryManager memory, int maxSamples, out int samplesCount)
{ {
if (!Playing) if (!Playing)
{ {
@ -122,7 +122,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
return output; return output;
} }
private void UpdateBuffer(MemoryManager memory) private void UpdateBuffer(IMemoryManager memory)
{ {
// TODO: Implement conversion for formats other // TODO: Implement conversion for formats other
// than interleaved stereo (2 channels). // than interleaved stereo (2 channels).

View file

@ -43,6 +43,7 @@
<ProjectReference Include="..\Ryujinx.Graphics\Ryujinx.Graphics.csproj" /> <ProjectReference Include="..\Ryujinx.Graphics\Ryujinx.Graphics.csproj" />
<ProjectReference Include="..\Ryujinx.Profiler\Ryujinx.Profiler.csproj" /> <ProjectReference Include="..\Ryujinx.Profiler\Ryujinx.Profiler.csproj" />
<ProjectReference Include="..\ARMeilleure\ARMeilleure.csproj" /> <ProjectReference Include="..\ARMeilleure\ARMeilleure.csproj" />
<ProjectReference Include="..\ChocolArm64\ChocolArm64.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -5,11 +5,11 @@ namespace Ryujinx.HLE.Utilities
{ {
class StructReader class StructReader
{ {
private MemoryManager _memory; private IMemoryManager _memory;
public long Position { get; private set; } public long Position { get; private set; }
public StructReader(MemoryManager memory, long position) public StructReader(IMemoryManager memory, long position)
{ {
_memory = memory; _memory = memory;
Position = position; Position = position;

View file

@ -5,11 +5,11 @@ namespace Ryujinx.HLE.Utilities
{ {
class StructWriter class StructWriter
{ {
private MemoryManager _memory; private IMemoryManager _memory;
public long Position { get; private set; } public long Position { get; private set; }
public StructWriter(MemoryManager memory, long position) public StructWriter(IMemoryManager memory, long position)
{ {
_memory = memory; _memory = memory;
Position = position; Position = position;