diff --git a/Core/Io/ULA.cs b/Core/Io/ULA.cs index 96afc34..451bbb3 100644 --- a/Core/Io/ULA.cs +++ b/Core/Io/ULA.cs @@ -12,6 +12,7 @@ namespace Core.Io public const int ScreenWidth = 320; public const int ScreenHeight = 256; // Perfectly cropped size public int[] FrameBuffer { get; private set; } + public int[] FrontBuffer { get; private set; } = new int[ScreenWidth * ScreenHeight]; private int _ulaFrameCount = 0; @@ -124,5 +125,10 @@ namespace Core.Io FrameBuffer[rowStartIndex + b] = currentBorderColor; } } + + public void CommitFrame() + { + Array.Copy(FrameBuffer, FrontBuffer, FrameBuffer.Length); + } } } \ No newline at end of file diff --git a/Desktop/48.rom.bak b/Desktop/48.rom.bak deleted file mode 100644 index ced65a8..0000000 Binary files a/Desktop/48.rom.bak and /dev/null differ diff --git a/Desktop/DebuggerForm.Designer.cs b/Desktop/DebuggerForm.Designer.cs index b1fc976..cbcb374 100644 --- a/Desktop/DebuggerForm.Designer.cs +++ b/Desktop/DebuggerForm.Designer.cs @@ -38,13 +38,10 @@ lblFlags = new Label(); lblTStates = new Label(); txtMemoryStart = new TextBox(); - btnStep = new Button(); btnRefreshMemory = new Button(); txtMemoryView = new RichTextBox(); lstDisassembly = new ListBox(); lstStack = new ListBox(); - btnExit = new Button(); - saveFileDialog1 = new SaveFileDialog(); label1 = new Label(); txtBreakpoint = new TextBox(); label2 = new Label(); @@ -151,17 +148,6 @@ txtMemoryStart.TextAlign = HorizontalAlignment.Center; txtMemoryStart.TextChanged += btnRefreshMemory_Click; // - // btnStep - // - btnStep.Location = new Point(6, 418); - btnStep.Margin = new Padding(2); - btnStep.Name = "btnStep"; - btnStep.Size = new Size(90, 27); - btnStep.TabIndex = 12; - btnStep.Text = "Step"; - btnStep.UseVisualStyleBackColor = true; - btnStep.Click += btnStep_Click; - // // btnRefreshMemory // btnRefreshMemory.Location = new Point(425, 21); @@ -200,16 +186,6 @@ lstStack.Size = new Size(130, 264); lstStack.TabIndex = 17; // - // btnExit - // - btnExit.Location = new Point(815, 416); - btnExit.Margin = new Padding(2); - btnExit.Name = "btnExit"; - btnExit.Size = new Size(90, 27); - btnExit.TabIndex = 18; - btnExit.Text = "Exit"; - btnExit.UseVisualStyleBackColor = true; - // // label1 // label1.AutoSize = true; @@ -276,7 +252,7 @@ // lblIE // lblIE.AutoSize = true; - lblIE.Location = new Point(200, 345); + lblIE.Location = new Point(88, 397); lblIE.Name = "lblIE"; lblIE.Size = new Size(109, 20); lblIE.TabIndex = 26; @@ -346,12 +322,10 @@ Controls.Add(label2); Controls.Add(txtBreakpoint); Controls.Add(label1); - Controls.Add(btnExit); Controls.Add(lstStack); Controls.Add(lstDisassembly); Controls.Add(txtMemoryView); Controls.Add(btnRefreshMemory); - Controls.Add(btnStep); Controls.Add(txtMemoryStart); Controls.Add(lblTStates); Controls.Add(lblFlags); @@ -379,13 +353,10 @@ private Label lblFlags; private Label lblTStates; private TextBox txtMemoryStart; - private Button btnStep; private Button btnRefreshMemory; private RichTextBox txtMemoryView; private ListBox lstStack; - private Button btnExit; public ListBox lstDisassembly; - private SaveFileDialog saveFileDialog1; private Label label1; private TextBox txtBreakpoint; private Label label2; diff --git a/Desktop/DebuggerForm.resx b/Desktop/DebuggerForm.resx index 7d0a62d..e7a282e 100644 --- a/Desktop/DebuggerForm.resx +++ b/Desktop/DebuggerForm.resx @@ -117,9 +117,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 17, 17 - 182, 17 diff --git a/Desktop/Desktop.csproj b/Desktop/Desktop.csproj index 132ab54..e936603 100644 --- a/Desktop/Desktop.csproj +++ b/Desktop/Desktop.csproj @@ -8,6 +8,44 @@ enable + + + + + + + + + + + + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + @@ -16,10 +54,4 @@ - - - PreserveNewest - - - \ No newline at end of file diff --git a/Desktop/Form1.Designer.cs b/Desktop/Form1.Designer.cs index 4e3bfdd..e0690c8 100644 --- a/Desktop/Form1.Designer.cs +++ b/Desktop/Form1.Designer.cs @@ -43,6 +43,9 @@ resetToolStripMenuItem1 = new ToolStripMenuItem(); optionsToolStripMenuItem = new ToolStripMenuItem(); HighSpeedToolStripMenuItem = new ToolStripMenuItem(); + includedToolStripMenuItem = new ToolStripMenuItem(); + tAPToolStripMenuItem1 = new ToolStripMenuItem(); + sNAToolStripMenuItem1 = new ToolStripMenuItem(); menuStrip1.SuspendLayout(); SuspendLayout(); // @@ -66,7 +69,7 @@ // // openToolStripMenuItem // - openToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { tAPToolStripMenuItem, sNAToolStripMenuItem }); + openToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { includedToolStripMenuItem, tAPToolStripMenuItem, sNAToolStripMenuItem }); openToolStripMenuItem.Name = "openToolStripMenuItem"; openToolStripMenuItem.Size = new Size(128, 26); openToolStripMenuItem.Text = "Open"; @@ -74,14 +77,14 @@ // tAPToolStripMenuItem // tAPToolStripMenuItem.Name = "tAPToolStripMenuItem"; - tAPToolStripMenuItem.Size = new Size(121, 26); + tAPToolStripMenuItem.Size = new Size(149, 26); tAPToolStripMenuItem.Text = "TAP"; tAPToolStripMenuItem.Click += loadTAPToolStripMenuItem_Click; // // sNAToolStripMenuItem // sNAToolStripMenuItem.Name = "sNAToolStripMenuItem"; - sNAToolStripMenuItem.Size = new Size(121, 26); + sNAToolStripMenuItem.Size = new Size(149, 26); sNAToolStripMenuItem.Text = "SNA"; sNAToolStripMenuItem.Click += openSNAToolStripMenuItem_Click; // @@ -116,28 +119,28 @@ // runToolStripMenuItem // runToolStripMenuItem.Name = "runToolStripMenuItem"; - runToolStripMenuItem.Size = new Size(129, 26); + runToolStripMenuItem.Size = new Size(224, 26); runToolStripMenuItem.Text = "Run"; runToolStripMenuItem.Click += btnRun_Click; // // resetToolStripMenuItem // resetToolStripMenuItem.Name = "resetToolStripMenuItem"; - resetToolStripMenuItem.Size = new Size(129, 26); + resetToolStripMenuItem.Size = new Size(224, 26); resetToolStripMenuItem.Text = "Pause"; resetToolStripMenuItem.Click += btnPause_Click; // // stepToolStripMenuItem // stepToolStripMenuItem.Name = "stepToolStripMenuItem"; - stepToolStripMenuItem.Size = new Size(129, 26); + stepToolStripMenuItem.Size = new Size(224, 26); stepToolStripMenuItem.Text = "Step"; stepToolStripMenuItem.Click += btnStep_Click; // // resetToolStripMenuItem1 // resetToolStripMenuItem1.Name = "resetToolStripMenuItem1"; - resetToolStripMenuItem1.Size = new Size(129, 26); + resetToolStripMenuItem1.Size = new Size(224, 26); resetToolStripMenuItem1.Text = "Reset"; resetToolStripMenuItem1.Click += btnReset_Click; // @@ -151,10 +154,29 @@ // HighSpeedToolStripMenuItem // HighSpeedToolStripMenuItem.Name = "HighSpeedToolStripMenuItem"; - HighSpeedToolStripMenuItem.Size = new Size(170, 26); + HighSpeedToolStripMenuItem.Size = new Size(224, 26); HighSpeedToolStripMenuItem.Text = "High Speed"; HighSpeedToolStripMenuItem.Click += btnHighSpeedToggle_Click; // + // includedToolStripMenuItem + // + includedToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { tAPToolStripMenuItem1, sNAToolStripMenuItem1 }); + includedToolStripMenuItem.Name = "includedToolStripMenuItem"; + includedToolStripMenuItem.Size = new Size(149, 26); + includedToolStripMenuItem.Text = "Included"; + // + // tAPToolStripMenuItem1 + // + tAPToolStripMenuItem1.Name = "tAPToolStripMenuItem1"; + tAPToolStripMenuItem1.Size = new Size(224, 26); + tAPToolStripMenuItem1.Text = "TAP"; + // + // sNAToolStripMenuItem1 + // + sNAToolStripMenuItem1.Name = "sNAToolStripMenuItem1"; + sNAToolStripMenuItem1.Size = new Size(224, 26); + sNAToolStripMenuItem1.Text = "SNA"; + // // Form1 // AutoScaleDimensions = new SizeF(8F, 20F); @@ -187,5 +209,8 @@ private ToolStripMenuItem resetToolStripMenuItem1; private ToolStripMenuItem optionsToolStripMenuItem; private ToolStripMenuItem HighSpeedToolStripMenuItem; + private ToolStripMenuItem includedToolStripMenuItem; + private ToolStripMenuItem tAPToolStripMenuItem1; + private ToolStripMenuItem sNAToolStripMenuItem1; } } diff --git a/Desktop/Form1.cs b/Desktop/Form1.cs index ca5a847..ab93bda 100644 --- a/Desktop/Form1.cs +++ b/Desktop/Form1.cs @@ -1,11 +1,12 @@ -using System.Drawing.Imaging; -using System.Runtime.InteropServices; -using System.Diagnostics; -using System.Threading; -using System.IO; using Core.Cpu; using Core.Io; using Core.Memory; +using System.Diagnostics; +using System.Drawing.Imaging; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; namespace Desktop { @@ -35,6 +36,7 @@ namespace Desktop public Form1() { InitializeComponent(); + PopulateIncludedTapsMenu(); this.DoubleBuffered = true; this.ResizeRedraw = true; InitializeEmulator(); @@ -94,7 +96,7 @@ namespace Desktop audioSampleCount = 0; nextScanlineTarget = TStatesPerFrame; stopwatch.Restart(); - + tapeLoaded = false; _pendingReset = false; } @@ -174,26 +176,26 @@ namespace Desktop { if (TotalFrameCount % 10 == 0) { - this.BeginInvoke((MethodInvoker)delegate + this.BeginInvoke((System.Windows.Forms.MethodInvoker)delegate { 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}"; + this.Text = $"{_baseTitle} - FPS: {FramesPerSecond:F1} - Tape Loaded: {tapeLoaded.ToString()}"; }); } } else { - this.BeginInvoke((MethodInvoker)delegate + this.BeginInvoke((System.Windows.Forms.MethodInvoker)delegate { 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}"; + this.Text = $"{_baseTitle} - FPS: {FramesPerSecond:F1} - Tape Loaded: {tapeLoaded.ToString()}"; }); } @@ -225,7 +227,7 @@ namespace Desktop catch (Exception ex) { _isPaused = true; - this.Invoke((MethodInvoker)delegate + this.Invoke((System.Windows.Forms.MethodInvoker)delegate { MessageBox.Show(ex.Message, "CPU Crash", MessageBoxButtons.OK, MessageBoxIcon.Error); @@ -234,6 +236,77 @@ namespace Desktop }); } + private void PopulateIncludedTapsMenu() + { + // 1. Get the current assembly (your .exe) + Assembly assembly = Assembly.GetExecutingAssembly(); + + // 2. Find all embedded resources + string[] resourceNames = assembly.GetManifestResourceNames(); + + foreach (string resourceName in resourceNames) + { + // Check if it is a TAP file in our TestRoms folder + // (Embedded resources use dot-notation, e.g., "Desktop.TestRoms.ZEXALL.TAP") + if (resourceName.Contains("Desktop.ROMS.TAP.") && resourceName.EndsWith(".TAP", StringComparison.OrdinalIgnoreCase)) + { + // Clean up the name for the menu (e.g., "Desktop.TestRoms.ZEXALL.TAP" -> "ZEXALL") + string[] parts = resourceName.Split('.'); + string displayName = parts[parts.Length - 2]; + + // Create the new menu item + ToolStripMenuItem item = new ToolStripMenuItem(displayName); + + // Store the full internal path in the Tag so we know what to load when clicked + item.Tag = resourceName; + + // Wire up the click event + item.Click += IncludedTapMenuItem_Click; + + // Add it to the "Open Included..." dropdown + tAPToolStripMenuItem1.DropDownItems.Add(item); + } + } + } + + private void IncludedTapMenuItem_Click(object? sender, EventArgs e) + { + if (sender is ToolStripMenuItem item && item.Tag is string resourceName) + { + _isPaused = true; + + try + { + Assembly assembly = Assembly.GetExecutingAssembly(); + + // Open a stream directly into the binary file + using (Stream? stream = assembly.GetManifestResourceStream(resourceName)) + { + if (stream == null) throw new Exception("Could not find embedded resource."); + + // Copy the binary stream into a byte array + using (MemoryStream ms = new MemoryStream()) + { + stream.CopyTo(ms); + byte[] tapBytes = ms.ToArray(); + + // Feed it directly to your existing TapManager! + _tapManager.LoadTapData(tapBytes); + tapeLoaded = true; + } + } + } + catch (Exception ex) + { + MessageBox.Show($"Failed to load built-in TAP:\n{ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + finally + { + _isPaused = false; + } + } + } + protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); @@ -326,7 +399,7 @@ namespace Desktop bmp.PixelFormat); // Pull the raw pixel data - Marshal.Copy(_ula.FrameBuffer, 0, bmpData.Scan0, _ula.FrameBuffer.Length); + Marshal.Copy(_ula.FrontBuffer, 0, bmpData.Scan0, _ula.FrontBuffer.Length); bmp.UnlockBits(bmpData); // Dispose of the old frame to prevent massive RAM leaks! @@ -388,10 +461,6 @@ namespace Desktop private void btnReset_Click(object sender, EventArgs e) { _pendingReset = true; - _isPaused = true; - _cpu.Reset(); - _memoryBus.CleanRAMData(); - _isPaused = false; } private void btnExit_Click(object sender, EventArgs e) diff --git a/Desktop/ROMS/Snapshot/ChuckieEgg.sna b/Desktop/ROMS/Snapshot/ChuckieEgg.sna new file mode 100644 index 0000000..20162ad Binary files /dev/null and b/Desktop/ROMS/Snapshot/ChuckieEgg.sna differ diff --git a/Desktop/ROMS/Snapshot/GHILL48K.sna b/Desktop/ROMS/Snapshot/GHILL48K.sna new file mode 100644 index 0000000..65609a0 Binary files /dev/null and b/Desktop/ROMS/Snapshot/GHILL48K.sna differ diff --git a/Desktop/ROMS/Snapshot/manic.sna b/Desktop/ROMS/Snapshot/manic.sna new file mode 100644 index 0000000..d8fcfa1 Binary files /dev/null and b/Desktop/ROMS/Snapshot/manic.sna differ diff --git a/Desktop/ROMS/TAP/Chuckie Egg.tap b/Desktop/ROMS/TAP/Chuckie Egg.tap new file mode 100644 index 0000000..0d18626 Binary files /dev/null and b/Desktop/ROMS/TAP/Chuckie Egg.tap differ diff --git a/Desktop/ROMS/TAP/GHILL48K.TAP b/Desktop/ROMS/TAP/GHILL48K.TAP new file mode 100644 index 0000000..dad2868 Binary files /dev/null and b/Desktop/ROMS/TAP/GHILL48K.TAP differ diff --git a/Desktop/ROMS/TAP/MANIC.TAP b/Desktop/ROMS/TAP/MANIC.TAP new file mode 100644 index 0000000..bc34199 Binary files /dev/null and b/Desktop/ROMS/TAP/MANIC.TAP differ diff --git a/Desktop/ROMS/TAP/zexall.tap b/Desktop/ROMS/TAP/zexall.tap new file mode 100644 index 0000000..1066688 Binary files /dev/null and b/Desktop/ROMS/TAP/zexall.tap differ