/// <summary> /// Sets the shadow ram control value of all sub-channels. /// </summary> /// <param name="control">New shadow ram control value</param> public void SetShadowRamControl(ShadowRamControl control) { for (int i = 0; i < _subChannels.Length; i++) { _subChannels[i].ShadowRamControl = control; } }
/// <summary> /// Calls a GPU method, using this state. /// </summary> /// <param name="meth">The GPU method to be called</param> public void CallMethod(MethodParams meth) { int value = meth.Argument; // Methods < 0x80 shouldn't be affected by shadow RAM at all. if (meth.Method >= 0x80) { ShadowRamControl shadowCtrl = ShadowRamControl; // TODO: Figure out what TrackWithFilter does, compared to Track. if (shadowCtrl == ShadowRamControl.Track || shadowCtrl == ShadowRamControl.TrackWithFilter) { _shadow[meth.Method] = value; } else if (shadowCtrl == ShadowRamControl.Replay) { value = _shadow[meth.Method]; } } Register register = _registers[meth.Method]; if (_memory[meth.Method] != value) { _registers[(int)register.BaseOffset].Modified = true; } _memory[meth.Method] = value; register.Callback?.Invoke(this, value); }
/// <summary> /// Starts executing the macro program code. /// </summary> /// <param name="mme">Program code</param> /// <param name="state">Current GPU state</param> public void Execute(int[] mme, ShadowRamControl shadowCtrl, GpuState state, GpuState shadowState) { if (_executionPending) { _executionPending = false; _interpreter?.Execute(mme, Position, _argument, shadowCtrl, state, shadowState); } }
/// <summary> /// Executes a macro program until it exits. /// </summary> /// <param name="mme">Code of the program to execute</param> /// <param name="position">Start position to execute</param> /// <param name="param">Optional argument passed to the program, 0 if not used</param> /// <param name="shadowCtrl">Shadow RAM control register value</param> /// <param name="state">Current GPU state</param> /// <param name="shadowState">Shadow GPU state</param> public void Execute(int[] mme, int position, int param, ShadowRamControl shadowCtrl, GpuState state, GpuState shadowState) { Reset(); _gprs[1] = param; _pc = position; _shadowCtrl = shadowCtrl; FetchOpCode(mme); while (Step(mme, state, shadowState)); // Due to the delay slot, we still need to execute // one more instruction before we actually exit. Step(mme, state, shadowState); }
/// <summary> /// Change the shadow RAM setting /// </summary> /// <param name="shadowCtrl">The new Shadow RAM setting</param> public void SetMmeShadowRamControl(ShadowRamControl shadowCtrl) { _shadowCtrl = shadowCtrl; }
/// <summary> /// Change the shadow RAM setting /// </summary> /// <param name="argument">Method call argument</param> public void SetMmeShadowRamControl(int argument) { ShadowCtrl = (ShadowRamControl)argument; }
/// <summary> /// Calls a GPU method. /// </summary> /// <param name="meth">GPU method call parameters</param> public void CallMethod(MethodParams meth) { if ((NvGpuFifoMeth)meth.Method == NvGpuFifoMeth.BindChannel) { _subChannels[meth.SubChannel].Class = (ClassId)meth.Argument; } else if (meth.Method < 0x60) { switch ((NvGpuFifoMeth)meth.Method) { case NvGpuFifoMeth.WaitForIdle: { _context.Methods.PerformDeferredDraws(); _context.Renderer.Pipeline.Barrier(); break; } case NvGpuFifoMeth.SetMacroUploadAddress: { _currMacroPosition = meth.Argument; break; } case NvGpuFifoMeth.SendMacroCodeData: { _mme[_currMacroPosition++] = meth.Argument; break; } case NvGpuFifoMeth.SetMacroBindingIndex: { _currMacroBindIndex = meth.Argument; break; } case NvGpuFifoMeth.BindMacro: { int position = meth.Argument; _macros[_currMacroBindIndex++] = new CachedMacro(position); break; } case NvGpuFifoMeth.SetMmeShadowRamControl: { _shadowCtrl = (ShadowRamControl)meth.Argument; break; } } } else if (meth.Method < 0xe00) { SubChannel sc = _subChannels[meth.SubChannel]; sc.ShadowState.Write(meth.Method, meth.Argument); sc.State.CallMethod(meth); } else { int macroIndex = (meth.Method >> 1) & MacroIndexMask; if ((meth.Method & 1) != 0) { _macros[macroIndex].PushArgument(meth.Argument); } else { _macros[macroIndex].StartExecution(meth.Argument); } if (meth.IsLastCall) { SubChannel sc = _subChannels[meth.SubChannel]; _macros[macroIndex].Execute(_mme, _shadowCtrl, sc.State, sc.ShadowState); _context.Methods.PerformDeferredDraws(); } } }