diff --git a/Desktop/Desktop.csproj b/Desktop/Desktop.csproj index 9785458..57d37e0 100644 --- a/Desktop/Desktop.csproj +++ b/Desktop/Desktop.csproj @@ -14,9 +14,9 @@ - - - + + + @@ -36,13 +36,13 @@ Always - + Always - + Always - + Always diff --git a/Desktop/Form1.Designer.cs b/Desktop/Form1.Designer.cs index e0690c8..0a8fef2 100644 --- a/Desktop/Form1.Designer.cs +++ b/Desktop/Form1.Designer.cs @@ -31,6 +31,9 @@ menuStrip1 = new MenuStrip(); fileToolStripMenuItem = new ToolStripMenuItem(); openToolStripMenuItem = new ToolStripMenuItem(); + includedToolStripMenuItem = new ToolStripMenuItem(); + tAPToolStripMenuItem1 = new ToolStripMenuItem(); + sNAToolStripMenuItem1 = new ToolStripMenuItem(); tAPToolStripMenuItem = new ToolStripMenuItem(); sNAToolStripMenuItem = new ToolStripMenuItem(); exitToolStripMenuItem = new ToolStripMenuItem(); @@ -43,16 +46,14 @@ resetToolStripMenuItem1 = new ToolStripMenuItem(); optionsToolStripMenuItem = new ToolStripMenuItem(); HighSpeedToolStripMenuItem = new ToolStripMenuItem(); - includedToolStripMenuItem = new ToolStripMenuItem(); - tAPToolStripMenuItem1 = new ToolStripMenuItem(); - sNAToolStripMenuItem1 = new ToolStripMenuItem(); + saveSnapshotToolStripMenuItem = new ToolStripMenuItem(); menuStrip1.SuspendLayout(); SuspendLayout(); // // menuStrip1 // menuStrip1.ImageScalingSize = new Size(24, 24); - menuStrip1.Items.AddRange(new ToolStripItem[] { fileToolStripMenuItem, viewToolStripMenuItem, machineToolStripMenuItem, optionsToolStripMenuItem }); + menuStrip1.Items.AddRange(new ToolStripItem[] { fileToolStripMenuItem, machineToolStripMenuItem, viewToolStripMenuItem, optionsToolStripMenuItem }); menuStrip1.Location = new Point(0, 0); menuStrip1.Name = "menuStrip1"; menuStrip1.Padding = new Padding(5, 2, 0, 2); @@ -62,7 +63,7 @@ // // fileToolStripMenuItem // - fileToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { openToolStripMenuItem, exitToolStripMenuItem }); + fileToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { openToolStripMenuItem, saveSnapshotToolStripMenuItem, exitToolStripMenuItem }); fileToolStripMenuItem.Name = "fileToolStripMenuItem"; fileToolStripMenuItem.Size = new Size(46, 24); fileToolStripMenuItem.Text = "File"; @@ -71,9 +72,28 @@ // openToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { includedToolStripMenuItem, tAPToolStripMenuItem, sNAToolStripMenuItem }); openToolStripMenuItem.Name = "openToolStripMenuItem"; - openToolStripMenuItem.Size = new Size(128, 26); + openToolStripMenuItem.Size = new Size(224, 26); openToolStripMenuItem.Text = "Open"; // + // 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(121, 26); + tAPToolStripMenuItem1.Text = "TAP"; + // + // sNAToolStripMenuItem1 + // + sNAToolStripMenuItem1.Name = "sNAToolStripMenuItem1"; + sNAToolStripMenuItem1.Size = new Size(121, 26); + sNAToolStripMenuItem1.Text = "SNA"; + // // tAPToolStripMenuItem // tAPToolStripMenuItem.Name = "tAPToolStripMenuItem"; @@ -91,7 +111,7 @@ // exitToolStripMenuItem // exitToolStripMenuItem.Name = "exitToolStripMenuItem"; - exitToolStripMenuItem.Size = new Size(128, 26); + exitToolStripMenuItem.Size = new Size(224, 26); exitToolStripMenuItem.Text = "Exit"; exitToolStripMenuItem.Click += btnExit_Click; // @@ -154,28 +174,16 @@ // HighSpeedToolStripMenuItem // HighSpeedToolStripMenuItem.Name = "HighSpeedToolStripMenuItem"; - HighSpeedToolStripMenuItem.Size = new Size(224, 26); + HighSpeedToolStripMenuItem.Size = new Size(170, 26); HighSpeedToolStripMenuItem.Text = "High Speed"; HighSpeedToolStripMenuItem.Click += btnHighSpeedToggle_Click; // - // includedToolStripMenuItem + // saveSnapshotToolStripMenuItem // - 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"; + saveSnapshotToolStripMenuItem.Name = "saveSnapshotToolStripMenuItem"; + saveSnapshotToolStripMenuItem.Size = new Size(224, 26); + saveSnapshotToolStripMenuItem.Text = "Save Snapshot"; + saveSnapshotToolStripMenuItem.Click += SaveSNAMenuItem_Click; // // Form1 // @@ -212,5 +220,6 @@ private ToolStripMenuItem includedToolStripMenuItem; private ToolStripMenuItem tAPToolStripMenuItem1; private ToolStripMenuItem sNAToolStripMenuItem1; + private ToolStripMenuItem saveSnapshotToolStripMenuItem; } } diff --git a/Desktop/Form1.cs b/Desktop/Form1.cs index ceb6f81..2ea7136 100644 --- a/Desktop/Form1.cs +++ b/Desktop/Form1.cs @@ -237,6 +237,69 @@ namespace Desktop }); } + private void SaveSNAMenuItem_Click(object? sender, EventArgs e) + { + _isPaused = true; + using (SaveFileDialog sfd = new SaveFileDialog()) + { + sfd.Filter = "Spectrum SNA Files|*.sna"; + if (sfd.ShowDialog() == DialogResult.OK) + { + SaveSNA(sfd.FileName); + } + } + _isPaused = false; + } + + public void SaveSNA(string filepath) + { + // 0. Back up the live state BEFORE modifying it + ushort originalSP = _cpu.SP; + byte originalMemLow = _memoryBus.Read((ushort)(_cpu.SP - 2)); + byte originalMemHigh = _memoryBus.Read((ushort)(_cpu.SP - 1)); + + // 1. We must push the PC onto the stack before saving! + _cpu.SP -= 2; + _memoryBus.Write(_cpu.SP, (byte)(_cpu.PC & 0xFF)); // Low byte + _memoryBus.Write((ushort)(_cpu.SP + 1), (byte)(_cpu.PC >> 8)); // High byte + + using (FileStream fs = new FileStream(filepath, FileMode.Create)) + using (BinaryWriter bw = new BinaryWriter(fs)) + { + // 2. Write the 27-byte Header + bw.Write(_cpu.I); + bw.Write(_cpu.HL_Prime.Low); bw.Write(_cpu.HL_Prime.High); + bw.Write(_cpu.DE_Prime.Low); bw.Write(_cpu.DE_Prime.High); + bw.Write(_cpu.BC_Prime.Low); bw.Write(_cpu.BC_Prime.High); + bw.Write(_cpu.AF_Prime.Low); bw.Write(_cpu.AF_Prime.High); + + bw.Write(_cpu.HL.Low); bw.Write(_cpu.HL.High); + bw.Write(_cpu.DE.Low); bw.Write(_cpu.DE.High); + bw.Write(_cpu.BC.Low); bw.Write(_cpu.BC.High); + bw.Write(_cpu.IY.Low); bw.Write(_cpu.IY.High); + bw.Write(_cpu.IX.Low); bw.Write(_cpu.IX.High); + + // IFF2 determines the interrupt state in SNA + bw.Write((byte)(_cpu.IFF2 ? 0x04 : 0x00)); + bw.Write(_cpu.R); + bw.Write(_cpu.AF.Low); bw.Write(_cpu.AF.High); + bw.Write((byte)(_cpu.SP & 0xFF)); bw.Write((byte)(_cpu.SP >> 8)); + bw.Write((byte)_cpu.InterruptMode); + bw.Write(_simpleIoBus.BorderColorIndex); + + // 3. Dump the 48K RAM + for (int i = 0x4000; i <= 0xFFFF; i++) + { + bw.Write(_memoryBus.Read((ushort)i)); + } + } + + // 4. RESTORE the emulator's state so the game can resume safely + _cpu.SP = originalSP; + _memoryBus.Write((ushort)(originalSP - 2), originalMemLow); + _memoryBus.Write((ushort)(originalSP - 1), originalMemHigh); + } + private void PopulateIncludedTapsMenu() { // 1. Get the current assembly (your .exe) diff --git a/Desktop/ROMS/TAP/DizzyB-TreasureIsland.tap b/Desktop/ROMS/TAP/DizzyB-TreasureIsland.tap deleted file mode 100644 index d839ef5..0000000 Binary files a/Desktop/ROMS/TAP/DizzyB-TreasureIsland.tap and /dev/null differ diff --git a/Desktop/ROMS/TAP/GHILL48K.TAP b/Desktop/ROMS/TAP/Grange Hill.TAP similarity index 100% rename from Desktop/ROMS/TAP/GHILL48K.TAP rename to Desktop/ROMS/TAP/Grange Hill.TAP diff --git a/Desktop/ROMS/TAP/MANIC.TAP b/Desktop/ROMS/TAP/Manic Miner.TAP similarity index 100% rename from Desktop/ROMS/TAP/MANIC.TAP rename to Desktop/ROMS/TAP/Manic Miner.TAP diff --git a/Desktop/ROMS/TAP/Treasure Island - Dizzy.tap b/Desktop/ROMS/TAP/Treasure Island - Dizzy.tap new file mode 100644 index 0000000..43012a7 Binary files /dev/null and b/Desktop/ROMS/TAP/Treasure Island - Dizzy.tap differ