From a63152b04d2ae7feec29bca20857b1f6b7468998 Mon Sep 17 00:00:00 2001 From: Marc Parsons Date: Tue, 21 Apr 2026 17:12:42 +0100 Subject: [PATCH] Sound fixed and complete. More OpCodes to implement --- Core/Cpu/Z80.cs | 34 +++++++++++++++++++++++++++++++++- Desktop/BeeperDevice.cs | 13 +++++++++---- Desktop/DebuggerForm.cs | 21 +++++++++++++++++++++ Desktop/Form1.cs | 6 ++++++ 4 files changed, 69 insertions(+), 5 deletions(-) diff --git a/Core/Cpu/Z80.cs b/Core/Cpu/Z80.cs index 54b8466..f93ece9 100644 --- a/Core/Cpu/Z80.cs +++ b/Core/Cpu/Z80.cs @@ -2181,6 +2181,28 @@ namespace Core.Cpu // 3. Read the byte from memory and drop it into the L register (Low byte of HL) HL.Low = ReadMemory(address6E); + return 19; + case 0x70: // LD (IX+d), B + // 1. Fetch the displacement byte and cast it to a signed sbyte + sbyte offset70 = (sbyte)FetchByte(); + + // 2. Calculate the exact memory address (IX + offset) + ushort address70 = (ushort)(IX.Word + offset70); + + // 3. Write the B register (High byte of BC) into memory + WriteMemory(address70, BC.High); + + return 19; + case 0x71: // LD (IX+d), C + // 1. Fetch the displacement byte and cast it to a signed sbyte + sbyte offset71 = (sbyte)FetchByte(); + + // 2. Calculate the exact memory address (IX + offset) + ushort address71 = (ushort)(IX.Word + offset71); + + // 3. Write the C register (Low byte of BC) into memory + WriteMemory(address71, BC.Low); + return 19; case 0x72: // LD (IX+d), D // 1. Fetch the displacement byte and cast to a signed sbyte @@ -2508,7 +2530,17 @@ namespace Core.Cpu // 3. Write the contents of the D register (High byte of DE) into memory WriteMemory(address72, DE.High); - return 19; // 19 T-States + return 19; + case 0x73: // LD (IY+d), E + // 1. Fetch the displacement byte and cast it to a signed sbyte + sbyte offset73 = (sbyte)FetchByte(); + + // 2. Calculate the exact memory address (IY + offset) + ushort address73 = (ushort)(IY.Word + offset73); + + // 3. Write the contents of the E register (Low byte of DE) into memory + WriteMemory(address73, DE.Low); + return 19; case 0x74: // LD (IY+d), H // 1. Fetch the displacement byte and cast it to a signed sbyte sbyte offset74 = (sbyte)FetchByte(); diff --git a/Desktop/BeeperDevice.cs b/Desktop/BeeperDevice.cs index fe54642..394e271 100644 --- a/Desktop/BeeperDevice.cs +++ b/Desktop/BeeperDevice.cs @@ -7,6 +7,8 @@ namespace Desktop { private WaveOutEvent _waveOut; private BufferedWaveProvider _buffer; + private float _lastSample = 0.0f; + private float _lastFiltered = 0.0f; public BeeperDevice() { @@ -25,16 +27,19 @@ namespace Desktop public void AddSample(bool isHigh) { //Buffer overrun check and dump - if (_buffer.BufferedDuration.TotalMilliseconds > 100) + while (_buffer.BufferedDuration.TotalMilliseconds > 80) { - _buffer.ClearBuffer(); + Thread.Sleep(1); } // Convert the boolean into a physical sound wave (-0.2 or +0.2) - float sampleValue = isHigh ? 0.2f : -0.2f; + float rawSample = isHigh ? 0.2f : -0.2f; + float filteredSample = rawSample - _lastSample + 0.995f * _lastFiltered; + _lastSample = rawSample; + _lastFiltered = filteredSample; // Convert the float to bytes and drop it in the pipe - byte[] bytes = BitConverter.GetBytes(sampleValue); + byte[] bytes = BitConverter.GetBytes(filteredSample); _buffer.AddSamples(bytes, 0, 4); } } diff --git a/Desktop/DebuggerForm.cs b/Desktop/DebuggerForm.cs index c378158..6dab922 100644 --- a/Desktop/DebuggerForm.cs +++ b/Desktop/DebuggerForm.cs @@ -835,6 +835,20 @@ namespace Desktop mnemonic = $"LD L, (IX{sign}{d})"; instructionLength = 3; } + else if (ddOpcode == 0x71) // LD (IX+d), B + { + sbyte offset = (sbyte)_memoryBus.Read((ushort)(currentPc + 2)); + string sign = offset >= 0 ? "+" : ""; + mnemonic = $"LD (IX{sign}{offset}), B"; + instructionLength = 3; + } + else if (ddOpcode == 0x71) // LD (IX+d), C + { + sbyte offset = (sbyte)_memoryBus.Read((ushort)(currentPc + 2)); + string sign = offset >= 0 ? "+" : ""; + mnemonic = $"LD (IX{sign}{offset}), C"; + instructionLength = 3; + } else if (ddOpcode == 0x72) // LD (IX+d), D { sbyte offset = (sbyte)_memoryBus.Read((ushort)(currentPc + 2)); @@ -1154,6 +1168,13 @@ namespace Desktop mnemonic = $"LD (IY{sign}{d}), D"; instructionLength = 3; } + else if (fdOpcode == 0x73) // LD (IY+d), E + { + sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2)); + string sign = d >= 0 ? "+" : ""; + mnemonic = $"LD (IY{sign}{d}), E"; + instructionLength = 3; + } else if (fdOpcode == 0x74) // LD (IY+d), H { sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2)); diff --git a/Desktop/Form1.cs b/Desktop/Form1.cs index dfbf00f..f8e84d9 100644 --- a/Desktop/Form1.cs +++ b/Desktop/Form1.cs @@ -79,6 +79,8 @@ namespace Desktop if (_isPaused) { + stopwatch.Restart(); + scanlineCount = 0; Thread.Sleep(10); continue; } @@ -174,6 +176,7 @@ namespace Desktop private void loadTAPToolStripMenuItem_Click(object sender, EventArgs e) { + _isPaused = true; using (OpenFileDialog ofd = new OpenFileDialog()) { ofd.Filter = "Spectrum TAP Files|*.tap"; @@ -183,9 +186,11 @@ namespace Desktop _cpu._tapManager.LoadTapData(tapBytes); } } + _isPaused = false; } private void openSNAToolStripMenuItem_Click(object sender, EventArgs e) { + _isPaused = true; using (OpenFileDialog ofd = new OpenFileDialog()) { ofd.Filter = "Snapshot Files (sna,z80)|*.sna"; @@ -195,6 +200,7 @@ namespace Desktop _cpu.LoadSNA(snaBytes); } } + _isPaused = false; } private void btnRun_Click(object sender, EventArgs e) => _isPaused = false;