Got main system and VDP working! There is a display!

This commit is contained in:
2026-05-10 02:43:11 +01:00
parent 778f03b55c
commit f4e279b9c8
8 changed files with 516 additions and 104 deletions

View File

@@ -57,95 +57,95 @@
lblFrameTime = new Label();
richTextBox1 = new RichTextBox();
button1 = new Button();
button2 = new Button();
CpuRun = new Button();
SuspendLayout();
//
// lblAF
//
lblAF.AutoSize = true;
lblAF.Location = new Point(10, 7);
lblAF.Location = new Point(12, 9);
lblAF.Margin = new Padding(2, 0, 2, 0);
lblAF.Name = "lblAF";
lblAF.Size = new Size(26, 20);
lblAF.Size = new Size(33, 25);
lblAF.TabIndex = 0;
lblAF.Text = "AF";
//
// lblBC
//
lblBC.AutoSize = true;
lblBC.Location = new Point(9, 48);
lblBC.Location = new Point(11, 60);
lblBC.Margin = new Padding(2, 0, 2, 0);
lblBC.Name = "lblBC";
lblBC.Size = new Size(27, 20);
lblBC.Size = new Size(33, 25);
lblBC.TabIndex = 1;
lblBC.Text = "BC";
//
// lblDE
//
lblDE.AutoSize = true;
lblDE.Location = new Point(10, 100);
lblDE.Location = new Point(12, 125);
lblDE.Margin = new Padding(2, 0, 2, 0);
lblDE.Name = "lblDE";
lblDE.Size = new Size(28, 20);
lblDE.Size = new Size(34, 25);
lblDE.TabIndex = 2;
lblDE.Text = "DE";
//
// lblHL
//
lblHL.AutoSize = true;
lblHL.Location = new Point(10, 150);
lblHL.Location = new Point(12, 188);
lblHL.Margin = new Padding(2, 0, 2, 0);
lblHL.Name = "lblHL";
lblHL.Size = new Size(27, 20);
lblHL.Size = new Size(33, 25);
lblHL.TabIndex = 3;
lblHL.Text = "HL";
//
// lblPC
//
lblPC.AutoSize = true;
lblPC.Location = new Point(9, 200);
lblPC.Location = new Point(11, 250);
lblPC.Margin = new Padding(2, 0, 2, 0);
lblPC.Name = "lblPC";
lblPC.Size = new Size(26, 20);
lblPC.Size = new Size(33, 25);
lblPC.TabIndex = 4;
lblPC.Text = "PC";
//
// lblSP
//
lblSP.AutoSize = true;
lblSP.Location = new Point(9, 252);
lblSP.Location = new Point(11, 315);
lblSP.Margin = new Padding(2, 0, 2, 0);
lblSP.Name = "lblSP";
lblSP.Size = new Size(25, 20);
lblSP.Size = new Size(32, 25);
lblSP.TabIndex = 6;
lblSP.Text = "SP";
//
// lblFlags
//
lblFlags.AutoSize = true;
lblFlags.Location = new Point(88, 52);
lblFlags.Location = new Point(110, 65);
lblFlags.Margin = new Padding(2, 0, 2, 0);
lblFlags.Name = "lblFlags";
lblFlags.Size = new Size(43, 20);
lblFlags.Size = new Size(53, 25);
lblFlags.TabIndex = 7;
lblFlags.Text = "Flags";
//
// lblTStates
//
lblTStates.AutoSize = true;
lblTStates.Location = new Point(88, 7);
lblTStates.Location = new Point(110, 9);
lblTStates.Margin = new Padding(2, 0, 2, 0);
lblTStates.Name = "lblTStates";
lblTStates.Size = new Size(63, 20);
lblTStates.Size = new Size(75, 25);
lblTStates.TabIndex = 8;
lblTStates.Text = "T-States";
//
// txtMemoryStart
//
txtMemoryStart.Location = new Point(300, 21);
txtMemoryStart.Location = new Point(375, 26);
txtMemoryStart.Margin = new Padding(2);
txtMemoryStart.Name = "txtMemoryStart";
txtMemoryStart.Size = new Size(121, 27);
txtMemoryStart.Size = new Size(150, 31);
txtMemoryStart.TabIndex = 9;
txtMemoryStart.Text = "Memory Start";
txtMemoryStart.TextAlign = HorizontalAlignment.Center;
@@ -153,10 +153,10 @@
//
// btnRefreshMemory
//
btnRefreshMemory.Location = new Point(425, 21);
btnRefreshMemory.Location = new Point(531, 26);
btnRefreshMemory.Margin = new Padding(2);
btnRefreshMemory.Name = "btnRefreshMemory";
btnRefreshMemory.Size = new Size(90, 27);
btnRefreshMemory.Size = new Size(112, 34);
btnRefreshMemory.TabIndex = 14;
btnRefreshMemory.Text = "Refresh Memory";
btnRefreshMemory.UseVisualStyleBackColor = true;
@@ -164,109 +164,117 @@
//
// txtMemoryView
//
txtMemoryView.Location = new Point(88, 80);
txtMemoryView.Location = new Point(110, 100);
txtMemoryView.Margin = new Padding(2);
txtMemoryView.Name = "txtMemoryView";
txtMemoryView.Size = new Size(443, 895);
txtMemoryView.Size = new Size(553, 1118);
txtMemoryView.TabIndex = 15;
txtMemoryView.Text = "Memory View Window";
//
// lstDisassembly
//
lstDisassembly.FormattingEnabled = true;
lstDisassembly.Location = new Point(567, 8);
lstDisassembly.ItemHeight = 25;
lstDisassembly.Location = new Point(709, 10);
lstDisassembly.Margin = new Padding(2);
lstDisassembly.Name = "lstDisassembly";
lstDisassembly.Size = new Size(252, 264);
lstDisassembly.Size = new Size(314, 329);
lstDisassembly.TabIndex = 16;
//
// lstStack
//
lstStack.FormattingEnabled = true;
lstStack.Location = new Point(823, 8);
lstStack.ItemHeight = 25;
lstStack.Location = new Point(1029, 10);
lstStack.Margin = new Padding(2);
lstStack.Name = "lstStack";
lstStack.Size = new Size(130, 264);
lstStack.Size = new Size(162, 329);
lstStack.TabIndex = 17;
//
// label1
//
label1.AutoSize = true;
label1.Location = new Point(568, 298);
label1.Location = new Point(710, 372);
label1.Margin = new Padding(4, 0, 4, 0);
label1.Name = "label1";
label1.Size = new Size(81, 20);
label1.Size = new Size(97, 25);
label1.TabIndex = 19;
label1.Text = "Breakpoint";
//
// txtBreakpoint
//
txtBreakpoint.Location = new Point(655, 295);
txtBreakpoint.Location = new Point(819, 369);
txtBreakpoint.Margin = new Padding(4);
txtBreakpoint.Name = "txtBreakpoint";
txtBreakpoint.Size = new Size(125, 27);
txtBreakpoint.Size = new Size(155, 31);
txtBreakpoint.TabIndex = 20;
//
// label2
//
label2.AutoSize = true;
label2.Location = new Point(233, 21);
label2.Location = new Point(291, 26);
label2.Margin = new Padding(4, 0, 4, 0);
label2.Name = "label2";
label2.Size = new Size(62, 20);
label2.Size = new Size(77, 25);
label2.TabIndex = 21;
label2.Text = "Address";
//
// lblIX
//
lblIX.AutoSize = true;
lblIX.Location = new Point(9, 298);
lblIX.Location = new Point(11, 372);
lblIX.Margin = new Padding(2, 0, 2, 0);
lblIX.Name = "lblIX";
lblIX.Size = new Size(22, 20);
lblIX.Size = new Size(28, 25);
lblIX.TabIndex = 22;
lblIX.Text = "IX";
//
// lblIY
//
lblIY.AutoSize = true;
lblIY.Location = new Point(10, 344);
lblIY.Location = new Point(12, 430);
lblIY.Margin = new Padding(2, 0, 2, 0);
lblIY.Name = "lblIY";
lblIY.Size = new Size(21, 20);
lblIY.Size = new Size(27, 25);
lblIY.TabIndex = 23;
lblIY.Text = "IY";
//
// lblIff1
//
lblIff1.AutoSize = true;
lblIff1.Location = new Point(567, 411);
lblIff1.Location = new Point(709, 514);
lblIff1.Margin = new Padding(4, 0, 4, 0);
lblIff1.Name = "lblIff1";
lblIff1.Size = new Size(35, 20);
lblIff1.Size = new Size(45, 25);
lblIff1.TabIndex = 24;
lblIff1.Text = "IFF1";
//
// lblIff2
//
lblIff2.AutoSize = true;
lblIff2.Location = new Point(567, 458);
lblIff2.Location = new Point(709, 572);
lblIff2.Margin = new Padding(4, 0, 4, 0);
lblIff2.Name = "lblIff2";
lblIff2.Size = new Size(35, 20);
lblIff2.Size = new Size(45, 25);
lblIff2.TabIndex = 25;
lblIff2.Text = "IFF2";
//
// lblIE
//
lblIE.AutoSize = true;
lblIE.Location = new Point(568, 370);
lblIE.Location = new Point(710, 462);
lblIE.Margin = new Padding(4, 0, 4, 0);
lblIE.Name = "lblIE";
lblIE.Size = new Size(109, 20);
lblIE.Size = new Size(133, 25);
lblIE.TabIndex = 26;
lblIE.Text = "Interrupt Mode";
//
// btnReset
//
btnReset.Location = new Point(651, 327);
btnReset.Location = new Point(814, 409);
btnReset.Margin = new Padding(2);
btnReset.Name = "btnReset";
btnReset.Size = new Size(132, 27);
btnReset.Size = new Size(165, 34);
btnReset.TabIndex = 27;
btnReset.Text = "Set Breakpoint";
btnReset.UseVisualStyleBackColor = true;
@@ -281,69 +289,72 @@
// lblFrames
//
lblFrames.AutoSize = true;
lblFrames.Location = new Point(567, 682);
lblFrames.Location = new Point(709, 852);
lblFrames.Margin = new Padding(2, 0, 2, 0);
lblFrames.Name = "lblFrames";
lblFrames.Size = new Size(124, 20);
lblFrames.Size = new Size(149, 25);
lblFrames.TabIndex = 28;
lblFrames.Text = "Frames Rendered";
//
// lblFPS
//
lblFPS.AutoSize = true;
lblFPS.Location = new Point(659, 759);
lblFPS.Location = new Point(824, 949);
lblFPS.Margin = new Padding(2, 0, 2, 0);
lblFPS.Name = "lblFPS";
lblFPS.Size = new Size(32, 20);
lblFPS.Size = new Size(41, 25);
lblFPS.TabIndex = 29;
lblFPS.Text = "FPS";
//
// lblFrameTime
//
lblFrameTime.AutoSize = true;
lblFrameTime.Location = new Point(604, 718);
lblFrameTime.Location = new Point(755, 898);
lblFrameTime.Margin = new Padding(2, 0, 2, 0);
lblFrameTime.Name = "lblFrameTime";
lblFrameTime.Size = new Size(87, 20);
lblFrameTime.Size = new Size(104, 25);
lblFrameTime.TabIndex = 30;
lblFrameTime.Text = "Frame Time";
//
// richTextBox1
//
richTextBox1.Enabled = false;
richTextBox1.Location = new Point(567, 509);
richTextBox1.Location = new Point(709, 636);
richTextBox1.Margin = new Padding(4);
richTextBox1.Name = "richTextBox1";
richTextBox1.ReadOnly = true;
richTextBox1.Size = new Size(304, 128);
richTextBox1.Size = new Size(379, 159);
richTextBox1.TabIndex = 32;
richTextBox1.Text = "Sega Master System Memory Map:\n0x0000 - 0x3FFF: ROM Slot 0 (16KB)\n0x4000 - 0x7FFF: ROM Slot 1 (16KB)\n0x8000 - 0xBFFF: ROM Slot 2 (16KB)\n0xC000 - 0xDFFF: System RAM (8KB)\n0xE000 - 0xFFFF: RAM Mirror";
//
// button1
//
button1.Location = new Point(555, 824);
button1.Location = new Point(694, 1030);
button1.Margin = new Padding(4);
button1.Name = "button1";
button1.Size = new Size(94, 29);
button1.Size = new Size(118, 36);
button1.TabIndex = 33;
button1.Text = "CPU Step";
button1.UseVisualStyleBackColor = true;
button1.Click += btnStep_Click;
//
// button2
// CpuRun
//
button2.Location = new Point(555, 883);
button2.Name = "button2";
button2.Size = new Size(94, 29);
button2.TabIndex = 34;
button2.Text = "CPU Run";
button2.UseVisualStyleBackColor = true;
button2.Click += btnStep_Click;
CpuRun.Location = new Point(694, 1104);
CpuRun.Margin = new Padding(4);
CpuRun.Name = "CpuRun";
CpuRun.Size = new Size(118, 36);
CpuRun.TabIndex = 34;
CpuRun.Text = "CPU Run";
CpuRun.UseVisualStyleBackColor = true;
CpuRun.Click += CpuRun_Click;
//
// DebuggerForm
//
AutoScaleDimensions = new SizeF(8F, 20F);
AutoScaleDimensions = new SizeF(10F, 25F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(965, 990);
Controls.Add(button2);
ClientSize = new Size(1206, 1238);
Controls.Add(CpuRun);
Controls.Add(button1);
Controls.Add(richTextBox1);
Controls.Add(lblFrameTime);
@@ -402,13 +413,13 @@
private Label lblIff2;
private Label lblIE;
private Button btnReset;
private System.Windows.Forms.Timer uiUpdateTimer;
private Label lblFrames;
private Label lblFPS;
private Label lblFrameTime;
private RichTextBox richTextBox1;
private Button button1;
private Button button2;
private Button CpuRun;
public System.Windows.Forms.Timer uiUpdateTimer;
//private TextBox textBox4;
}
}

