Updated graphics renderer to allow for pixel perfect resizing
This commit is contained in:
18
Desktop/Form1.Designer.cs
generated
18
Desktop/Form1.Designer.cs
generated
@@ -28,7 +28,6 @@
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
picScreen = new PictureBox();
|
||||
menuStrip1 = new MenuStrip();
|
||||
fileToolStripMenuItem = new ToolStripMenuItem();
|
||||
openToolStripMenuItem = new ToolStripMenuItem();
|
||||
@@ -44,20 +43,9 @@
|
||||
resetToolStripMenuItem1 = new ToolStripMenuItem();
|
||||
optionsToolStripMenuItem = new ToolStripMenuItem();
|
||||
HighSpeedToolStripMenuItem = new ToolStripMenuItem();
|
||||
((System.ComponentModel.ISupportInitialize)picScreen).BeginInit();
|
||||
menuStrip1.SuspendLayout();
|
||||
SuspendLayout();
|
||||
//
|
||||
// picScreen
|
||||
//
|
||||
picScreen.BackColor = Color.Black;
|
||||
picScreen.Location = new Point(10, 26);
|
||||
picScreen.Name = "picScreen";
|
||||
picScreen.Size = new Size(720, 576);
|
||||
picScreen.SizeMode = PictureBoxSizeMode.Zoom;
|
||||
picScreen.TabIndex = 0;
|
||||
picScreen.TabStop = false;
|
||||
//
|
||||
// menuStrip1
|
||||
//
|
||||
menuStrip1.ImageScalingSize = new Size(24, 24);
|
||||
@@ -163,7 +151,7 @@
|
||||
// HighSpeedToolStripMenuItem
|
||||
//
|
||||
HighSpeedToolStripMenuItem.Name = "HighSpeedToolStripMenuItem";
|
||||
HighSpeedToolStripMenuItem.Size = new Size(224, 26);
|
||||
HighSpeedToolStripMenuItem.Size = new Size(170, 26);
|
||||
HighSpeedToolStripMenuItem.Text = "High Speed";
|
||||
HighSpeedToolStripMenuItem.Click += btnHighSpeedToggle_Click;
|
||||
//
|
||||
@@ -172,13 +160,11 @@
|
||||
AutoScaleDimensions = new SizeF(8F, 20F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
ClientSize = new Size(738, 608);
|
||||
Controls.Add(picScreen);
|
||||
Controls.Add(menuStrip1);
|
||||
KeyPreview = true;
|
||||
MainMenuStrip = menuStrip1;
|
||||
Name = "Form1";
|
||||
Text = "Parsons Sinclair ZX Spectrum 48K - 2026";
|
||||
((System.ComponentModel.ISupportInitialize)picScreen).EndInit();
|
||||
menuStrip1.ResumeLayout(false);
|
||||
menuStrip1.PerformLayout();
|
||||
ResumeLayout(false);
|
||||
@@ -186,8 +172,6 @@
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private PictureBox picScreen;
|
||||
private MenuStrip menuStrip1;
|
||||
private ToolStripMenuItem fileToolStripMenuItem;
|
||||
private ToolStripMenuItem openToolStripMenuItem;
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace Desktop
|
||||
private TapManager _tapManager = null!;
|
||||
private DebuggerForm? _debugger = null;
|
||||
private BeeperDevice _beeper = null!;
|
||||
private Bitmap _screenBitmap = null!;
|
||||
private string _baseTitle = "";
|
||||
private bool _isRunning = false;
|
||||
private bool _isPaused = false;
|
||||
@@ -34,6 +35,8 @@ namespace Desktop
|
||||
public Form1()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.DoubleBuffered = true;
|
||||
this.ResizeRedraw = true;
|
||||
InitializeEmulator();
|
||||
}
|
||||
|
||||
@@ -173,7 +176,10 @@ namespace Desktop
|
||||
{
|
||||
this.BeginInvoke((MethodInvoker)delegate
|
||||
{
|
||||
UpdateScreenBitmap();
|
||||
UpdateScreenBitmap(); // Your existing method that writes the ULA data to _screenBitmap
|
||||
|
||||
this.Invalidate(); // Tells Windows: "The bitmap changed, please run OnPaint()!"
|
||||
|
||||
this.Text = $"{_baseTitle} - FPS: {FramesPerSecond:F1}";
|
||||
});
|
||||
}
|
||||
@@ -181,10 +187,13 @@ namespace Desktop
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Invoke((MethodInvoker)delegate
|
||||
this.BeginInvoke((MethodInvoker)delegate
|
||||
{
|
||||
UpdateScreenBitmap();
|
||||
this.Text = $"{_baseTitle} - FPS: {FramesPerSecond:F1} - Tape Loaded: {tapeLoaded.ToString()}";
|
||||
UpdateScreenBitmap(); // Your existing method that writes the ULA data to _screenBitmap
|
||||
|
||||
this.Invalidate(); // Tells Windows: "The bitmap changed, please run OnPaint()!"
|
||||
|
||||
this.Text = $"{_baseTitle} - FPS: {FramesPerSecond:F1}";
|
||||
});
|
||||
}
|
||||
|
||||
@@ -225,6 +234,40 @@ namespace Desktop
|
||||
});
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
base.OnPaint(e);
|
||||
|
||||
// If we don't have a screen bitmap yet, just paint the background black and exit
|
||||
if (_screenBitmap == null)
|
||||
{
|
||||
e.Graphics.Clear(Color.Black);
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. Calculate the scaling factor to fit the window while preserving aspect ratio
|
||||
float scaleX = (float)this.ClientSize.Width / _screenBitmap.Width;
|
||||
float scaleY = (float)this.ClientSize.Height / _screenBitmap.Height;
|
||||
float scale = Math.Min(scaleX, scaleY); // Pick the smallest scale so it fits inside
|
||||
|
||||
int newWidth = (int)(_screenBitmap.Width * scale);
|
||||
int newHeight = (int)(_screenBitmap.Height * scale);
|
||||
|
||||
// 2. Center the image horizontally and vertically (Pillarboxing/Letterboxing)
|
||||
int posX = (this.ClientSize.Width - newWidth) / 2;
|
||||
int posY = (this.ClientSize.Height - newHeight) / 2;
|
||||
|
||||
// 3. RETRO MAGIC: Force Nearest-Neighbor interpolation for razor-sharp pixels!
|
||||
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
|
||||
|
||||
// PixelOffsetMode.Half is a GDI+ trick required to make NearestNeighbor perfectly accurate
|
||||
e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
|
||||
|
||||
// 4. Paint the black borders (if any) and draw the screen
|
||||
e.Graphics.Clear(Color.Black);
|
||||
e.Graphics.DrawImage(_screenBitmap, posX, posY, newWidth, newHeight);
|
||||
}
|
||||
|
||||
private void HandleInstantTapeLoad()
|
||||
{
|
||||
byte[] block = _tapManager.GetNextBlock(); // Your original Queue.Dequeue() method
|
||||
@@ -286,8 +329,14 @@ namespace Desktop
|
||||
Marshal.Copy(_ula.FrameBuffer, 0, bmpData.Scan0, _ula.FrameBuffer.Length);
|
||||
bmp.UnlockBits(bmpData);
|
||||
|
||||
if (picScreen.Image != null) picScreen.Image.Dispose();
|
||||
picScreen.Image = bmp;
|
||||
// Dispose of the old frame to prevent massive RAM leaks!
|
||||
if (_screenBitmap != null)
|
||||
{
|
||||
_screenBitmap.Dispose();
|
||||
}
|
||||
|
||||
// Save the new frame so OnPaint() can draw it
|
||||
_screenBitmap = bmp;
|
||||
}
|
||||
|
||||
private void loadTAPToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
|
||||
Reference in New Issue
Block a user