Moved emulator stuff out of cpu and into GameBoy class

Replaced OnPerformedStep event with hardcoded calls to whatever component to reduce EventArgs creation (GC)
Added  Cpu.SpeedMultiplier to dimplify (speedMode ? 2 : 1) everwhere
This commit is contained in:
Lee Fogg 2020-04-17 23:09:27 +01:00
parent 6565bd2933
commit fe0d65a084
14 changed files with 270 additions and 282 deletions

View File

@ -130,7 +130,7 @@ namespace Emux.GameBoy.Audio
public void ChannelStep(int cycles)
{
double cpuSpeedFactor = Spu.Device.Cpu.SpeedFactor;
double cpuSpeedFactor = Spu.Device.SpeedFactor;
if (!Active || double.IsNaN(cpuSpeedFactor) || double.IsInfinity(cpuSpeedFactor) || cpuSpeedFactor < 0.5)
return;

View File

@ -146,7 +146,7 @@ namespace Emux.GameBoy.Audio
public virtual void ChannelStep(int cycles)
{
double cpuSpeedFactor = Spu.Device.Cpu.SpeedFactor;
double cpuSpeedFactor = Spu.Device.SpeedFactor;
if (!Active || double.IsNaN(cpuSpeedFactor) || double.IsInfinity(cpuSpeedFactor) || cpuSpeedFactor < 0.5)
return;

View File

@ -47,9 +47,9 @@ namespace Emux.GameBoy.Audio
protected void UpdateFrequency(int cycles)
{
if (SweepTime > 0 && _spu.Device.Cpu.SpeedFactor > 0.5)
if (SweepTime > 0 && _spu.Device.SpeedFactor > 0.5)
{
double timeDelta = (cycles / GameBoyCpu.OfficialClockFrequency) / _spu.Device.Cpu.SpeedFactor;
double timeDelta = (cycles / GameBoyCpu.OfficialClockFrequency) / _spu.Device.SpeedFactor;
_frequencySweepClock += timeDelta;
while (_frequencySweepClock >= SweepTime)

View File

@ -45,7 +45,7 @@ namespace Emux.GameBoy.Audio
{
if (EnvelopeSweepCount > 0)
{
double timeDelta = (cycles / GameBoyCpu.OfficialClockFrequency) / _channel.Spu.Device.Cpu.SpeedFactor;
double timeDelta = (cycles / GameBoyCpu.OfficialClockFrequency) / _channel.Spu.Device.SpeedFactor;
_timer += timeDelta;
double stepInterval = EnvelopeSweepCount / 64.0;

View File

@ -127,7 +127,7 @@ namespace Emux.GameBoy.Audio
public void ChannelStep(int cycles)
{
double cpuSpeedFactor = Spu.Device.Cpu.SpeedFactor;
double cpuSpeedFactor = Spu.Device.SpeedFactor;
if (!Active
|| !SoundEnabled
|| double.IsNaN(cpuSpeedFactor)

View File

@ -16,39 +16,16 @@ namespace Emux.GameBoy.Cpu
public const int SerialLinkIsr = 0x0058;
public const int JoypadPressIsr = 0x0060;
public const double OfficialClockFrequency = 4194304;
/// <summary>
/// Occurs when the processor has resumed execution.
/// </summary>
public event EventHandler Resumed;
/// <summary>
/// Occurs when the processor is paused by breaking the execution explicitly, or when the control flow hit a breakpoint.
/// </summary>
public event EventHandler Paused;
/// <summary>
/// Occurs when the process has completely shut down.
/// </summary>
public event EventHandler Terminated;
public event StepEventHandler PerformedStep;
private readonly Z80Disassembler _disassembler;
private readonly GameBoy _device;
private readonly ManualResetEvent _continueSignal = new ManualResetEvent(false);
private readonly ManualResetEvent _terminateSignal = new ManualResetEvent(false);
private ulong _ticks;
private bool _break = true;
private bool _halt = false;
private readonly ManualResetEvent _frameStartSignal = new ManualResetEvent(false);
private readonly ManualResetEvent _breakSignal = new ManualResetEvent(false);
private TimeSpan _frameStartTime;
private ulong _frameStartTickCount;
private readonly IDictionary<ushort, Breakpoint> _breakpoints = new Dictionary<ushort, Breakpoint>();
public double CyclesPerSecond;
private ulong _frameStartTickCount;
private ulong _ticks;
public bool IsBroken = true;
public bool Halted = false;
public GameBoyCpu(GameBoy device, IClock clock)
{
@ -57,32 +34,12 @@ namespace Emux.GameBoy.Cpu
Registers = new RegisterBank();
Alu = new GameBoyAlu(Registers);
EnableFrameLimit = true;
Clock = clock ?? throw new ArgumentNullException(nameof(clock));
Clock.Tick += ClockOnTick;
new Thread(CpuLoop)
{
Name = "Z80CPULOOP",
IsBackground = true
}.Start();
}
private void ClockOnTick(object sender, EventArgs e)
{
_frameStartSignal.Set();
var time = DateTime.Now.TimeOfDay;
var delta = time - _frameStartTime;
CyclesPerSecond = (_ticks - _frameStartTickCount) / delta.TotalSeconds;
FramesPerSecond = 1 / delta.TotalSeconds;
_frameStartTime = time;
_frameStartTickCount = _ticks;
}
/// <summary>
/// Gets the register bank of the processor.
/// </summary>
public RegisterBank Registers
/// <summary>
/// Gets the register bank of the processor.
/// </summary>
public RegisterBank Registers
{
get;
}
@ -104,44 +61,19 @@ namespace Emux.GameBoy.Cpu
/// Gets a value indicating whether the processor is active.
/// </summary>
public bool Running
{
get;
private set;
}
/// <summary>
/// Gets or sets a value indicating whether the processor should limit the execution speed to the original GameBoy clock speed.
/// Disable this if experiencing heavy performance losses.
/// </summary>
public bool EnableFrameLimit
{
get;
set;
}
public double FramesPerSecond
{
get;
private set;
}
public double CyclesPerSecond
{
get;
private set;
}
public double SpeedFactor
{
get { return CyclesPerSecond / (OfficialClockFrequency * (DoubleSpeed ? 2 : 1)); }
}
public bool DoubleSpeed
public bool DoubleSpeed
{
get;
internal set;
}
public int SpeedMultiplier => DoubleSpeed ? 2 : 1;
public bool IsPreparingSpeedSwitch
{
get;
@ -173,58 +105,16 @@ namespace Emux.GameBoy.Cpu
public void Shutdown()
{
Terminate();
}
private void CpuLoop()
{
bool enabled = true;
while (enabled)
{
if (WaitHandle.WaitAny(new WaitHandle[] { _continueSignal, _terminateSignal }) == 1)
{
enabled = false;
}
else
{
Running = true;
_continueSignal.Reset();
OnResumed();
int cycles = 0;
do
{
cycles += CpuStep();
if (cycles >= GameBoyGpu.FullFrameCycles * (DoubleSpeed ? 2 : 1))
{
_device.Spu.SpuStep(cycles / (DoubleSpeed ? 2 : 1));
cycles -= GameBoyGpu.FullFrameCycles * (DoubleSpeed ? 2 : 1);
if (EnableFrameLimit)
{
WaitHandle.WaitAny(new WaitHandle[] { _breakSignal, _frameStartSignal });
_frameStartSignal.Reset();
}
}
if (_breakpoints.TryGetValue(Registers.PC, out var breakpoint) && breakpoint.Condition(this))
_break = true;
} while (!_break);
_breakSignal.Reset();
Running = false;
OnPaused();
}
}
OnTerminated();
}
private int CpuStep()
public int PerformNextInstruction()
{
Registers.IMESet = false;
int cycles;
if (_halt)
if (Halted)
{
cycles = 4;
}
@ -255,99 +145,30 @@ namespace Emux.GameBoy.Cpu
cycles += 12;
}
_halt = false;
Halted = false;
}
}
}
// Update cycle dependent components.
OnPerformedStep(new StepEventArgs(cycles / (DoubleSpeed ? 2 : 1)));
OnPerformedStep(cycles / SpeedMultiplier);
_ticks = (_ticks + (ulong) cycles) & long.MaxValue;
return cycles;
return cycles;
}
public void Step()
{
Clock.Stop();
_break = true;
_continueSignal.Set();
}
public void SecondElapsed(TimeSpan delta)
{
CyclesPerSecond = (_ticks - _frameStartTickCount) / delta.TotalSeconds;
_ticks = 0;
}
public void Run()
protected virtual void OnPerformedStep(int cycles)
{
_frameStartTime = DateTime.Now.TimeOfDay;
Clock.Start();
_break = false;
_continueSignal.Set();
}
public void Break()
{
_breakSignal.Set();
Clock.Stop();
_continueSignal.Reset();
_break = true;
}
public void Terminate()
{
Clock.Stop();
_continueSignal.Reset();
_terminateSignal.Set();
}
public Breakpoint SetBreakpoint(ushort address)
{
if (!_breakpoints.TryGetValue(address, out var breakpoint))
{
breakpoint = new Breakpoint(address);
_breakpoints.Add(address, breakpoint);
}
return breakpoint;
}
public void RemoveBreakpoint(ushort address)
{
_breakpoints.Remove(address);
}
public IEnumerable<Breakpoint> GetBreakpoints()
{
return _breakpoints.Values;
}
public Breakpoint GetBreakpointAtAddress(ushort address)
{
_breakpoints.TryGetValue(address, out var breakpoint);
return breakpoint;
}
public void ClearBreakpoints()
{
_breakpoints.Clear();
}
protected virtual void OnResumed()
{
Resumed?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnPaused()
{
Paused?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnTerminated()
{
Terminated?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnPerformedStep(StepEventArgs args)
{
PerformedStep?.Invoke(this, args);
}
_device.Gpu.Step(cycles);
_device.Timer.Step(cycles);
}
private Z80Instruction ReadNextInstruction()
{
@ -423,7 +244,7 @@ namespace Emux.GameBoy.Cpu
internal void Halt()
{
_halt = true;
Halted = true;
}
internal void Stop()

View File

@ -1,4 +1,6 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Threading;
using Emux.GameBoy.Audio;
using Emux.GameBoy.Cartridge;
using Emux.GameBoy.Cpu;
@ -14,10 +16,45 @@ namespace Emux.GameBoy
/// </summary>
public class GameBoy
{
public GameBoy(ICartridge cartridge, IClock clock, bool preferGbcMode)
private readonly ManualResetEvent _continueSignal = new ManualResetEvent(false);
private readonly ManualResetEvent _terminateSignal = new ManualResetEvent(false);
private readonly ManualResetEvent _frameStartSignal = new ManualResetEvent(false);
private readonly ManualResetEvent _breakSignal = new ManualResetEvent(false);
/// <summary>
/// Occurs when the processor has resumed execution.
/// </summary>
public event EventHandler Resumed;
/// <summary>
/// Occurs when the processor is paused by breaking the execution explicitly, or when the control flow hit a breakpoint.
/// </summary>
public event EventHandler Paused;
/// <summary>
/// Occurs when the process has completely shut down.
/// </summary>
public event EventHandler Terminated;
public event StepEventHandler PerformedStep;
private readonly IDictionary<ushort, Breakpoint> _breakpoints = new Dictionary<ushort, Breakpoint>();
private IClock Clock;
private int framesCount;
public double FramesPerSecond;
public bool EnableFrameLimit;
public TimeSpan _frameStartTime;
public GameBoy(ICartridge cartridge, IClock clock, bool preferGbcMode)
{
GbcMode = preferGbcMode && (cartridge.GameBoyColorFlag & GameBoyColorFlag.SupportsColor) != 0;
Clock = clock;
Components = new List<IGameBoyComponent>
{
(Cartridge = cartridge),
@ -34,9 +71,18 @@ namespace Emux.GameBoy
Reset();
IsPoweredOn = true;
}
public ICollection<IGameBoyComponent> Components
Clock.Tick += nextFrame;
new Thread(CpuLoop)
{
Name = "Z80CPULOOP",
IsBackground = true
}.Start();
Gpu.VBlankStarted += (_, __) => framesCount++;
}
private ICollection<IGameBoyComponent> Components
{
get;
}
@ -49,10 +95,10 @@ namespace Emux.GameBoy
get;
}
/// <summary>
/// Gets the central processing unit of the emulated GameBoy device.
/// </summary>
public GameBoyCpu Cpu
/// <summary>
/// Gets the central processing unit of the emulated GameBoy device.
/// </summary>
public GameBoyCpu Cpu
{
get;
}
@ -114,14 +160,149 @@ namespace Emux.GameBoy
private set;
}
/// <summary>
/// Resets the state of the GameBoy to the bootup state.
/// </summary>
public void Reset()
public double SpeedFactor => Cpu.CyclesPerSecond / (GameBoyCpu.OfficialClockFrequency * Cpu.SpeedMultiplier);
private void nextFrame(object sender, EventArgs e)
{
_frameStartSignal.Set();
var time = DateTime.Now.TimeOfDay;
var delta = time - _frameStartTime;
if (delta.TotalSeconds > 1)
{
FramesPerSecond = framesCount / delta.TotalSeconds;
framesCount = 0;
Cpu.SecondElapsed(delta);
_frameStartTime = time;
}
}
public void Step()
{
Clock.Stop();
Cpu.IsBroken = true;
_continueSignal.Set();
}
public void Run()
{
_frameStartTime = DateTime.Now.TimeOfDay;
Clock.Start();
Cpu.IsBroken = false;
_continueSignal.Set();
}
public void Break()
{
_breakSignal.Set();
Clock.Stop();
_continueSignal.Reset();
Cpu.IsBroken = true;
}
private void CpuLoop()
{
bool enabled = true;
while (enabled)
{
if (WaitHandle.WaitAny(new WaitHandle[] { _continueSignal, _terminateSignal }) == 1)
{
enabled = false;
}
else
{
Cpu.Running = true;
_continueSignal.Reset();
OnResumed();
int cycles = 0;
do
{
cycles += Cpu.PerformNextInstruction();
if (cycles >= GameBoyGpu.FullFrameCycles * Cpu.SpeedMultiplier)
{
Spu.SpuStep(cycles / Cpu.SpeedMultiplier);
cycles -= GameBoyGpu.FullFrameCycles * Cpu.SpeedMultiplier;
if (EnableFrameLimit)
{
WaitHandle.WaitAny(new WaitHandle[] { _breakSignal, _frameStartSignal });
_frameStartSignal.Reset();
}
}
if (_breakpoints.TryGetValue(Cpu.Registers.PC, out var breakpoint) && breakpoint.Condition(Cpu))
Cpu.IsBroken = true;
} while (!Cpu.IsBroken);
_breakSignal.Reset();
Cpu.Running = false;
OnPaused();
}
}
OnTerminated();
}
protected virtual void OnResumed()
{
Resumed?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnPaused()
{
Paused?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnTerminated()
{
Terminated?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnPerformedStep(StepEventArgs args)
{
PerformedStep?.Invoke(this, args);
}
public Breakpoint SetBreakpoint(ushort address)
{
if (!_breakpoints.TryGetValue(address, out var breakpoint))
{
breakpoint = new Breakpoint(address);
_breakpoints.Add(address, breakpoint);
}
return breakpoint;
}
public void RemoveBreakpoint(ushort address)
{
_breakpoints.Remove(address);
}
public IEnumerable<Breakpoint> GetBreakpoints()
{
return _breakpoints.Values;
}
public Breakpoint GetBreakpointAtAddress(ushort address)
{
_breakpoints.TryGetValue(address, out var breakpoint);
return breakpoint;
}
public void ClearBreakpoints()
{
_breakpoints.Clear();
}
/// <summary>
/// Resets the state of the GameBoy to the bootup state.
/// </summary>
public void Reset()
{
foreach (var component in Components)
component.Reset();
}
/// <summary>
@ -129,9 +310,11 @@ namespace Emux.GameBoy
/// </summary>
public void Terminate()
{
Clock.Stop();
foreach (var component in Components)
component.Shutdown();
IsPoweredOn = false;
}
}
}
}

View File

@ -15,8 +15,8 @@ namespace Emux.GameBoy.Graphics
public const int ScanLineOamCycles = 80;
public const int ScanLineVramCycles = 172;
public const int HBlankCycles = 204;
public const int OneLineCycles = 456;
public const int VBlankCycles = 456 * 10;
public const int OneLineCycles = ScanLineOamCycles + ScanLineVramCycles + HBlankCycles;
public const int VBlankCycles = OneLineCycles * 10;
public const int FullFrameCycles = 70224;
public event EventHandler HBlankStarted;
@ -389,7 +389,6 @@ namespace Emux.GameBoy.Graphics
public void Initialize()
{
_device.Cpu.PerformedStep += CpuOnPerformedStep;
}
public void Reset()
@ -416,19 +415,14 @@ namespace Emux.GameBoy.Graphics
public void Shutdown()
{
_device.Cpu.PerformedStep -= CpuOnPerformedStep;
}
private void CpuOnPerformedStep(object sender, StepEventArgs args)
{
GpuStep(args.Cycles);
}
/// <summary>
/// Advances the execution of the graphical processor unit.
/// </summary>
/// <param name="cycles">The cycles the central processor unit has executed since last step.</param>
private void GpuStep(int cycles)
public void Step(int cycles)
{
if ((_lcdc & LcdControlFlags.EnableLcd) == 0)
return;
@ -468,8 +462,8 @@ namespace Emux.GameBoy.Graphics
{
currentMode = LcdStatusFlags.VBlankMode;
OnVBlankStarted();
VideoOutput.RenderFrame(_frameBuffer);
_device.Cpu.Registers.IF |= InterruptFlags.VBlank;
VideoOutput.RenderFrame(_frameBuffer);
_device.Cpu.Registers.IF |= InterruptFlags.VBlank;
if ((stat & LcdStatusFlags.VBlankModeInterrupt) == LcdStatusFlags.VBlankModeInterrupt)
_device.Cpu.Registers.IF |= InterruptFlags.LcdStat;
}
@ -699,14 +693,14 @@ namespace Emux.GameBoy.Graphics
private static Color GetGbcColor(byte[] paletteMemory, int paletteIndex, int colorIndex)
{
ushort rawValue = (ushort)(paletteMemory[paletteIndex * 8 + colorIndex * 2] | (paletteMemory[paletteIndex * 8 + colorIndex * 2 + 1] << 8));
return new Color(
(byte)((rawValue & 0x1F) * (0xFF / 0x1F)),
(byte)(((rawValue >> 5) & 0x1F) * (0xFF / 0x1F)),
(byte)(((rawValue >> 10) & 0x1F) * (0xFF / 0x1F)));
return new Color(
(byte)((rawValue & 0x1F) * (0xFF / 0x1F)),
(byte)(((rawValue >> 5) & 0x1F) * (0xFF / 0x1F)),
(byte)(((rawValue >> 10) & 0x1F) * (0xFF / 0x1F)));
}
}
private static int GetGreyshadeIndex(byte palette, int paletteIndex)
private static int GetGreyshadeIndex(byte palette, int paletteIndex)
{
return (palette >> (paletteIndex * 2)) & 3;
}
@ -730,10 +724,6 @@ namespace Emux.GameBoy.Graphics
if ((flags & SpriteDataFlags.XFlip) != 0)
actualX = 7 - actualX;
if (LY == 0)
{
}
int paletteIndex = (int)(flags & SpriteDataFlags.PaletteNumberMask);
int colorIndex = GetPixelColorIndex(actualX, currentTileData);
RenderPixel(outputX, LY, colorIndex, GetGbcColor(_bgPaletteMemory, paletteIndex, colorIndex));

View File

@ -61,7 +61,6 @@ namespace Emux.GameBoy.Timer
public void Initialize()
{
_device.Cpu.PerformedStep += CpuOnPerformedStep;
}
public void Reset()
@ -74,7 +73,6 @@ namespace Emux.GameBoy.Timer
public void Shutdown()
{
_device.Cpu.PerformedStep -= CpuOnPerformedStep;
}
public int GetTimaFrequency()
@ -97,13 +95,9 @@ namespace Emux.GameBoy.Timer
{
return (int)(GameBoyCpu.OfficialClockFrequency / GetTimaFrequency());
}
private void CpuOnPerformedStep(object sender, StepEventArgs args)
{
TimerStep(args.Cycles);
}
private void TimerStep(int cycles)
public void Step(int cycles)
{
_divClock += cycles;
while (_divClock > DivCycleInterval)

View File

@ -57,7 +57,7 @@ namespace Emux.MonoGame
_video = new Texture2D(GraphicsDevice, 160, 144);
_font = Content.Load<SpriteFont>("Calibri");
GameBoy.Cpu.Run();
GameBoy.Run();
}
protected override void Update(GameTime gameTime)
@ -139,7 +139,7 @@ namespace Emux.MonoGame
private void DrawDebugInformation(GameTime time)
{
_fps.Add(1 / time.ElapsedGameTime.TotalSeconds);
_gbfps.Add(GameBoy.Cpu.FramesPerSecond);
_gbfps.Add(GameBoy.FramesPerSecond);
var difference = time.TotalGameTime - _last;
if (difference.TotalSeconds > 1)

View File

@ -43,14 +43,14 @@ namespace Emux.Gui
{
if (value != null)
{
value.Cpu.Paused -= CpuOnPaused;
value.Cpu.Resumed -= CpuOnResumed;
value.Paused -= CpuOnPaused;
value.Resumed -= CpuOnResumed;
}
_device = value;
if (_device != null)
{
_device.Cpu.Paused += CpuOnPaused;
_device.Cpu.Resumed += CpuOnResumed;
_device.Paused += CpuOnPaused;
_device.Resumed += CpuOnResumed;
}
}
}

View File

@ -30,9 +30,9 @@ namespace Emux.Gui
set
{
if (value)
_gameBoy.Cpu.SetBreakpoint(_instruction.Offset);
_gameBoy.SetBreakpoint(_instruction.Offset);
else
_gameBoy.Cpu.RemoveBreakpoint(_instruction.Offset);
_gameBoy.RemoveBreakpoint(_instruction.Offset);
OnPropertyChanged(nameof(IsBreakpoint));
}
}
@ -41,7 +41,7 @@ namespace Emux.Gui
{
get
{
var bp = _gameBoy.Cpu.GetBreakpointAtAddress(_instruction.Offset);
var bp = _gameBoy.GetBreakpointAtAddress(_instruction.Offset);
if (bp == null)
return null;
App.Current.DeviceManager.Breakpoints.TryGetValue(_instruction.Offset, out var breakpointInfo);

View File

@ -179,14 +179,14 @@ namespace Emux.Gui
{
if (_currentDevice != null)
{
_currentDevice.Cpu.Paused -= GameBoyOnPaused;
_currentDevice.Cpu.Resumed -= GameBoyOnResumed;
_currentDevice.Paused -= GameBoyOnPaused;
_currentDevice.Resumed -= GameBoyOnResumed;
RunningOverlay.DisableOverlay();
}
_currentDevice = DeviceManager.CurrentDevice;
_currentDevice.Cpu.Paused += GameBoyOnPaused;
_currentDevice.Cpu.Resumed += GameBoyOnResumed;
_currentDevice.Paused += GameBoyOnPaused;
_currentDevice.Resumed += GameBoyOnResumed;
_currentDevice.Gpu.VideoOutput = _videoWindow;
_videoWindow.Device = _currentDevice;
@ -252,7 +252,7 @@ namespace Emux.Gui
private void StepCommandOnExecuted(object sender, ExecutedRoutedEventArgs e)
{
_currentDevice.Cpu.Step();
_currentDevice.Step();
RefreshView();
}
@ -273,12 +273,12 @@ namespace Emux.Gui
private void RunCommandOnExecuted(object sender, ExecutedRoutedEventArgs e)
{
_currentDevice.Cpu.Run();
_currentDevice.Run();
}
private void BreakCommandOnExecuted(object sender, ExecutedRoutedEventArgs e)
{
_currentDevice.Cpu.Break();
_currentDevice.Break();
}
private void SetBreakpointCommandOnExecuted(object sender, ExecutedRoutedEventArgs e)
@ -307,7 +307,7 @@ namespace Emux.Gui
}
else
{
var bp = _currentDevice.Cpu.SetBreakpoint(address);
var bp = _currentDevice.SetBreakpoint(address);
DeviceManager.Breakpoints[address] = new BreakpointInfo(bp);
}
}
@ -322,7 +322,7 @@ namespace Emux.Gui
private void ClearBreakpointsCommandOnExecuted(object sender, ExecutedRoutedEventArgs e)
{
_currentDevice.Cpu.ClearBreakpoints();
_currentDevice.ClearBreakpoints();
}
private void KeyPadCommandOnExecuted(object sender, ExecutedRoutedEventArgs e)
@ -401,7 +401,7 @@ namespace Emux.Gui
{
if (instruction.Breakpoint == null)
{
_currentDevice.Cpu.SetBreakpoint((ushort) instruction.Offset);
_currentDevice.SetBreakpoint((ushort) instruction.Offset);
}
var dialog = new BreakpointDialog(instruction.Breakpoint);

View File

@ -54,7 +54,7 @@ namespace Emux.Gui
lock (this)
{
Dispatcher.Invoke(() => Title = string.Format("Video Output ({0:0.00} %)",
_device.Cpu.SpeedFactor * 100));
_device.SpeedFactor * 100));
}
}
}
@ -84,7 +84,7 @@ namespace Emux.Gui
private void VideoWindowOnKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space)
Device.Cpu.EnableFrameLimit = false;
Device.EnableFrameLimit = false;
else if (GetBindedButton(e.Key, out var button))
Device.KeyPad.PressedButtons |= button;
}
@ -93,7 +93,7 @@ namespace Emux.Gui
private void VideoWindowOnKeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space)
Device.Cpu.EnableFrameLimit = true;
Device.EnableFrameLimit = true;
else if (GetBindedButton(e.Key, out var button))
Device.KeyPad.PressedButtons &= ~button;
}