View File

@@ -27,11 +27,36 @@ namespace Desktop
_mainForm = mainForm;
}
private void CpuRun_Click(object sender, EventArgs e)
{
if (_mainForm.IsRunning)
{
// Stop the machine
_mainForm.StopEmulator();
CpuRun.Text = "CPU Run";
// Stop the live UI updates and do one final manual refresh
uiUpdateTimer.Stop();
UpdateDisplay();
}
else
{
// Start the machine
_mainForm.StartEmulator();
CpuRun.Text = "CPU Stop";
// Start the timer so the debugger screen updates automatically
// (Make sure your uiUpdateTimer Interval in the designer is set to something like 100ms)
uiUpdateTimer.Start();
}
}
private void btnStep_Click(object sender, EventArgs e)
{
try
{
_cpu.Step();
// Ask the main form to step the WHOLE machine, not just the Z80!
_mainForm.StepEmulator();
UpdateDisplay();
}
catch (Exception ex)
@@ -57,7 +82,7 @@ namespace Desktop
UpdateDisplay();
}
private void uiUpdateTimer_Tick(object sender, EventArgs e)
public void uiUpdateTimer_Tick(object sender, EventArgs e)
{
UpdateDisplay();
}
@@ -180,6 +205,9 @@ namespace Desktop
case 0x02: mnemonic = "LD (BC), A"; break;
// --- 16-Bit Increments ---
case 0x03: mnemonic = "INC BC"; break;
case 0x07:
mnemonic = "RLCA";
break;
case 0x08:
mnemonic = "EX AF, AF'";
break;

