Changed the structure of the emulator
This commit is contained in:
119
Desktop/Form1.cs
119
Desktop/Form1.cs
@@ -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()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user