Changed the structure of the emulator

This commit is contained in:
2026-04-20 14:31:06 +01:00
parent 7464b29fca
commit adbf64a84d
6 changed files with 296 additions and 240 deletions

View File

@@ -16,6 +16,11 @@ namespace Desktop
private IO_Bus _simpleIoBus = null!;
private TapManager _tapManager = null!;
private int _ulaFrameCount = 0;
private bool _isRunning = false;
private bool _isPaused = false;
private bool _resetFlag = false;
public ushort? Breakpoint = null; // Public so the debugger can set it!
private DebuggerForm _debugger = null;
// The 16 physical colors of the ZX Spectrum (ARGB format)
private readonly int[] SpectrumColors = new int[]
@@ -61,16 +66,88 @@ namespace Desktop
_cpu = new Z80(_memoryBus, _simpleIoBus, _tapManager);
// Pass 'this' so the DebuggerForm can talk back to this main window
DebuggerForm debugger = new DebuggerForm(_cpu, _memoryBus, this);
debugger.Show();
//DebuggerForm debugger = new DebuggerForm(_cpu, _memoryBus, this);
//debugger.Show();
}
catch (Exception ex)
{
MessageBox.Show($"Failed to initialize emulator:\n{ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
StartEmulationLoop();
}
private void StartEmulationLoop()
{
if (_isRunning) return;
_isRunning = true;
_isPaused = false;
Task.Run(() =>
{
try
{
const int TStatesPerFrame = 69888;
long nextFrameTargetTStates = _cpu.TotalTStates + TStatesPerFrame;
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
long frameCount = 0;
while (_isRunning)
{
//if(_resetFlag)
//{
// _resetFlag = false;
// stopwatch.Reset();
// nextFrameTargetTStates = _cpu.TotalTStates + TStatesPerFrame;
// frameCount = 0;
//}
if (_isPaused)
{
System.Threading.Thread.Sleep(10); // Don't melt the host CPU while paused
continue;
}
// --- Breakpoint Check ---
if (Breakpoint.HasValue && _cpu.PC == Breakpoint.Value)
{
_isPaused = true;
// Optional: You could force the debugger to open here!
continue;
}
// --- Execute Instruction ---
_cpu.Step();
// --- Check for End of Frame ---
if (_cpu.TotalTStates >= nextFrameTargetTStates)
{
_cpu.RequestInterrupt();
nextFrameTargetTStates += TStatesPerFrame;
frameCount++;
// Render the screen
this.Invoke((MethodInvoker)delegate { RenderScreen(); });
// Throttle to real-time (50 FPS = 20ms)
long targetTimeMs = frameCount * 20;
long elapsedMs = stopwatch.ElapsedMilliseconds;
if (elapsedMs < targetTimeMs)
{
System.Threading.Thread.Sleep((int)(targetTimeMs - elapsedMs));
}
}
}
}
catch (Exception ex)
{
_isPaused = true;
this.Invoke((MethodInvoker)delegate {
MessageBox.Show(ex.Message, "CPU Crash", MessageBoxButtons.OK, MessageBoxIcon.Error);
});
}
});
}
// Inside Desktop/Form1.cs
private void loadTAPToolStripMenuItem_Click(object sender, EventArgs e)
{
using (OpenFileDialog ofd = new OpenFileDialog())
@@ -101,6 +178,42 @@ namespace Desktop
}
}
private void btnRun_Click(object sender, EventArgs e) => _isPaused = false;
private void btnPause_Click(object sender, EventArgs e) => _isPaused = true;
private void btnStep_Click(object sender, EventArgs e)
{
if (_isPaused) _cpu.Step();
}
private void btnReset_Click(object sender, EventArgs e)
{
//_resetFlag = true;
_isPaused = true;
_cpu.Reset();
_memoryBus.CleanRAMData();
_isPaused = false;
}
private void btnExit_Click(object sender, EventArgs e)
{
Environment.Exit(0);
}
private void openDebuggerToolStripMenuItem_Click(object sender, EventArgs e)
{
if (_debugger == null || _debugger.IsDisposed)
{
_debugger = new DebuggerForm(_cpu, _memoryBus, this);
_debugger.Show();
}
else
{
_debugger.BringToFront();
}
}
// Public so the Debugger's background thread can call it 50 times a second
public void RenderScreen()
{