View File

@@ -29,32 +29,48 @@
private void InitializeComponent()
{
button1 = new Button();
pbScreen = new PictureBox();
((System.ComponentModel.ISupportInitialize)pbScreen).BeginInit();
SuspendLayout();
//
// button1
//
button1.Location = new Point(304, 268);
button1.Location = new Point(1294, 13);
button1.Margin = new Padding(4, 4, 4, 4);
button1.Name = "button1";
button1.Size = new Size(94, 29);
button1.Size = new Size(118, 36);
button1.TabIndex = 0;
button1.Text = "button1";
button1.UseVisualStyleBackColor = true;
button1.Click += button1_Click;
//
// pbScreen
//
pbScreen.Location = new Point(23, 59);
pbScreen.Name = "pbScreen";
pbScreen.Size = new Size(1390, 760);
pbScreen.SizeMode = PictureBoxSizeMode.Zoom;
pbScreen.TabIndex = 1;
pbScreen.TabStop = false;
//
// Form1
//
AutoScaleDimensions = new SizeF(8F, 20F);
AutoScaleDimensions = new SizeF(10F, 25F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(800, 450);
ClientSize = new Size(1425, 842);
Controls.Add(pbScreen);
Controls.Add(button1);
Margin = new Padding(4, 4, 4, 4);
Name = "Form1";
Text = "Form1";
Click += button1_Click;
((System.ComponentModel.ISupportInitialize)pbScreen).EndInit();
ResumeLayout(false);
}
#endregion
private Button button1;
private PictureBox pbScreen;
}
}

