Fixed fast and slow tape loading and play_stop tape
This commit is contained in:
@@ -145,10 +145,24 @@ namespace Core.Io
|
||||
CalculateNextDataPulse();
|
||||
}
|
||||
break;
|
||||
|
||||
//case TapeState.Pause:
|
||||
// // The .TAP Format Auto-Stop Heuristic:
|
||||
// if (_currentBlock != null && _currentBlock.Length > 0 && _currentBlock[0] == 0x00)
|
||||
// {
|
||||
// // 1. It was a Header block. The ROM is waiting for the Data right now! Keep spinning.
|
||||
// LoadNextBlock();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // 2. It was a Data block (or custom). The "file" is done.
|
||||
// // Auto-Stop the tape deck so we don't accidentally play the next level into the void.
|
||||
// _state = TapeState.Idle;
|
||||
// _currentBlock = null;
|
||||
// }
|
||||
// break;
|
||||
case TapeState.Pause:
|
||||
_state = TapeState.Idle;
|
||||
//LoadNextBlock();
|
||||
LoadNextBlock();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -170,12 +184,14 @@ namespace Core.Io
|
||||
|
||||
//public bool HasBlocks => _blocks.Count > 0;
|
||||
// Change this line:
|
||||
public bool HasBlocks => _blocks.Count > 0 || _currentBlock != null;
|
||||
//public bool HasBlocks => _blocks.Count > 0 || _currentBlock != null;
|
||||
// Only consider _currentBlock valid if we are actively playing it!
|
||||
public bool HasBlocks => _blocks.Count > 0 || (_currentBlock != null && _state != TapeState.Idle && _state != TapeState.Pause);
|
||||
|
||||
public byte[] GetNextBlock()
|
||||
{
|
||||
// If a block is loaded into the tape deck, yank it immediately
|
||||
if (_currentBlock != null)
|
||||
// Yank the current block ONLY if it is actively playing
|
||||
if (_currentBlock != null && _state != TapeState.Idle && _state != TapeState.Pause)
|
||||
{
|
||||
byte[] blockToReturn = _currentBlock;
|
||||
_state = TapeState.Idle; // Ensure the tape deck is stopped
|
||||
@@ -183,7 +199,9 @@ namespace Core.Io
|
||||
return blockToReturn;
|
||||
}
|
||||
|
||||
// Otherwise, pull directly from the queue
|
||||
// Otherwise, pull directly from the unplayed queue
|
||||
_state = TapeState.Idle; // Stop the tape deck just in case
|
||||
_currentBlock = null;
|
||||
return _blocks.Count > 0 ? _blocks.Dequeue() : null;
|
||||
}
|
||||
}
|
||||
|
||||
39
Desktop/DebuggerForm.Designer.cs
generated
39
Desktop/DebuggerForm.Designer.cs
generated
@@ -55,6 +55,7 @@
|
||||
lblFrames = new Label();
|
||||
lblFPS = new Label();
|
||||
lblFrameTime = new Label();
|
||||
richTextBox1 = new RichTextBox();
|
||||
SuspendLayout();
|
||||
//
|
||||
// lblAF
|
||||
@@ -164,14 +165,14 @@
|
||||
txtMemoryView.Location = new Point(88, 80);
|
||||
txtMemoryView.Margin = new Padding(2);
|
||||
txtMemoryView.Name = "txtMemoryView";
|
||||
txtMemoryView.Size = new Size(416, 195);
|
||||
txtMemoryView.Size = new Size(443, 895);
|
||||
txtMemoryView.TabIndex = 15;
|
||||
txtMemoryView.Text = "Memory View Window";
|
||||
//
|
||||
// lstDisassembly
|
||||
//
|
||||
lstDisassembly.FormattingEnabled = true;
|
||||
lstDisassembly.Location = new Point(523, 11);
|
||||
lstDisassembly.Location = new Point(567, 8);
|
||||
lstDisassembly.Margin = new Padding(2);
|
||||
lstDisassembly.Name = "lstDisassembly";
|
||||
lstDisassembly.Size = new Size(252, 264);
|
||||
@@ -180,7 +181,7 @@
|
||||
// lstStack
|
||||
//
|
||||
lstStack.FormattingEnabled = true;
|
||||
lstStack.Location = new Point(779, 11);
|
||||
lstStack.Location = new Point(823, 8);
|
||||
lstStack.Margin = new Padding(2);
|
||||
lstStack.Name = "lstStack";
|
||||
lstStack.Size = new Size(130, 264);
|
||||
@@ -189,7 +190,7 @@
|
||||
// label1
|
||||
//
|
||||
label1.AutoSize = true;
|
||||
label1.Location = new Point(289, 284);
|
||||
label1.Location = new Point(568, 298);
|
||||
label1.Name = "label1";
|
||||
label1.Size = new Size(81, 20);
|
||||
label1.TabIndex = 19;
|
||||
@@ -197,7 +198,7 @@
|
||||
//
|
||||
// txtBreakpoint
|
||||
//
|
||||
txtBreakpoint.Location = new Point(376, 281);
|
||||
txtBreakpoint.Location = new Point(655, 295);
|
||||
txtBreakpoint.Name = "txtBreakpoint";
|
||||
txtBreakpoint.Size = new Size(125, 27);
|
||||
txtBreakpoint.TabIndex = 20;
|
||||
@@ -234,7 +235,7 @@
|
||||
// lblIff1
|
||||
//
|
||||
lblIff1.AutoSize = true;
|
||||
lblIff1.Location = new Point(88, 298);
|
||||
lblIff1.Location = new Point(567, 411);
|
||||
lblIff1.Name = "lblIff1";
|
||||
lblIff1.Size = new Size(35, 20);
|
||||
lblIff1.TabIndex = 24;
|
||||
@@ -243,7 +244,7 @@
|
||||
// lblIff2
|
||||
//
|
||||
lblIff2.AutoSize = true;
|
||||
lblIff2.Location = new Point(88, 345);
|
||||
lblIff2.Location = new Point(567, 458);
|
||||
lblIff2.Name = "lblIff2";
|
||||
lblIff2.Size = new Size(35, 20);
|
||||
lblIff2.TabIndex = 25;
|
||||
@@ -252,7 +253,7 @@
|
||||
// lblIE
|
||||
//
|
||||
lblIE.AutoSize = true;
|
||||
lblIE.Location = new Point(88, 397);
|
||||
lblIE.Location = new Point(568, 370);
|
||||
lblIE.Name = "lblIE";
|
||||
lblIE.Size = new Size(109, 20);
|
||||
lblIE.TabIndex = 26;
|
||||
@@ -260,7 +261,7 @@
|
||||
//
|
||||
// btnReset
|
||||
//
|
||||
btnReset.Location = new Point(372, 313);
|
||||
btnReset.Location = new Point(651, 327);
|
||||
btnReset.Margin = new Padding(2);
|
||||
btnReset.Name = "btnReset";
|
||||
btnReset.Size = new Size(132, 27);
|
||||
@@ -278,7 +279,7 @@
|
||||
// lblFrames
|
||||
//
|
||||
lblFrames.AutoSize = true;
|
||||
lblFrames.Location = new Point(538, 320);
|
||||
lblFrames.Location = new Point(568, 651);
|
||||
lblFrames.Margin = new Padding(2, 0, 2, 0);
|
||||
lblFrames.Name = "lblFrames";
|
||||
lblFrames.Size = new Size(124, 20);
|
||||
@@ -288,7 +289,7 @@
|
||||
// lblFPS
|
||||
//
|
||||
lblFPS.AutoSize = true;
|
||||
lblFPS.Location = new Point(630, 397);
|
||||
lblFPS.Location = new Point(660, 728);
|
||||
lblFPS.Margin = new Padding(2, 0, 2, 0);
|
||||
lblFPS.Name = "lblFPS";
|
||||
lblFPS.Size = new Size(32, 20);
|
||||
@@ -298,18 +299,29 @@
|
||||
// lblFrameTime
|
||||
//
|
||||
lblFrameTime.AutoSize = true;
|
||||
lblFrameTime.Location = new Point(575, 356);
|
||||
lblFrameTime.Location = new Point(605, 687);
|
||||
lblFrameTime.Margin = new Padding(2, 0, 2, 0);
|
||||
lblFrameTime.Name = "lblFrameTime";
|
||||
lblFrameTime.Size = new Size(87, 20);
|
||||
lblFrameTime.TabIndex = 30;
|
||||
lblFrameTime.Text = "Frame Time";
|
||||
//
|
||||
// richTextBox1
|
||||
//
|
||||
richTextBox1.Enabled = false;
|
||||
richTextBox1.Location = new Point(568, 500);
|
||||
richTextBox1.Name = "richTextBox1";
|
||||
richTextBox1.ReadOnly = true;
|
||||
richTextBox1.Size = new Size(304, 113);
|
||||
richTextBox1.TabIndex = 32;
|
||||
richTextBox1.Text = "ZX Spectrum 48K Memory Map:\n0x0000 - 0x3FFF: ROM (16KB)\n0x4000 - 0x57FF: Display File (Screen Pixels)\n0x5800 - 0x5AFF: Colour Attributes\n0x5B00 - 0xFFFF: General Purpose RAM";
|
||||
//
|
||||
// DebuggerForm
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(8F, 20F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
ClientSize = new Size(928, 454);
|
||||
ClientSize = new Size(965, 990);
|
||||
Controls.Add(richTextBox1);
|
||||
Controls.Add(lblFrameTime);
|
||||
Controls.Add(lblFPS);
|
||||
Controls.Add(lblFrames);
|
||||
@@ -370,6 +382,7 @@
|
||||
private Label lblFrames;
|
||||
private Label lblFPS;
|
||||
private Label lblFrameTime;
|
||||
private RichTextBox richTextBox1;
|
||||
//private TextBox textBox4;
|
||||
}
|
||||
}
|
||||
@@ -88,6 +88,7 @@ namespace Desktop
|
||||
|
||||
private void UpdateMemoryView()
|
||||
{
|
||||
int count = 40;
|
||||
// Try to parse the hex string the user typed in
|
||||
if (!ushort.TryParse(txtMemoryStart.Text, System.Globalization.NumberStyles.HexNumber, null, out ushort startAddress))
|
||||
{
|
||||
@@ -98,7 +99,7 @@ namespace Desktop
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
// Read 100 bytes (or roughly 6 lines of 16 bytes)
|
||||
for (int line = 0; line < 7; line++)
|
||||
for (int line = 0; line < count; line++)
|
||||
{
|
||||
ushort currentAddr = (ushort)(startAddress + (line * 16));
|
||||
|
||||
@@ -246,8 +247,8 @@ namespace Desktop
|
||||
instructionLength = 2;
|
||||
break;
|
||||
case 0x17: // RLA
|
||||
mnemonic = "RLA";
|
||||
instructionLength = 1;
|
||||
mnemonic = "RLA";
|
||||
instructionLength = 1;
|
||||
break;
|
||||
case 0x18:
|
||||
sbyte dUnconditional = (sbyte)_memoryBus.Read((ushort)(currentPc + 1));
|
||||
@@ -266,7 +267,8 @@ namespace Desktop
|
||||
mnemonic = $"LD E, 0x{val1E:X2}";
|
||||
instructionLength = 2;
|
||||
break;
|
||||
case 0x1F: mnemonic = $"RRA";
|
||||
case 0x1F:
|
||||
mnemonic = $"RRA";
|
||||
break;
|
||||
case 0x20:
|
||||
sbyte jrOffset = (sbyte)_memoryBus.Read((ushort)(currentPc + 1));
|
||||
@@ -295,8 +297,8 @@ namespace Desktop
|
||||
instructionLength = 2;
|
||||
break;
|
||||
case 0x27: // DAA
|
||||
mnemonic = "DAA";
|
||||
instructionLength = 1;
|
||||
mnemonic = "DAA";
|
||||
instructionLength = 1;
|
||||
break;
|
||||
case 0x28:
|
||||
sbyte jrZOffset = (sbyte)_memoryBus.Read((ushort)(currentPc + 1));
|
||||
@@ -462,9 +464,9 @@ namespace Desktop
|
||||
case 0x8D:
|
||||
case 0x8E:
|
||||
case 0x8F:
|
||||
string[] registers = { "B", "C", "D", "E", "H", "L", "(HL)", "A" };
|
||||
mnemonic = $"ADC A, {registers[opcode - 0x88]}";
|
||||
instructionLength = 1;
|
||||
string[] registers = { "B", "C", "D", "E", "H", "L", "(HL)", "A" };
|
||||
mnemonic = $"ADC A, {registers[opcode - 0x88]}";
|
||||
instructionLength = 1;
|
||||
break;
|
||||
// --- SUB r ---
|
||||
case 0x90: mnemonic = "SUB B"; break;
|
||||
@@ -690,9 +692,9 @@ namespace Desktop
|
||||
mnemonic = "RET C";
|
||||
break;
|
||||
case 0xDB: // IN A, (n)
|
||||
n = _memoryBus.Read((ushort)(currentPc + 1));
|
||||
mnemonic = $"IN A, (0x{n:X2})";
|
||||
instructionLength = 2;
|
||||
n = _memoryBus.Read((ushort)(currentPc + 1));
|
||||
mnemonic = $"IN A, (0x{n:X2})";
|
||||
instructionLength = 2;
|
||||
break;
|
||||
case 0xDD:
|
||||
{
|
||||
|
||||
21
Desktop/Form1.Designer.cs
generated
21
Desktop/Form1.Designer.cs
generated
@@ -47,6 +47,7 @@
|
||||
debuggerToolStripMenuItem = new ToolStripMenuItem();
|
||||
optionsToolStripMenuItem = new ToolStripMenuItem();
|
||||
HighSpeedToolStripMenuItem = new ToolStripMenuItem();
|
||||
fastLoadToolStripMenuItem = new ToolStripMenuItem();
|
||||
playTapeToolStripMenuItem = new ToolStripMenuItem();
|
||||
menuStrip1.SuspendLayout();
|
||||
SuspendLayout();
|
||||
@@ -73,7 +74,7 @@
|
||||
//
|
||||
openToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { includedToolStripMenuItem, tAPToolStripMenuItem, sNAToolStripMenuItem });
|
||||
openToolStripMenuItem.Name = "openToolStripMenuItem";
|
||||
openToolStripMenuItem.Size = new Size(224, 26);
|
||||
openToolStripMenuItem.Size = new Size(188, 26);
|
||||
openToolStripMenuItem.Text = "Open";
|
||||
//
|
||||
// includedToolStripMenuItem
|
||||
@@ -112,14 +113,14 @@
|
||||
// saveSnapshotToolStripMenuItem
|
||||
//
|
||||
saveSnapshotToolStripMenuItem.Name = "saveSnapshotToolStripMenuItem";
|
||||
saveSnapshotToolStripMenuItem.Size = new Size(224, 26);
|
||||
saveSnapshotToolStripMenuItem.Size = new Size(188, 26);
|
||||
saveSnapshotToolStripMenuItem.Text = "Save Snapshot";
|
||||
saveSnapshotToolStripMenuItem.Click += SaveSNAMenuItem_Click;
|
||||
//
|
||||
// exitToolStripMenuItem
|
||||
//
|
||||
exitToolStripMenuItem.Name = "exitToolStripMenuItem";
|
||||
exitToolStripMenuItem.Size = new Size(224, 26);
|
||||
exitToolStripMenuItem.Size = new Size(188, 26);
|
||||
exitToolStripMenuItem.Text = "Exit";
|
||||
exitToolStripMenuItem.Click += btnExit_Click;
|
||||
//
|
||||
@@ -174,7 +175,7 @@
|
||||
//
|
||||
// optionsToolStripMenuItem
|
||||
//
|
||||
optionsToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { HighSpeedToolStripMenuItem });
|
||||
optionsToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { HighSpeedToolStripMenuItem, fastLoadToolStripMenuItem });
|
||||
optionsToolStripMenuItem.Name = "optionsToolStripMenuItem";
|
||||
optionsToolStripMenuItem.Size = new Size(75, 24);
|
||||
optionsToolStripMenuItem.Text = "Options";
|
||||
@@ -182,10 +183,19 @@
|
||||
// HighSpeedToolStripMenuItem
|
||||
//
|
||||
HighSpeedToolStripMenuItem.Name = "HighSpeedToolStripMenuItem";
|
||||
HighSpeedToolStripMenuItem.Size = new Size(170, 26);
|
||||
HighSpeedToolStripMenuItem.Size = new Size(224, 26);
|
||||
HighSpeedToolStripMenuItem.Text = "High Speed";
|
||||
HighSpeedToolStripMenuItem.Click += btnHighSpeedToggle_Click;
|
||||
//
|
||||
// fastLoadToolStripMenuItem
|
||||
//
|
||||
fastLoadToolStripMenuItem.Checked = true;
|
||||
fastLoadToolStripMenuItem.CheckState = CheckState.Checked;
|
||||
fastLoadToolStripMenuItem.Name = "fastLoadToolStripMenuItem";
|
||||
fastLoadToolStripMenuItem.Size = new Size(224, 26);
|
||||
fastLoadToolStripMenuItem.Text = "Fast Loading";
|
||||
fastLoadToolStripMenuItem.Click += fastLoadToolStripMenuItem_Click;
|
||||
//
|
||||
// playTapeToolStripMenuItem
|
||||
//
|
||||
playTapeToolStripMenuItem.Name = "playTapeToolStripMenuItem";
|
||||
@@ -230,5 +240,6 @@
|
||||
private ToolStripMenuItem sNAToolStripMenuItem1;
|
||||
private ToolStripMenuItem saveSnapshotToolStripMenuItem;
|
||||
private ToolStripMenuItem playTapeToolStripMenuItem;
|
||||
private ToolStripMenuItem fastLoadToolStripMenuItem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,9 @@ namespace Desktop
|
||||
public double FrameTime = 0;
|
||||
public bool highSpeed = false;
|
||||
public bool tapeLoaded = false;
|
||||
public bool tapePlaying = false;
|
||||
private volatile bool _pendingReset = false;
|
||||
private bool _enableFastLoad = true;
|
||||
// Comment to push a new commit
|
||||
|
||||
public Form1()
|
||||
@@ -57,6 +59,8 @@ namespace Desktop
|
||||
_memoryBus.LoadRom(romData);
|
||||
_cpu = new Z80(_memoryBus, _simpleIoBus);
|
||||
_cpu.WaitStateCallback = _ula.GetContentionDelay;
|
||||
fastLoadToolStripMenuItem.Checked = _enableFastLoad;
|
||||
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -118,10 +122,10 @@ namespace Desktop
|
||||
long tStatesBefore = _cpu.TotalTStates;
|
||||
|
||||
// --- HARDWARE INTERCEPTS ---
|
||||
if ((_cpu.PC == 0x0556 || _cpu.PC == 0x0558) && _tapManager.HasBlocks)
|
||||
if (_enableFastLoad && _cpu.PC == 0x0556 && _tapManager.HasBlocks)
|
||||
{
|
||||
HandleInstantTapeLoad();
|
||||
_cpu.TotalTStates += 100; // Charge some arbitrary time for the fast load
|
||||
_cpu.TotalTStates += 100;
|
||||
}
|
||||
|
||||
// --- Execute Instruction ---
|
||||
@@ -302,37 +306,34 @@ 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 fastLoadToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.fastLoadToolStripMenuItem.Checked = !this.fastLoadToolStripMenuItem.Checked;
|
||||
|
||||
_enableFastLoad = this.fastLoadToolStripMenuItem.Checked;
|
||||
}
|
||||
|
||||
private void IncludedTapMenuItem_Click(object? sender, EventArgs e)
|
||||
{
|
||||
if (sender is ToolStripMenuItem item && item.Tag is string resourceName)
|
||||
@@ -357,7 +358,7 @@ namespace Desktop
|
||||
// Feed it directly to your existing TapManager!
|
||||
_tapManager.LoadTapData(tapBytes);
|
||||
tapeLoaded = true;
|
||||
_tapManager.Play();
|
||||
//_tapManager.Play();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -488,7 +489,7 @@ namespace Desktop
|
||||
byte[] tapBytes = File.ReadAllBytes(ofd.FileName);
|
||||
_tapManager.LoadTapData(tapBytes);
|
||||
tapeLoaded = true;
|
||||
_tapManager.Play();
|
||||
//_tapManager.Play();
|
||||
}
|
||||
}
|
||||
_isPaused = false;
|
||||
@@ -643,11 +644,13 @@ namespace Desktop
|
||||
{
|
||||
playTapeToolStripMenuItem.Text = "Stop Tape";
|
||||
_tapManager.Play();
|
||||
tapePlaying = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
playTapeToolStripMenuItem.Text = "Play Tape";
|
||||
_tapManager.Stop();
|
||||
tapePlaying = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user