Implemenmted rendering priorities
This commit is contained in:
@@ -10,9 +10,9 @@ namespace Desktop
|
||||
{
|
||||
private readonly Z80 _cpu;
|
||||
private readonly SmsMemoryBus _memoryBus;
|
||||
private readonly Form1 _mainForm;
|
||||
private readonly ParsonsForm1 _mainForm;
|
||||
|
||||
public DebuggerForm(Z80 cpu, SmsMemoryBus memoryBus, Form1 mainForm)
|
||||
public DebuggerForm(Z80 cpu, SmsMemoryBus memoryBus, ParsonsForm1 mainForm)
|
||||
{
|
||||
InitializeComponent();
|
||||
_cpu = cpu;
|
||||
@@ -103,9 +103,9 @@ namespace Desktop
|
||||
lblIE.Text = $"Interrupt Mode: {_cpu.InterruptMode}";
|
||||
lblFlags.Text = $"Flags: {_cpu.GetFlagsString()}";
|
||||
lblTStates.Text = $"T-States: {_cpu.TotalTStates}";
|
||||
//lblFrames.Text = $"Frames Rendered: {_mainForm.TotalFrameCount}";
|
||||
//lblFrameTime.Text = $"Frame Time: {((float)_mainForm.FrameTime):F1}ms";
|
||||
//lblFPS.Text = $"FPS: {_mainForm.FramesPerSecond:F2}";
|
||||
lblFrames.Text = $"Frames Rendered: {_mainForm.TotalFrameCount}";
|
||||
lblFrameTime.Text = $"Frame Time: {((float)_mainForm.FrameTime):F1}ms";
|
||||
lblFPS.Text = $"FPS: {_mainForm.FramesPerSecond:F2}";
|
||||
UpdateMemoryView();
|
||||
UpdateStackView();
|
||||
UpdateDisassemblyView();
|
||||
|
||||
20
Desktop/Form1.Designer.cs
generated
20
Desktop/Form1.Designer.cs
generated
@@ -1,6 +1,6 @@
|
||||
namespace Desktop
|
||||
{
|
||||
partial class Form1
|
||||
partial class ParsonsForm1
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
@@ -49,7 +49,7 @@
|
||||
//
|
||||
pbScreen.Location = new Point(12, 36);
|
||||
pbScreen.Name = "pbScreen";
|
||||
pbScreen.Size = new Size(762, 672);
|
||||
pbScreen.Size = new Size(768, 576);
|
||||
pbScreen.SizeMode = PictureBoxSizeMode.Zoom;
|
||||
pbScreen.TabIndex = 1;
|
||||
pbScreen.TabStop = false;
|
||||
@@ -60,7 +60,7 @@
|
||||
menuStrip1.Items.AddRange(new ToolStripItem[] { fileToolStripMenuItem, viewToolStripMenuItem, machineToolStripMenuItem, helpToolStripMenuItem });
|
||||
menuStrip1.Location = new Point(0, 0);
|
||||
menuStrip1.Name = "menuStrip1";
|
||||
menuStrip1.Size = new Size(785, 33);
|
||||
menuStrip1.Size = new Size(791, 33);
|
||||
menuStrip1.TabIndex = 2;
|
||||
menuStrip1.Text = "menuStrip1";
|
||||
//
|
||||
@@ -75,27 +75,27 @@
|
||||
//
|
||||
openToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { includedToolStripMenuItem, selectROMToolStripMenuItem1 });
|
||||
openToolStripMenuItem.Name = "openToolStripMenuItem";
|
||||
openToolStripMenuItem.Size = new Size(270, 34);
|
||||
openToolStripMenuItem.Size = new Size(158, 34);
|
||||
openToolStripMenuItem.Text = "Open";
|
||||
//
|
||||
// includedToolStripMenuItem
|
||||
//
|
||||
includedToolStripMenuItem.Name = "includedToolStripMenuItem";
|
||||
includedToolStripMenuItem.Size = new Size(270, 34);
|
||||
includedToolStripMenuItem.Size = new Size(218, 34);
|
||||
includedToolStripMenuItem.Text = "Included";
|
||||
includedToolStripMenuItem.Click += includedToolStripMenuItem_Click;
|
||||
//
|
||||
// selectROMToolStripMenuItem1
|
||||
//
|
||||
selectROMToolStripMenuItem1.Name = "selectROMToolStripMenuItem1";
|
||||
selectROMToolStripMenuItem1.Size = new Size(270, 34);
|
||||
selectROMToolStripMenuItem1.Size = new Size(218, 34);
|
||||
selectROMToolStripMenuItem1.Text = "Select ROM...";
|
||||
selectROMToolStripMenuItem1.Click += selectROMToolStripMenuItem_Click;
|
||||
//
|
||||
// exitToolStripMenuItem
|
||||
//
|
||||
exitToolStripMenuItem.Name = "exitToolStripMenuItem";
|
||||
exitToolStripMenuItem.Size = new Size(270, 34);
|
||||
exitToolStripMenuItem.Size = new Size(158, 34);
|
||||
exitToolStripMenuItem.Text = "Exit";
|
||||
exitToolStripMenuItem.Click += exitToolStripMenuItem_Click;
|
||||
//
|
||||
@@ -140,16 +140,16 @@
|
||||
aboutToolStripMenuItem.Size = new Size(164, 34);
|
||||
aboutToolStripMenuItem.Text = "About";
|
||||
//
|
||||
// Form1
|
||||
// ParsonsForm1
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(10F, 25F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
ClientSize = new Size(785, 719);
|
||||
ClientSize = new Size(791, 622);
|
||||
Controls.Add(pbScreen);
|
||||
Controls.Add(menuStrip1);
|
||||
MainMenuStrip = menuStrip1;
|
||||
Margin = new Padding(4);
|
||||
Name = "Form1";
|
||||
Name = "ParsonsForm1";
|
||||
Text = "Form1";
|
||||
((System.ComponentModel.ISupportInitialize)pbScreen).EndInit();
|
||||
menuStrip1.ResumeLayout(false);
|
||||
|
||||
@@ -1,22 +1,26 @@
|
||||
using System.Diagnostics;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Reflection;
|
||||
using System.Reflection.PortableExecutable;
|
||||
using Core;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Core;
|
||||
|
||||
namespace Desktop
|
||||
{
|
||||
public partial class Form1 : Form
|
||||
public partial class ParsonsForm1 : Form
|
||||
{
|
||||
private SmsMachine _machine = null!;
|
||||
private DebuggerForm _debugger;
|
||||
private Bitmap _screenBitmap = new Bitmap(256, 192, PixelFormat.Format32bppArgb);
|
||||
|
||||
private Task _emulatorTask;
|
||||
|
||||
|
||||
private double TargetFrameTime = 16.667f;
|
||||
public int TotalFrameCount = 0;
|
||||
public double FrameTime { get; private set; } = 0;
|
||||
public double FramesPerSecond { get; private set; } = 0;
|
||||
private string _currentRomName = "No ROM";
|
||||
private Stopwatch _stopwatch = new System.Diagnostics.Stopwatch();
|
||||
public bool IsRunning { get; private set; } = false;
|
||||
|
||||
public ushort? Breakpoint
|
||||
@@ -25,9 +29,10 @@ namespace Desktop
|
||||
set { if (_machine != null) _machine.Breakpoint = value; }
|
||||
}
|
||||
|
||||
public Form1()
|
||||
public ParsonsForm1()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.Text = $"Parsons Master System 2026 - {_currentRomName}";
|
||||
_machine = new SmsMachine();
|
||||
|
||||
PopulateIncludedRomsMenu();
|
||||
@@ -46,32 +51,81 @@ namespace Desktop
|
||||
|
||||
// Update the PictureBox
|
||||
pbScreen.Image = _screenBitmap;
|
||||
TotalFrameCount++;
|
||||
}
|
||||
|
||||
public void StartEmulator()
|
||||
{
|
||||
if (IsRunning) return;
|
||||
IsRunning = true;
|
||||
TotalFrameCount = 0;
|
||||
|
||||
double TargetFrameTime = 1000.0 / 60.0;
|
||||
|
||||
_emulatorTask = Task.Run(() =>
|
||||
{
|
||||
_stopwatch.Restart();
|
||||
|
||||
double nextFrameTargetTime = _stopwatch.Elapsed.TotalMilliseconds + TargetFrameTime;
|
||||
double lastFpsUpdate = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
int framesThisSecond = 0;
|
||||
|
||||
while (IsRunning)
|
||||
{
|
||||
// Mark exactly when the emulator starts thinking
|
||||
double frameStartTime = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
|
||||
// 1. Do the heavy lifting (Z80 and VDP)
|
||||
_machine.RunFrame();
|
||||
|
||||
Invoke((System.Windows.Forms.MethodInvoker)delegate { DrawScreen(); });
|
||||
// 2. FIRE AND FORGET! Tell Windows to draw, but DO NOT WAIT for it to finish!
|
||||
BeginInvoke((System.Windows.Forms.MethodInvoker)delegate { DrawScreen(); });
|
||||
|
||||
// Safety catch: If we hit a breakpoint while running, stop the loop!
|
||||
// 3. Safety catch
|
||||
if (_machine.Breakpoint.HasValue && _machine.Cpu.PC == _machine.Breakpoint.Value)
|
||||
{
|
||||
IsRunning = false;
|
||||
|
||||
// Optional: Force the debugger UI to update immediately so you see it!
|
||||
Invoke((System.Windows.Forms.MethodInvoker)delegate { _debugger?.uiUpdateTimer_Tick(null, EventArgs.Empty); });
|
||||
BeginInvoke((System.Windows.Forms.MethodInvoker)delegate { _debugger?.uiUpdateTimer_Tick(null, EventArgs.Empty); });
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
||||
// 4. Calculate TRUE Frame Time (Compute Time) BEFORE we go to sleep!
|
||||
FrameTime = _stopwatch.Elapsed.TotalMilliseconds - frameStartTime;
|
||||
|
||||
// --- HIGH PRECISION THROTTLE ---
|
||||
while (_stopwatch.Elapsed.TotalMilliseconds < nextFrameTargetTime)
|
||||
{
|
||||
// Only throttle the speed if we are actively running
|
||||
Thread.Sleep(8);
|
||||
if (nextFrameTargetTime - _stopwatch.Elapsed.TotalMilliseconds > 2.0)
|
||||
{
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.SpinWait(10);
|
||||
}
|
||||
}
|
||||
|
||||
// --- METRICS MATH ---
|
||||
double currentTime = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
TotalFrameCount++;
|
||||
framesThisSecond++;
|
||||
|
||||
if (currentTime - lastFpsUpdate >= 1000.0)
|
||||
{
|
||||
FramesPerSecond = framesThisSecond / ((currentTime - lastFpsUpdate) / 1000.0);
|
||||
framesThisSecond = 0;
|
||||
lastFpsUpdate = currentTime;
|
||||
|
||||
BeginInvoke((System.Windows.Forms.MethodInvoker)delegate {
|
||||
this.Text = $"Parsons Master System - {_currentRomName} [FPS/FT: {FramesPerSecond:F0}/{FrameTime:F1}]";
|
||||
});
|
||||
}
|
||||
|
||||
nextFrameTargetTime += TargetFrameTime;
|
||||
|
||||
if (currentTime > nextFrameTargetTime + TargetFrameTime)
|
||||
{
|
||||
nextFrameTargetTime = currentTime + TargetFrameTime;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -102,8 +156,8 @@ namespace Desktop
|
||||
// 3. Jam it into the Sega Mapper
|
||||
_machine.LoadCartridge(rom);
|
||||
|
||||
// 4. Update the Window title so it looks professional
|
||||
this.Text = $"Parsons Master System 2026 - {Path.GetFileNameWithoutExtension(filePath)}";
|
||||
_currentRomName = Path.GetFileNameWithoutExtension(filePath);
|
||||
this.Text = $"Parsons Master System - {_currentRomName}";
|
||||
|
||||
// 5. Turn the power on!
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Desktop
|
||||
// To customize application configuration such as set high DPI settings or default font,
|
||||
// see https://aka.ms/applicationconfiguration.
|
||||
ApplicationConfiguration.Initialize();
|
||||
Application.Run(new Form1());
|
||||
Application.Run(new ParsonsForm1());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user