private (long, KThread) MutexUnlock(AMemory Memory, KThread CurrentThread, long MutexAddress) { KThread NewOwnerThread = CurrentThread.RelinquishMutex(MutexAddress, out int Count); int MutexValue = 0; if (NewOwnerThread != null) { MutexValue = NewOwnerThread.ThreadHandleForUserMutex; if (Count >= 2) { MutexValue |= HasListenersMask; } NewOwnerThread.SignaledObj = null; NewOwnerThread.ObjSyncResult = 0; NewOwnerThread.ReleaseAndResume(); } long Result = 0; if (!KernelToUserInt32(Memory, MutexAddress, MutexValue)) { Result = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); } return(Result, NewOwnerThread); }
public SvcHandler(Switch Ns, Process Process) { SvcFuncs = new Dictionary <int, SvcFunc>() { { 0x01, SvcSetHeapSize }, { 0x03, SvcSetMemoryAttribute }, { 0x04, SvcMapMemory }, { 0x06, SvcQueryMemory }, { 0x08, SvcCreateThread }, { 0x09, SvcStartThread }, { 0x0b, SvcSleepThread }, { 0x0c, SvcGetThreadPriority }, { 0x13, SvcMapSharedMemory }, { 0x14, SvcUnmapSharedMemory }, { 0x15, SvcCreateTransferMemory }, { 0x16, SvcCloseHandle }, { 0x17, SvcResetSignal }, { 0x18, SvcWaitSynchronization }, { 0x1a, SvcArbitrateLock }, { 0x1b, SvcArbitrateUnlock }, { 0x1c, SvcWaitProcessWideKeyAtomic }, { 0x1d, SvcSignalProcessWideKey }, { 0x1e, SvcGetSystemTick }, { 0x1f, SvcConnectToNamedPort }, { 0x21, SvcSendSyncRequest }, { 0x22, SvcSendSyncRequestWithUserBuffer }, { 0x26, SvcBreak }, { 0x27, SvcOutputDebugString }, { 0x29, SvcGetInfo } }; this.Ns = Ns; this.Process = Process; this.Memory = Process.Memory; }
private unsafe static void Write4Bpp(AMemory Memory, Texture Texture, byte[] Data) { int Width = Texture.Width; int Height = Texture.Height; ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 4); fixed(byte *BuffPtr = Data) { long InOffs = 0; for (int Y = 0; Y < Height; Y++) { for (int X = 0; X < Width; X++) { long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y); int Pixel = *(int *)(BuffPtr + InOffs); Memory.WriteInt32Unchecked(Texture.Position + Offset, Pixel); InOffs += 4; } } } }
public HTransferMem(AMemory Memory, AMemoryPerm Perm, long Position, long Size) { this.Memory = Memory; this.Perm = Perm; this.Position = Position; this.Size = Size; }
public void Setup() { Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize); Allocator = new AMemoryAlloc(); Memory = new AMemory(Ram, Allocator); Memory.Manager.MapPhys(0x1000, 0x1000, 2, AMemoryPerm.Read | AMemoryPerm.Write | AMemoryPerm.Execute); }
public static void Blx(AThreadState State, AMemory Memory, AOpCode OpCode, bool X) { A32OpCodeBImmAl Op = (A32OpCodeBImmAl)OpCode; if (IsConditionTrue(State, Op.Cond)) { uint Pc = GetPc(State); if (State.Thumb) { State.R14 = Pc | 1; } else { State.R14 = Pc - 4U; } if (X) { State.Thumb = !State.Thumb; } if (!State.Thumb) { Pc &= ~3U; } BranchWritePc(State, Pc + (uint)Op.Imm); } }
public bool IsRegionModified(AMemory Memory, NvGpuBufferType BufferType, long PA, long Size) { bool[] Modified = Memory.IsRegionModified(PA, Size); if (Modified == null) { return(true); } ClearCachedPagesIfNeeded(); long PageSize = Memory.GetHostPageSize(); long Mask = PageSize - 1; long PAEnd = PA + Size; bool RegMod = false; int Index = 0; while (PA < PAEnd) { long Key = PA & ~Mask; long PAPgEnd = Math.Min((PA + PageSize) & ~Mask, PAEnd); bool IsCached = Cache.TryGetValue(Key, out CachedPage Cp); if (IsCached) { CpCount -= Cp.GetTotalCount(); SortedCache.Remove(Cp.Node); } else { Cp = new CachedPage(); Cache.Add(Key, Cp); } if (Modified[Index++] && IsCached) { Cp = new CachedPage(); Cache[Key] = Cp; } Cp.Node = SortedCache.AddLast(Key); RegMod |= Cp.AddRange(PA, PAPgEnd, BufferType); CpCount += Cp.GetTotalCount(); PA = PAPgEnd; } return(RegMod); }
public Process(Switch Device, KProcessScheduler Scheduler, int ProcessId, Npdm MetaData) { this.Device = Device; this.Scheduler = Scheduler; this.MetaData = MetaData; this.ProcessId = ProcessId; Memory = new AMemory(Device.Memory.RamPointer); MemoryManager = new KMemoryManager(this); TlsPages = new List <KTlsPageManager>(); ThreadArbiterList = new List <KThread>(); ThreadSyncLock = new object(); HandleTable = new KProcessHandleTable(); AppletState = new AppletStateMgr(); SvcHandler = new SvcHandler(Device, this); Threads = new ConcurrentDictionary <long, KThread>(); Executables = new List <Executable>(); ImageBase = MemoryManager.CodeRegionStart; }
public static AOpCode DecodeOpCode(AThreadState State, AMemory Memory, long Position) { int OpCode = Memory.ReadInt32(Position); AInst Inst; if (State.ExecutionMode == AExecutionMode.AArch64) { Inst = AOpCodeTable.GetInstA64(OpCode); } else { //TODO: Thumb support. Inst = AOpCodeTable.GetInstA32(OpCode); } AOpCode DecodedOpCode = new AOpCode(AInst.Undefined, Position, OpCode); if (Inst.Type != null) { DecodedOpCode = MakeOpCode(Inst.Type, Inst, Position, OpCode); } return(DecodedOpCode); }
public void SignalProcessWideKey(Process Process, AMemory Memory, long Address, int Count) { Queue <KThread> SignaledThreads = new Queue <KThread>(); System.CriticalSectionLock.Lock(); IOrderedEnumerable <KThread> SortedThreads = CondVarThreads.OrderBy(x => x.DynamicPriority); foreach (KThread CondVarThread in SortedThreads.Where(x => x.CondVarAddress == Address)) { TryAcquireMutex(Process, Memory, CondVarThread); SignaledThreads.Enqueue(CondVarThread); //If the count is <= 0, we should signal all threads waiting //for the conditional variable. if (Count >= 1 && --Count == 0) { break; } } while (SignaledThreads.TryDequeue(out KThread Thread)) { CondVarThreads.Remove(Thread); } System.CriticalSectionLock.Unlock(); }
public IAudioRenderer(AMemory Memory, IAalOutput AudioOut, AudioRendererParameter Params) { m_Commands = new Dictionary <int, ServiceProcessRequest>() { { 4, RequestUpdateAudioRenderer }, { 5, StartAudioRenderer }, { 6, StopAudioRenderer }, { 7, QuerySystemEvent } }; UpdateEvent = new KEvent(); this.Memory = Memory; this.AudioOut = AudioOut; this.Params = Params; Track = AudioOut.OpenTrack( AudioConsts.HostSampleRate, AudioConsts.HostChannelsCount, AudioCallback); MemoryPools = CreateArray <MemoryPoolContext>(Params.EffectCount + Params.VoiceCount * 4); Voices = CreateArray <VoiceContext>(Params.VoiceCount); InitializeAudioOut(); }
private void ExecuteSubroutineA64(AThreadState State, AMemory Memory, long Position) { do { if (EnableCpuTrace) { if (!SymbolTable.TryGetValue(Position, out string SubName)) { SubName = string.Empty; } CpuTrace?.Invoke(this, new ACpuTraceEventArgs(Position, SubName)); } if (!CachedSubs.TryGetValue(Position, out ATranslatedSub Sub)) { Sub = TranslateTier0(State, Memory, Position); } if (Sub.ShouldReJit()) { TranslateTier1(State, Memory, Position); } Position = Sub.Execute(State, Memory); }while (Position != 0 && State.Running); }
public void Teardown() { Thread = null; Memory = null; Allocator = null; Marshal.FreeHGlobal(Ram); }
private unsafe static byte[] Read8Bpt4x4(AMemory Memory, Texture Texture) { int Width = (Texture.Width + 3) / 4; int Height = (Texture.Height + 3) / 4; byte[] Output = new byte[Width * Height * 8]; ISwizzle Swizzle = GetSwizzle(Texture, 8); fixed(byte *BuffPtr = Output) { long OutOffs = 0; for (int Y = 0; Y < Height; Y++) { for (int X = 0; X < Width; X++) { long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y); long Tile = Memory.ReadInt64Unchecked(Texture.Position + Offset); *(long *)(BuffPtr + OutOffs) = Tile; OutOffs += 8; } } } return(Output); }
public void Teardown() { Marshal.FreeHGlobal(RamPointer); Memory = null; Thread = null; UnicornEmu = null; }
public long Execute(AThreadState ThreadState, AMemory Memory) { if (!HasDelegate) { string Name = $"{Method.Name}_Dispatch"; DynamicMethod Mthd = new DynamicMethod(Name, typeof(long), FixedArgTypes); ILGenerator Generator = Mthd.GetILGenerator(); Generator.EmitLdargSeq(FixedArgTypes.Length); foreach (ARegister Reg in Params) { Generator.EmitLdarg(StateArgIdx); Generator.Emit(OpCodes.Ldfld, Reg.GetField()); } Generator.Emit(OpCodes.Call, Method); Generator.Emit(OpCodes.Ret); ExecDelegate = (AA64Subroutine)Mthd.CreateDelegate(typeof(AA64Subroutine)); HasDelegate = true; } return(ExecDelegate(ThreadState, Memory)); }
private unsafe static byte[] Read2Bpp(AMemory Memory, Texture Texture) { int Width = Texture.Width; int Height = Texture.Height; byte[] Output = new byte[Width * Height * 2]; ISwizzle Swizzle = GetSwizzle(Texture, 2); fixed(byte *BuffPtr = Output) { long OutOffs = 0; for (int Y = 0; Y < Height; Y++) { for (int X = 0; X < Width; X++) { long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y); short Pixel = Memory.ReadInt16Unchecked(Texture.Position + Offset); *(short *)(BuffPtr + OutOffs) = Pixel; OutOffs += 2; } } } return(Output); }
private void UploadTexture(AMemory Memory, long BasePosition, int TexIndex, int HndIndex) { long Position = BasePosition + HndIndex * 4; int TextureHandle = Memory.ReadInt32(Position); int TicIndex = (TextureHandle >> 0) & 0xfffff; int TscIndex = (TextureHandle >> 20) & 0xfff; TryGetCpuAddr(NvGpuEngine3dReg.TexHeaderPoolOffset, out long TicPosition); TryGetCpuAddr(NvGpuEngine3dReg.TexSamplerPoolOffset, out long TscPosition); TicPosition += TicIndex * 0x20; TscPosition += TscIndex * 0x20; GalTextureSampler Sampler = TextureFactory.MakeSampler(Gpu, Memory, TscPosition); long TextureAddress = Memory.ReadInt64(TicPosition + 4) & 0xffffffffffff; if (FrameBuffers.Contains(TextureAddress)) { //This texture is a frame buffer texture, //we shouldn't read anything from memory and bind //the frame buffer texture instead, since we're not //really writing anything to memory. Gpu.Renderer.BindFrameBufferTexture(TextureAddress, TexIndex, Sampler); } else { GalTexture Texture = TextureFactory.MakeTexture(Gpu, Memory, TicPosition); Gpu.Renderer.SetTextureAndSampler(TexIndex, Texture, Sampler); Gpu.Renderer.BindTexture(TexIndex); } }
public Process(Switch Ns, AMemoryAlloc Allocator, int ProcessId) { this.Ns = Ns; this.ProcessId = ProcessId; Memory = new AMemory(Ns.Ram, Allocator); Scheduler = new KProcessScheduler(); SvcHandler = new SvcHandler(Ns, this); TlsSlots = new ConcurrentDictionary<int, AThread>(); ThreadsByTpidr = new ConcurrentDictionary<long, HThread>(); Executables = new List<Executable>(); ImageBase = 0x8000000; Memory.Manager.MapPhys( TlsPageAddr, TlsTotalSize, (int)MemoryType.ThreadLocal, AMemoryPerm.RW); }
private void UploadUniforms(AMemory Memory) { long BasePosition = MakeInt64From2xInt32(NvGpuEngine3dReg.ShaderAddress); for (int Index = 0; Index < 5; Index++) { int Control = ReadRegister(NvGpuEngine3dReg.ShaderNControl + (Index + 1) * 0x10); int Offset = ReadRegister(NvGpuEngine3dReg.ShaderNOffset + (Index + 1) * 0x10); //Note: Vertex Program (B) is always enabled. bool Enable = (Control & 1) != 0 || Index == 0; if (!Enable) { continue; } for (int Cbuf = 0; Cbuf < ConstBuffers.Length; Cbuf++) { ConstBuffer Cb = ConstBuffers[Cbuf]; if (Cb.Enabled) { long CbPosition = Cb.Position + Index * Cb.Size; byte[] Data = AMemoryHelper.ReadBytes(Memory, CbPosition, (uint)Cb.Size); Gpu.Renderer.SetConstBuffer(BasePosition + (uint)Offset, Cbuf, Data); } } } }
private ATranslatedSub TranslateTier0(AThreadState State, AMemory Memory, long Position) { ABlock Block = ADecoder.DecodeBasicBlock(State, Memory, Position); ABlock[] Graph = new ABlock[] { Block }; string SubName = GetSubroutineName(Position); AILEmitterCtx Context = new AILEmitterCtx(Cache, Graph, Block, SubName); do { Context.EmitOpCode(); }while (Context.AdvanceOpCode()); ATranslatedSub Subroutine = Context.GetSubroutine(); Subroutine.SetType(ATranslatedSubType.SubTier0); Cache.AddOrUpdate(Position, Subroutine, Block.OpCodes.Count); AOpCode LastOp = Block.GetLastOp(); return(Subroutine); }
private void UploadTextures(AMemory Memory, long[] Tags) { long BaseShPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.ShaderAddress); int TextureCbIndex = ReadRegister(NvGpuEngine3dReg.TextureCbIndex); long BasePosition = ConstBuffers[TextureCbIndex].Position; long Size = (uint)ConstBuffers[TextureCbIndex].Size; //Note: On the emulator renderer, Texture Unit 0 is //reserved for drawing the frame buffer. int TexIndex = 1; for (int Index = 0; Index < Tags.Length; Index++) { foreach (ShaderDeclInfo DeclInfo in Gpu.Renderer.GetTextureUsage(Tags[Index])) { long Position = BasePosition + Index * Size; UploadTexture(Memory, Position, TexIndex, DeclInfo.Index); Gpu.Renderer.SetUniform1(DeclInfo.Name, TexIndex); TexIndex++; } } }
public static string ReadHbAbiNextLoadPath(AMemory Memory, long Position) { string FileName = null; while (true) { long Key = Memory.ReadInt64(Position); if (Key == 2) { long Value0 = Memory.ReadInt64(Position + 0x08); long Value1 = Memory.ReadInt64(Position + 0x10); FileName = AMemoryHelper.ReadAsciiString(Memory, Value0, Value1 - Value0); break; } else if (Key == 0) { break; } Position += 0x18; } return(FileName); }
public static GalTextureSampler MakeSampler(NsGpu Gpu, AMemory Memory, long TscPosition) { int[] Tsc = ReadWords(Memory, TscPosition, 8); GalTextureWrap AddressU = (GalTextureWrap)((Tsc[0] >> 0) & 7); GalTextureWrap AddressV = (GalTextureWrap)((Tsc[0] >> 3) & 7); GalTextureWrap AddressP = (GalTextureWrap)((Tsc[0] >> 6) & 7); GalTextureFilter MagFilter = (GalTextureFilter)((Tsc[1] >> 0) & 3); GalTextureFilter MinFilter = (GalTextureFilter)((Tsc[1] >> 4) & 3); GalTextureMipFilter MipFilter = (GalTextureMipFilter)((Tsc[1] >> 6) & 3); GalColorF BorderColor = new GalColorF( BitConverter.Int32BitsToSingle(Tsc[4]), BitConverter.Int32BitsToSingle(Tsc[5]), BitConverter.Int32BitsToSingle(Tsc[6]), BitConverter.Int32BitsToSingle(Tsc[7])); return(new GalTextureSampler( AddressU, AddressV, AddressP, MinFilter, MagFilter, MipFilter, BorderColor)); }
private void UploadTextures(AMemory Memory, long[] Tags) { long BaseShPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.ShaderAddress); int TextureCbIndex = ReadRegister(NvGpuEngine3dReg.TextureCbIndex); long BasePosition = Cbs[TextureCbIndex].Position; long Size = (uint)Cbs[TextureCbIndex].Size; int TexIndex = 0; for (int Index = 0; Index < Tags.Length; Index++) { foreach (ShaderDeclInfo DeclInfo in Gpu.Renderer.GetTextureUsage(Tags[Index])) { long Position = BasePosition + Index * Size; UploadTexture(Memory, Position, TexIndex, DeclInfo.Index); Gpu.Renderer.SetUniform1(DeclInfo.Name, TexIndex); TexIndex++; } } }
public Process(Switch Ns, KProcessScheduler Scheduler, int ProcessId) { this.Ns = Ns; this.Scheduler = Scheduler; this.ProcessId = ProcessId; Memory = new AMemory(); HandleTable = new KProcessHandleTable(); AppletState = new AppletStateMgr(); SvcHandler = new SvcHandler(Ns, this); TlsSlots = new ConcurrentDictionary <int, AThread>(); ThreadsByTpidr = new ConcurrentDictionary <long, KThread>(); Executables = new List <Executable>(); ImageBase = MemoryRegions.AddrSpaceStart; MapRWMemRegion( MemoryRegions.TlsPagesAddress, MemoryRegions.TlsPagesSize, MemoryType.ThreadLocal); }
private void UpdateBuffer(AMemory Memory) { //TODO: Implement conversion for formats other //than interleaved stereo (2 channels). //As of now, it assumes that HostChannelsCount == 2. WaveBuffer Wb = WaveBuffers[BufferIndex]; if (SampleFormat == SampleFormat.PcmInt16) { int SamplesCount = (int)(Wb.Size / (sizeof(short) * ChannelsCount)); Samples = new int[SamplesCount * AudioConsts.HostChannelsCount]; if (ChannelsCount == 1) { for (int Index = 0; Index < SamplesCount; Index++) { short Sample = Memory.ReadInt16(Wb.Position + Index * 2); Samples[Index * 2 + 0] = Sample; Samples[Index * 2 + 1] = Sample; } } else { for (int Index = 0; Index < SamplesCount * 2; Index++) { Samples[Index] = Memory.ReadInt16(Wb.Position + Index * 2); } } } else if (SampleFormat == SampleFormat.Adpcm) { byte[] Buffer = Memory.ReadBytes(Wb.Position, Wb.Size); Samples = AdpcmDecoder.Decode(Buffer, AdpcmCtx); } else { throw new InvalidOperationException(); } if (SampleRate != AudioConsts.HostSampleRate) { //TODO: We should keep the frames being discarded (see the 4 below) //on a buffer and include it on the next samples buffer, to allow //the resampler to do seamless interpolation between wave buffers. int SamplesCount = Samples.Length / AudioConsts.HostChannelsCount; SamplesCount = Math.Max(SamplesCount - 4, 0); Samples = Resampler.Resample2Ch( Samples, SampleRate, AudioConsts.HostSampleRate, SamplesCount, ref ResamplerFracPart); } }
private void Send(AMemory Memory, int Value) { NsGpuPBEntry PBEntry = new NsGpuPBEntry(MethAddr, 0, Value); Engine.CallMethod(Memory, PBEntry); MethAddr += MethIncr; }
private int ReadCb(AMemory Memory, int Cbuf, int Offset) { long Position = ConstBuffers[Cbuf].Position; int Value = Memory.ReadInt32(Position + Offset); return(Value); }
private void FetchOpCode(AMemory Memory) { OpCode = PipeOp; PipeOp = Memory.ReadInt32(Pc); Pc += 4; }