View File

@@ -1,12 +1,21 @@
using System.Reflection;
using System.Reflection.PortableExecutable;
using Core;
using System.Threading.Tasks;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Desktop
{
public partial class Form1 : Form
{
private SmsMachine _machine = null!;
private DebuggerForm _debugger;
private Bitmap _screenBitmap = new Bitmap(256, 192, PixelFormat.Format32bppArgb);
public bool IsRunning { get; private set; } = false;
public ushort? Breakpoint
{
@@ -20,23 +29,67 @@ namespace Desktop
_machine = new SmsMachine();
}
private void DrawScreen()
{
// Rapidly copy our VDP FrameBuffer into the Windows Bitmap
var data = _screenBitmap.LockBits(new Rectangle(0, 0, 256, 192), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
Marshal.Copy(_machine.VideoProcessor.FrameBuffer, 0, data.Scan0, _machine.VideoProcessor.FrameBuffer.Length);
_screenBitmap.UnlockBits(data);
// Update the PictureBox
pbScreen.Image = _screenBitmap;
}
public void StartEmulator()
{
if (IsRunning) return;
IsRunning = true;
// Fire off a background task so we don't freeze the Windows UI!
Task.Run(() =>
{
while (IsRunning)
{
_machine.RunFrame();
Invoke((System.Windows.Forms.MethodInvoker)delegate { DrawScreen(); });
// Safety catch: If we hit a breakpoint while running, stop the loop!
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); });
}
else
{
// Only throttle the speed if we are actively running
Thread.Sleep(16);
}
}
});
}
public void StopEmulator()
{
IsRunning = false;
}
public void StepEmulator()
{
_machine.StepMachine();
}
private void button1_Click(object sender, EventArgs e)
{
// 1. Load a commercial Master System ROM!
byte[] rom = File.ReadAllBytes(@"C:\Parsons\Local Code Projects\ParsonsMasterSystem2026\Desktop\ROMS\Golden Axe Warrior.sms");
try
{
// 2. Jam it into the Sega Mapper
_machine.LoadCartridge(rom);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
// 3. Open the Debugger to look around
if (_debugger == null || _debugger.IsDisposed)