From f8c171ac2f12c03d5933dd449dd8f210af2f4b12 Mon Sep 17 00:00:00 2001 From: Michael Bohn Date: Wed, 16 Jul 2025 23:48:51 +0200 Subject: [PATCH 01/12] adjust Cmd_A9_Test for cycle counting --- CPU_emu/Class_CPU.cs | 58 +++++++++++++++++++++------------------ CPU_emuTests/CPU_Tests.cs | 10 ++++--- 2 files changed, 38 insertions(+), 30 deletions(-) diff --git a/CPU_emu/Class_CPU.cs b/CPU_emu/Class_CPU.cs index bc8f359..1ed00f8 100644 --- a/CPU_emu/Class_CPU.cs +++ b/CPU_emu/Class_CPU.cs @@ -42,6 +42,8 @@ private byte public bool SteppingMode { get => _SteppingMode; set => _SteppingMode = value; } public bool ExitRequested { get => _ExitRequested; set => _ExitRequested = value; } public ulong InterruptPeriod { get => _InterruptPeriod; set => _InterruptPeriod = value; } + + public ulong CpuCycle { get => _CpuCycle; } public byte[] Memory { get @@ -91,7 +93,7 @@ public void Reset() SetRegister("A", 0); SetRegister("X", 0); SetRegister("Y", 0); - InterruptPeriod = 1000; + ExitRequested = false; // set all status flags to false @@ -163,8 +165,7 @@ public void Start() private void CpuRunner_DoWork(object sender, DoWorkEventArgs e) { - //_CpuCycle = InterruptPeriod; - + Type thisType = this.GetType(); @@ -172,28 +173,8 @@ private void CpuRunner_DoWork(object sender, DoWorkEventArgs e) { byte instruction = FetchByte(); - // Build method name from 'Cmd' + opcode - string cmd = "Cmd_" + instruction.ToString("X2").ToUpper(); - - MethodInfo theMethod2Call = thisType.GetMethod(cmd); - // Check if method Cmd_ exists - if (theMethod2Call != null) - { - // check for method attribute - OpcodeAttribute? attribute = theMethod2Call.GetCustomAttribute(); - - theMethod2Call.Invoke(this, new object[] { }); + CallInstruction(thisType, instruction); - if (attribute != null) - { - IncrementCpuCycle((ulong)attribute.Cycles); - } - } - else - { - MessageBox.Show(string.Format("Method {0} not found!", cmd),"Error!",MessageBoxButtons.OK,MessageBoxIcon.Error); - } - if (_SteppingMode) { break; @@ -208,13 +189,38 @@ private void CpuRunner_DoWork(object sender, DoWorkEventArgs e) break; } - + if (SlowDown && !_SteppingMode) { System.Threading.Thread.Sleep(SlowDownTime); } - + + } + } + + public void CallInstruction(Type thisType, byte instruction) + { + // Build method name from 'Cmd' + opcode + string cmd = "Cmd_" + instruction.ToString("X2").ToUpper(); + + MethodInfo theMethod2Call = thisType.GetMethod(cmd); + // Check if method Cmd_ exists + if (theMethod2Call != null) + { + // check for method attribute + OpcodeAttribute? attribute = theMethod2Call.GetCustomAttribute(); + + theMethod2Call.Invoke(this, new object[] { }); + + if (attribute != null) + { + IncrementCpuCycle((ulong)attribute.Cycles); + } + } + else + { + MessageBox.Show(string.Format("Method {0} not found!", cmd), "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error); } } diff --git a/CPU_emuTests/CPU_Tests.cs b/CPU_emuTests/CPU_Tests.cs index 519819b..8d56618 100644 --- a/CPU_emuTests/CPU_Tests.cs +++ b/CPU_emuTests/CPU_Tests.cs @@ -330,19 +330,21 @@ public void SetUp() } #region LDA // Test Load Accumulator immidiate A9 - [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff })] - [TestCase(0x00, ExpectedResult = new object[] { true, false, 0x00 })] + [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff, 3 })] + [TestCase(0x00, ExpectedResult = new object[] { true, false, 0x00, 3 })] public object[] Cmd_A9_Test(byte b) { - object[] result = new object[3]; + object[] result = new object[4]; cpu.WriteByteToMemory(b, 0x200); cpu.SetPC(0x200); - cpu.Cmd_A9(); + //cpu.Cmd_A9(); + cpu.CallInstruction(cpu.GetType(), 0xA9); result[0] = cpu.flags["Z"]; result[1] = cpu.flags["N"]; result[2] = cpu.A; + result[3] = cpu.CpuCycle; return result; From b1840a6e88ab89480369c14f32828814514fe222 Mon Sep 17 00:00:00 2001 From: Michael Bohn Date: Thu, 17 Jul 2025 08:53:21 +0200 Subject: [PATCH 02/12] Switch access modifier of CallInstruction() to private --- CPU_emu/Class_CPU.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CPU_emu/Class_CPU.cs b/CPU_emu/Class_CPU.cs index 1ed00f8..d0f2a30 100644 --- a/CPU_emu/Class_CPU.cs +++ b/CPU_emu/Class_CPU.cs @@ -199,7 +199,7 @@ private void CpuRunner_DoWork(object sender, DoWorkEventArgs e) } } - public void CallInstruction(Type thisType, byte instruction) + private void CallInstruction(Type thisType, byte instruction) { // Build method name from 'Cmd' + opcode string cmd = "Cmd_" + instruction.ToString("X2").ToUpper(); From df6ec7506aba7e9048049cf44bec8f5c47c5b4ab Mon Sep 17 00:00:00 2001 From: Michael Bohn Date: Thu, 17 Jul 2025 09:06:46 +0200 Subject: [PATCH 03/12] Helper-method GetPrivateMethod() moved to static class TestHelper --- CPU_emuTests/CPU_Tests.cs | 850 +++++++++++++++++++------------------- 1 file changed, 428 insertions(+), 422 deletions(-) diff --git a/CPU_emuTests/CPU_Tests.cs b/CPU_emuTests/CPU_Tests.cs index 8d56618..2bd12da 100644 --- a/CPU_emuTests/CPU_Tests.cs +++ b/CPU_emuTests/CPU_Tests.cs @@ -2,555 +2,561 @@ using System.Reflection; -namespace CPU_emulator +namespace CPU_emulator; + +[TestFixture] +public class CPU_Tests { - [TestFixture] - public class CPU_Tests + private CPU cpu; + + [SetUp] + public void Setup() + { + cpu = new CPU(); + } + #region set registers + [Test] + public void SetRegister_A_Test() + { + byte value = 0xff; + cpu.SetRegister("A", value); + Assert.That(cpu.A, Is.EqualTo(0xff)); + + } + + [Test] + public void SetRegister_X_Test() + { + byte value = 0xff; + cpu.SetRegister("X", value); + Assert.That(cpu.X, Is.EqualTo(0xff)); + + } + + [Test] + public void SetRegister_Y_Test() + { + byte value = 0xff; + cpu.SetRegister("Y", value); + Assert.That(cpu.Y, Is.EqualTo(0xff)); + + } + #endregion + + #region misc + [Test] + public void Reset_Test() { - private CPU cpu; - [SetUp] - public void Setup() - { - cpu = new CPU(); - } - #region set registers - [Test] - public void SetRegister_A_Test() - { - byte value = 0xff; - cpu.SetRegister("A", value); - Assert.That(cpu.A, Is.EqualTo(0xff)); + cpu.Reset(); + + + Assert.That(cpu.PC, Is.EqualTo(0x200)); + Assert.That(cpu.SP, Is.EqualTo(0x1FF)); + Assert.That(cpu.A, Is.EqualTo(0)); + Assert.That(cpu.X, Is.EqualTo(0)); + Assert.That(cpu.A, Is.EqualTo(0)); + + Assert.That(cpu.flags["C"], Is.False); + Assert.That(cpu.flags["Z"], Is.False); + Assert.That(cpu.flags["I"], Is.False); + Assert.That(cpu.flags["D"], Is.False); + Assert.That(cpu.flags["B"], Is.False); + Assert.That(cpu.flags["V"], Is.False); + Assert.That(cpu.flags["N"], Is.False); + + // TODO: Check events from PC and flags update + } - } + [Test] + public void SetVectors_Test() + { + TestHelper.GetPrivateMethod("SetVectors", cpu).Invoke(cpu, null); + byte[] memory = cpu.ReadMemory(); - [Test] - public void SetRegister_X_Test() - { - byte value = 0xff; - cpu.SetRegister("X", value); - Assert.That(cpu.X, Is.EqualTo(0xff)); + Assert.That(memory[0xFFFC], Is.EqualTo(0x00)); + Assert.That(memory[0xFFFD], Is.EqualTo(0x02)); + } - } + #endregion + + #region set flags + [TestCase(0xff, ExpectedResult = new bool[] { false, true })] + [TestCase(0x00, ExpectedResult = new bool[] { true, false })] + public bool[] SetZeroAndNegativeFlags_Test(byte b) + { + CPUEventArgs? cpuea = null; - [Test] - public void SetRegister_Y_Test() + cpu.OnFlagsUpdate += delegate (object? sender, CPUEventArgs e) { - byte value = 0xff; - cpu.SetRegister("Y", value); - Assert.That(cpu.Y, Is.EqualTo(0xff)); + cpuea = e; + }; - } - #endregion + bool[] result = new bool[2]; + TestHelper.GetPrivateMethod("SetZeroAndNegativeFlags",cpu).Invoke(cpu,new object[] {b}); - #region misc - [Test] - public void Reset_Test() + if (cpuea != null) { + switch (b) + { + case 0xff: + Assert.That(cpuea.Flags["Z"], Is.EqualTo(false)); + Assert.That(cpuea.Flags["N"], Is.EqualTo(true)); + break; + case 0x00: + Assert.That(cpuea.Flags["Z"], Is.EqualTo(true)); + Assert.That(cpuea.Flags["N"], Is.EqualTo(false)); + break; + + default: + break; + } + - cpu.Reset(); - - - Assert.That(cpu.PC, Is.EqualTo(0x200)); - Assert.That(cpu.SP, Is.EqualTo(0x1FF)); - Assert.That(cpu.A, Is.EqualTo(0)); - Assert.That(cpu.X, Is.EqualTo(0)); - Assert.That(cpu.A, Is.EqualTo(0)); - - Assert.That(cpu.flags["C"], Is.False); - Assert.That(cpu.flags["Z"], Is.False); - Assert.That(cpu.flags["I"], Is.False); - Assert.That(cpu.flags["D"], Is.False); - Assert.That(cpu.flags["B"], Is.False); - Assert.That(cpu.flags["V"], Is.False); - Assert.That(cpu.flags["N"], Is.False); - - // TODO: Check events from PC and flags update } - - [Test] - public void SetVectors_Test() + else { - GetPrivateMethod("SetVectors", cpu).Invoke(cpu, null); - byte[] memory = cpu.ReadMemory(); - - Assert.That(memory[0xFFFC], Is.EqualTo(0x00)); - Assert.That(memory[0xFFFD], Is.EqualTo(0x02)); + Assert.Fail("Event not triggered"); } - #endregion + result[0] = cpu.flags["Z"]; + result[1] = cpu.flags["N"]; - #region set flags - [TestCase(0xff, ExpectedResult = new bool[] { false, true })] - [TestCase(0x00, ExpectedResult = new bool[] { true, false })] - public bool[] SetZeroAndNegativeFlags_Test(byte b) - { - CPUEventArgs? cpuea = null; + return result; + } + #endregion - cpu.OnFlagsUpdate += delegate (object? sender, CPUEventArgs e) - { - cpuea = e; - }; + #region fetch data + [Test] + public void FetchByte_Test() + { + byte value = 0xff; + ulong cyc = 100; - bool[] result = new bool[2]; - GetPrivateMethod("SetZeroAndNegativeFlags",cpu).Invoke(cpu,new object[] {b}); + cpu.ResetMemory(); + cpu.WriteByteToMemory(value, 200); + cpu.SetPC(200); - if (cpuea != null) - { - switch (b) - { - case 0xff: - Assert.That(cpuea.Flags["Z"], Is.EqualTo(false)); - Assert.That(cpuea.Flags["N"], Is.EqualTo(true)); - break; - case 0x00: - Assert.That(cpuea.Flags["Z"], Is.EqualTo(true)); - Assert.That(cpuea.Flags["N"], Is.EqualTo(false)); - break; - - default: - break; - } - - - } - else - { - Assert.Fail("Event not triggered"); - } + Assert.That(TestHelper.GetPrivateMethod("FetchByte", cpu).Invoke(cpu,null), Is.EqualTo(0xff)); + Assert.That(cpu.PC, Is.EqualTo(201)); - result[0] = cpu.flags["Z"]; - result[1] = cpu.flags["N"]; + } - return result; - } - #endregion + #endregion - #region fetch data - [Test] - public void FetchByte_Test() - { - byte value = 0xff; - ulong cyc = 100; + #region ProgramCounterTest + [Test] + public void SetPC_Test() + { + CPUEventArgs? cpuea = null; - cpu.ResetMemory(); - cpu.WriteByteToMemory(value, 200); - cpu.SetPC(200); + cpu.OnProgramCounterUpdate += delegate (object? sender, CPUEventArgs e) + { + cpuea = e; + }; - Assert.That(GetPrivateMethod("FetchByte", cpu).Invoke(cpu,null), Is.EqualTo(0xff)); - Assert.That(cpu.PC, Is.EqualTo(201)); + cpu.SetPC(0x200); + Assert.That(cpu.PC, Is.EqualTo(0x200)); + if (cpuea != null) + { + Assert.That(cpuea.PC, Is.EqualTo(0x200)); } + else + { + Assert.Fail("Event not triggered"); + } + } - #endregion + [Test] + public void IncrementPC_Test() + { + cpu.SetPC(0x200); - #region ProgramCounterTest - [Test] - public void SetPC_Test() - { - CPUEventArgs? cpuea = null; + CPUEventArgs? cpuea = null; - cpu.OnProgramCounterUpdate += delegate (object? sender, CPUEventArgs e) - { - cpuea = e; - }; + cpu.OnProgramCounterUpdate += delegate (object? sender, CPUEventArgs e) + { + cpuea = e; + }; - cpu.SetPC(0x200); - Assert.That(cpu.PC, Is.EqualTo(0x200)); + cpu.IncrementPC(); + Assert.That(cpu.PC, Is.EqualTo(0x201)); - if (cpuea != null) - { - Assert.That(cpuea.PC, Is.EqualTo(0x200)); - } - else - { - Assert.Fail("Event not triggered"); - } + if (cpuea != null) + { + Assert.That(cpuea.PC, Is.EqualTo(0x201)); } - - [Test] - public void IncrementPC_Test() + else { - cpu.SetPC(0x200); + Assert.Fail("Event not triggered"); + } - CPUEventArgs? cpuea = null; + } - cpu.OnProgramCounterUpdate += delegate (object? sender, CPUEventArgs e) - { - cpuea = e; - }; + [Test] + public void DecrementPC_Test() + { + cpu.SetPC(0x201); - cpu.IncrementPC(); - Assert.That(cpu.PC, Is.EqualTo(0x201)); + CPUEventArgs? cpuea = null; - if (cpuea != null) - { - Assert.That(cpuea.PC, Is.EqualTo(0x201)); - } - else - { - Assert.Fail("Event not triggered"); - } + cpu.OnProgramCounterUpdate += delegate (object? sender, CPUEventArgs e) + { + cpuea = e; + }; - } + cpu.DecrementPC(); + Assert.That(cpu.PC, Is.EqualTo(0x200)); - [Test] - public void DecrementPC_Test() + if (cpuea != null) + { + Assert.That(cpuea.PC, Is.EqualTo(0x200)); + } + else { - cpu.SetPC(0x201); + Assert.Fail("Event not triggered"); + } - CPUEventArgs? cpuea = null; + } - cpu.OnProgramCounterUpdate += delegate (object? sender, CPUEventArgs e) - { - cpuea = e; - }; + #endregion - cpu.DecrementPC(); - Assert.That(cpu.PC, Is.EqualTo(0x200)); + #region StackPointerTest + [Test] + public void SetSP_Test() + { + CPUEventArgs? cpuea = null; - if (cpuea != null) - { - Assert.That(cpuea.PC, Is.EqualTo(0x200)); - } - else - { - Assert.Fail("Event not triggered"); - } + cpu.OnStackPointerUpdate += delegate (object? sender, CPUEventArgs e) + { + cpuea = e; + }; + TestHelper.GetPrivateMethod("SetSP", cpu).Invoke(cpu, new object[] { (ushort)0x01e0 }); + Assert.That(cpu.SP, Is.EqualTo(0x01e0)); + + if (cpuea != null) + { + Assert.That(cpuea.SP, Is.EqualTo(0x01e0)); } + else + { + Assert.Fail("Event not triggered"); + } + + } - #endregion + [Test] + public void IncrementSP_Test() + { + ushort? expectedSPfromEventargs = null; - #region StackPointerTest - [Test] - public void SetSP_Test() - { - CPUEventArgs? cpuea = null; + TestHelper.GetPrivateMethod("SetSP", cpu).Invoke(cpu, new object[] { (ushort)0x01fc }); - cpu.OnStackPointerUpdate += delegate (object? sender, CPUEventArgs e) - { - cpuea = e; - }; + cpu.OnStackPointerUpdate += delegate (object? sender, CPUEventArgs e) + { + expectedSPfromEventargs = e.SP; + }; + + TestHelper.GetPrivateMethod("IncrementSP", cpu).Invoke(cpu, null); + Assert.That(cpu.SP, Is.EqualTo(0x01fd)); - GetPrivateMethod("SetSP", cpu).Invoke(cpu, new object[] { (ushort)0x01e0 }); - Assert.That(cpu.SP, Is.EqualTo(0x01e0)); - - if (cpuea != null) - { - Assert.That(cpuea.SP, Is.EqualTo(0x01e0)); - } - else - { - Assert.Fail("Event not triggered"); - } - + if (expectedSPfromEventargs != null) + { + Assert.That(expectedSPfromEventargs, Is.EqualTo(0x01fd)); } - - [Test] - public void IncrementSP_Test() + else { - ushort? expectedSPfromEventargs = null; + Assert.Fail("Event not triggered"); + } - GetPrivateMethod("SetSP", cpu).Invoke(cpu, new object[] { (ushort)0x01fc }); + } - cpu.OnStackPointerUpdate += delegate (object? sender, CPUEventArgs e) - { - expectedSPfromEventargs = e.SP; - }; - - GetPrivateMethod("IncrementSP", cpu).Invoke(cpu, null); - Assert.That(cpu.SP, Is.EqualTo(0x01fd)); + [Test] + public void DecrementSP_Test() + { + ushort? expectedSPfromEventargs = null; - if (expectedSPfromEventargs != null) - { - Assert.That(expectedSPfromEventargs, Is.EqualTo(0x01fd)); - } - else - { - Assert.Fail("Event not triggered"); - } + TestHelper.GetPrivateMethod("SetSP", cpu).Invoke(cpu, new object[] { (ushort)0x01ff }); - } + cpu.OnStackPointerUpdate += delegate (object? sender, CPUEventArgs e) + { + expectedSPfromEventargs = e.SP; + }; + + TestHelper.GetPrivateMethod("DecrementSP", cpu).Invoke(cpu, null); + + Assert.That(cpu.SP, Is.EqualTo(0x01fe)); - [Test] - public void DecrementSP_Test() + if (expectedSPfromEventargs != null) + { + Assert.That(expectedSPfromEventargs, Is.EqualTo(0x01fe)); + } + else { - ushort? expectedSPfromEventargs = null; + Assert.Fail("Event not triggered"); + } - GetPrivateMethod("SetSP", cpu).Invoke(cpu, new object[] { (ushort)0x01ff }); + } - cpu.OnStackPointerUpdate += delegate (object? sender, CPUEventArgs e) - { - expectedSPfromEventargs = e.SP; - }; + #endregion - GetPrivateMethod("DecrementSP", cpu).Invoke(cpu, null); - Assert.That(cpu.SP, Is.EqualTo(0x01fe)); + +} - if (expectedSPfromEventargs != null) - { - Assert.That(expectedSPfromEventargs, Is.EqualTo(0x01fe)); - } - else - { - Assert.Fail("Event not triggered"); - } - } - #endregion +public class CPU_Command_Tests +{ + private CPU cpu; - #region helper - private MethodInfo GetPrivateMethod(string methodName,object objectUnderTest) - { - if (string.IsNullOrWhiteSpace(methodName)) - Assert.Fail("methodName cannot be null or whitespace"); + [SetUp] + public void SetUp() + { + cpu = new CPU(); + } + #region LDA + // Test Load Accumulator immidiate A9 + [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff, 3 })] + [TestCase(0x00, ExpectedResult = new object[] { true, false, 0x00, 3 })] + public object[] Cmd_A9_Test(byte b) + { + object[] result = new object[4]; - var method = objectUnderTest.GetType() - .GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); + cpu.WriteByteToMemory(b, 0x200); + cpu.SetPC(0x200); + //cpu.Cmd_A9(); + //cpu.CallInstruction(cpu.GetType(), 0xA9); + //GetPrivateMethod("DecrementSP", cpu).Invoke(cpu, null); + TestHelper.GetPrivateMethod("CallInstruction", cpu).Invoke(cpu, null); - if (method == null) - Assert.Fail(string.Format("{0} method not found", methodName)); + result[0] = cpu.flags["Z"]; + result[1] = cpu.flags["N"]; + result[2] = cpu.A; + result[3] = cpu.CpuCycle; - return method; - } + return result; - #endregion } - - public class CPU_Command_Tests + + // Test Load Accumulator zeropage A5 + [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff })] + [TestCase(0x00, ExpectedResult = new object[] { true, false, 0x00 })] + public object[] Cmd_A5_Test(byte b) { - private CPU cpu; + object[] result = new object[3]; - [SetUp] - public void SetUp() - { - cpu = new CPU(); - } - #region LDA - // Test Load Accumulator immidiate A9 - [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff, 3 })] - [TestCase(0x00, ExpectedResult = new object[] { true, false, 0x00, 3 })] - public object[] Cmd_A9_Test(byte b) - { - object[] result = new object[4]; - - cpu.WriteByteToMemory(b, 0x200); - cpu.SetPC(0x200); - //cpu.Cmd_A9(); - cpu.CallInstruction(cpu.GetType(), 0xA9); + cpu.WriteByteToMemory(b, 0x01); // set byte on zeropage adr. 0x01 + cpu.WriteByteToMemory(0x01, 0x200); + cpu.SetPC(0x200); + cpu.Cmd_A5(); - result[0] = cpu.flags["Z"]; - result[1] = cpu.flags["N"]; - result[2] = cpu.A; - result[3] = cpu.CpuCycle; + result[0] = cpu.flags["Z"]; + result[1] = cpu.flags["N"]; + result[2] = cpu.A; - return result; + return result; - } - - // Test Load Accumulator zeropage A5 - [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff })] - [TestCase(0x00, ExpectedResult = new object[] { true, false, 0x00 })] - public object[] Cmd_A5_Test(byte b) - { - object[] result = new object[3]; + } - cpu.WriteByteToMemory(b, 0x01); // set byte on zeropage adr. 0x01 - cpu.WriteByteToMemory(0x01, 0x200); - cpu.SetPC(0x200); - cpu.Cmd_A5(); + // Load Accumulator zeropage X B5 + [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff })] + [TestCase(0x00, ExpectedResult = new object[] { true, false, 0x00 })] + public object[] Cmd_B5_Test(byte b) + { + object[] result = new object[3]; + cpu.SetRegister("X",0x06); + cpu.WriteByteToMemory(b, 0x07); // set byte on zeropage adr. 0x01 + cpu.WriteByteToMemory(0x01, 0x200); + cpu.SetPC(0x200); + cpu.Cmd_B5(); - result[0] = cpu.flags["Z"]; - result[1] = cpu.flags["N"]; - result[2] = cpu.A; + result[0] = cpu.flags["Z"]; + result[1] = cpu.flags["N"]; + result[2] = cpu.A; - return result; + return result; - } + } - // Load Accumulator zeropage X B5 - [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff })] - [TestCase(0x00, ExpectedResult = new object[] { true, false, 0x00 })] - public object[] Cmd_B5_Test(byte b) - { - object[] result = new object[3]; - cpu.SetRegister("X",0x06); - cpu.WriteByteToMemory(b, 0x07); // set byte on zeropage adr. 0x01 - cpu.WriteByteToMemory(0x01, 0x200); - cpu.SetPC(0x200); - cpu.Cmd_B5(); + #endregion - result[0] = cpu.flags["Z"]; - result[1] = cpu.flags["N"]; - result[2] = cpu.A; + #region LDX - return result; + // Test Load X immidiate A2 + [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff })] + [TestCase(0x00, ExpectedResult = new object[] { true, false, 0x00 })] + public object[] Cmd_A2_Test(byte b) + { + object[] result = new object[3]; - } + cpu.WriteByteToMemory(b, 0x200); + cpu.SetPC(0x200); + cpu.Cmd_A2(); - #endregion + result[0] = cpu.flags["Z"]; + result[1] = cpu.flags["N"]; + result[2] = cpu.X; - #region LDX + return result; - // Test Load X immidiate A2 - [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff })] - [TestCase(0x00, ExpectedResult = new object[] { true, false, 0x00 })] - public object[] Cmd_A2_Test(byte b) - { - object[] result = new object[3]; + } - cpu.WriteByteToMemory(b, 0x200); - cpu.SetPC(0x200); - cpu.Cmd_A2(); + // Test Load X zeropage A6 + [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff })] + [TestCase(0x00, ExpectedResult = new object[] { true, false, 0x00 })] + public object[] Cmd_A6_Test(byte b) + { + object[] result = new object[3]; - result[0] = cpu.flags["Z"]; - result[1] = cpu.flags["N"]; - result[2] = cpu.X; + cpu.WriteByteToMemory(b, 0x01); // set byte on zeropage adr. 0x01 + cpu.WriteByteToMemory(0x01, 0x200); + cpu.SetPC(0x200); + cpu.Cmd_A6(); - return result; + result[0] = cpu.flags["Z"]; + result[1] = cpu.flags["N"]; + result[2] = cpu.X; - } + return result; - // Test Load X zeropage A6 - [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff })] - [TestCase(0x00, ExpectedResult = new object[] { true, false, 0x00 })] - public object[] Cmd_A6_Test(byte b) - { - object[] result = new object[3]; + } - cpu.WriteByteToMemory(b, 0x01); // set byte on zeropage adr. 0x01 - cpu.WriteByteToMemory(0x01, 0x200); - cpu.SetPC(0x200); - cpu.Cmd_A6(); + // Load X zeropage Y B6 + [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff })] + [TestCase(0x00, ExpectedResult = new object[] { true, false, 0x00 })] + public object[] Cmd_B6_Test(byte b) + { + object[] result = new object[3]; + cpu.SetRegister("Y", 0x06); + cpu.WriteByteToMemory(b, 0x07); // set byte on zeropage adr. 0x01 + cpu.WriteByteToMemory(0x01, 0x200); + cpu.SetPC(0x200); + cpu.Cmd_B6(); - result[0] = cpu.flags["Z"]; - result[1] = cpu.flags["N"]; - result[2] = cpu.X; + result[0] = cpu.flags["Z"]; + result[1] = cpu.flags["N"]; + result[2] = cpu.X; - return result; + return result; - } + } - // Load X zeropage Y B6 - [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff })] - [TestCase(0x00, ExpectedResult = new object[] { true, false, 0x00 })] - public object[] Cmd_B6_Test(byte b) - { - object[] result = new object[3]; - cpu.SetRegister("Y", 0x06); - cpu.WriteByteToMemory(b, 0x07); // set byte on zeropage adr. 0x01 - cpu.WriteByteToMemory(0x01, 0x200); - cpu.SetPC(0x200); - cpu.Cmd_B6(); + #endregion - result[0] = cpu.flags["Z"]; - result[1] = cpu.flags["N"]; - result[2] = cpu.X; + #region LDY - return result; + // Test Load Y immidiate A0 + [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff })] + [TestCase(0x00, ExpectedResult = new object[] { true, false, 0x00 })] + public object[] Cmd_A0_Test(byte b) + { + object[] result = new object[3]; - } + cpu.WriteByteToMemory(b, 0x200); + cpu.SetPC(0x200); + cpu.Cmd_A0(); - #endregion + result[0] = cpu.flags["Z"]; + result[1] = cpu.flags["N"]; + result[2] = cpu.Y; - #region LDY + return result; - // Test Load Y immidiate A0 - [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff })] - [TestCase(0x00, ExpectedResult = new object[] { true, false, 0x00 })] - public object[] Cmd_A0_Test(byte b) - { - object[] result = new object[3]; + } - cpu.WriteByteToMemory(b, 0x200); - cpu.SetPC(0x200); - cpu.Cmd_A0(); + // Test Load Y zeropage A4 + [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff })] + [TestCase(0x00, ExpectedResult = new object[] { true, false, 0x00 })] + public object[] Cmd_A4_Test(byte b) + { + object[] result = new object[3]; - result[0] = cpu.flags["Z"]; - result[1] = cpu.flags["N"]; - result[2] = cpu.Y; + cpu.WriteByteToMemory(b, 0x01); // set byte on zeropage adr. 0x01 + cpu.WriteByteToMemory(0x01, 0x200); + cpu.SetPC(0x200); + cpu.Cmd_A4(); - return result; + result[0] = cpu.flags["Z"]; + result[1] = cpu.flags["N"]; + result[2] = cpu.Y; - } + return result; - // Test Load Y zeropage A4 - [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff })] - [TestCase(0x00, ExpectedResult = new object[] { true, false, 0x00 })] - public object[] Cmd_A4_Test(byte b) - { - object[] result = new object[3]; + } - cpu.WriteByteToMemory(b, 0x01); // set byte on zeropage adr. 0x01 - cpu.WriteByteToMemory(0x01, 0x200); - cpu.SetPC(0x200); - cpu.Cmd_A4(); + // Load Y zeropage X B4 + [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff })] + [TestCase(0x00, ExpectedResult = new object[] { true, false, 0x00 })] + public object[] Cmd_B4_Test(byte b) + { + object[] result = new object[3]; + cpu.SetRegister("X", 0x06); + cpu.WriteByteToMemory(b, 0x07); // set byte on zeropage adr. 0x01 + cpu.WriteByteToMemory(0x01, 0x200); + cpu.SetPC(0x200); + cpu.Cmd_B4(); - result[0] = cpu.flags["Z"]; - result[1] = cpu.flags["N"]; - result[2] = cpu.Y; + result[0] = cpu.flags["Z"]; + result[1] = cpu.flags["N"]; + result[2] = cpu.Y; - return result; + return result; - } + } - // Load Y zeropage X B4 - [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff })] - [TestCase(0x00, ExpectedResult = new object[] { true, false, 0x00 })] - public object[] Cmd_B4_Test(byte b) - { - object[] result = new object[3]; - cpu.SetRegister("X", 0x06); - cpu.WriteByteToMemory(b, 0x07); // set byte on zeropage adr. 0x01 - cpu.WriteByteToMemory(0x01, 0x200); - cpu.SetPC(0x200); - cpu.Cmd_B4(); - result[0] = cpu.flags["Z"]; - result[1] = cpu.flags["N"]; - result[2] = cpu.Y; + #endregion - return result; + #region push pull - } + // Test Push Accumulator on Stack + [Test] + public void Cmd_48_Test() + { + CPUEventArgs? cpuea = null; + cpu.OnStackPointerUpdate += delegate (object? sender, CPUEventArgs e) + { + cpuea = e; + }; - #endregion + cpu.Reset(); + cpu.SetRegister("A", 0x42); + cpu.Cmd_48(); - #region push pull + Assert.That(cpu.SP, Is.EqualTo(0x01fe)); - // Test Push Accumulator on Stack - [Test] - public void Cmd_48_Test() + if (cpuea != null) + { + Assert.That(cpuea.SP, Is.EqualTo(0x01fe)); + } + else { - CPUEventArgs? cpuea = null; + Assert.Fail("Event not triggered"); + } - cpu.OnStackPointerUpdate += delegate (object? sender, CPUEventArgs e) - { - cpuea = e; - }; + Assert.That(cpu.Memory[0x01ff], Is.EqualTo(0x42)); - cpu.Reset(); - cpu.SetRegister("A", 0x42); - cpu.Cmd_48(); + } - Assert.That(cpu.SP, Is.EqualTo(0x01fe)); + #endregion +} - if (cpuea != null) - { - Assert.That(cpuea.SP, Is.EqualTo(0x01fe)); - } - else - { - Assert.Fail("Event not triggered"); - } +static class TestHelper +{ + public static MethodInfo GetPrivateMethod(string methodName, object objectUnderTest) + { + if (string.IsNullOrWhiteSpace(methodName)) + Assert.Fail("methodName cannot be null or whitespace"); - Assert.That(cpu.Memory[0x01ff], Is.EqualTo(0x42)); + var method = objectUnderTest.GetType() + .GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); - } + if (method == null) + Assert.Fail(string.Format("{0} method not found", methodName)); - #endregion + return method; } } \ No newline at end of file From 9d6fc5391bc2d497a43dfabec6cb345bd8b4970b Mon Sep 17 00:00:00 2001 From: Michael Bohn Date: Thu, 17 Jul 2025 09:37:11 +0200 Subject: [PATCH 04/12] tidy up #regions etc --- CPU_emuTests/CPU_Tests.cs | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/CPU_emuTests/CPU_Tests.cs b/CPU_emuTests/CPU_Tests.cs index 2bd12da..c1e9270 100644 --- a/CPU_emuTests/CPU_Tests.cs +++ b/CPU_emuTests/CPU_Tests.cs @@ -14,7 +14,9 @@ public void Setup() { cpu = new CPU(); } + #region set registers + [Test] public void SetRegister_A_Test() { @@ -41,7 +43,8 @@ public void SetRegister_Y_Test() Assert.That(cpu.Y, Is.EqualTo(0xff)); } - #endregion + + #endregion set registers #region misc [Test] @@ -78,9 +81,10 @@ public void SetVectors_Test() Assert.That(memory[0xFFFD], Is.EqualTo(0x02)); } - #endregion + #endregion misc #region set flags + [TestCase(0xff, ExpectedResult = new bool[] { false, true })] [TestCase(0x00, ExpectedResult = new bool[] { true, false })] public bool[] SetZeroAndNegativeFlags_Test(byte b) @@ -124,7 +128,8 @@ public bool[] SetZeroAndNegativeFlags_Test(byte b) return result; } - #endregion + + #endregion set flags #region fetch data [Test] @@ -142,9 +147,10 @@ public void FetchByte_Test() } - #endregion + #endregion fetch data #region ProgramCounterTest + [Test] public void SetPC_Test() { @@ -220,7 +226,7 @@ public void DecrementPC_Test() } - #endregion + #endregion ProgramCounterTest #region StackPointerTest [Test] @@ -300,12 +306,10 @@ public void DecrementSP_Test() } - #endregion - - -} + #endregion StackPointerTest +} public class CPU_Command_Tests { @@ -316,6 +320,7 @@ public void SetUp() { cpu = new CPU(); } + #region LDA // Test Load Accumulator immidiate A9 [TestCase(0xff, ExpectedResult = new object[] { false, true, 0xff, 3 })] @@ -326,9 +331,7 @@ public object[] Cmd_A9_Test(byte b) cpu.WriteByteToMemory(b, 0x200); cpu.SetPC(0x200); - //cpu.Cmd_A9(); - //cpu.CallInstruction(cpu.GetType(), 0xA9); - //GetPrivateMethod("DecrementSP", cpu).Invoke(cpu, null); + TestHelper.GetPrivateMethod("CallInstruction", cpu).Invoke(cpu, null); result[0] = cpu.flags["Z"]; @@ -551,7 +554,7 @@ public static MethodInfo GetPrivateMethod(string methodName, object objectUnderT if (string.IsNullOrWhiteSpace(methodName)) Assert.Fail("methodName cannot be null or whitespace"); - var method = objectUnderTest.GetType() + MethodInfo? method = objectUnderTest.GetType() .GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); if (method == null) From 2272a024ddedf9637136932e662103073b5266b6 Mon Sep 17 00:00:00 2001 From: Michael Bohn Date: Thu, 17 Jul 2025 09:56:15 +0200 Subject: [PATCH 05/12] Bugfix type mismatch @ Cmd_A9_Test() --- CPU_emuTests/CPU_Tests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CPU_emuTests/CPU_Tests.cs b/CPU_emuTests/CPU_Tests.cs index c1e9270..25ac4f1 100644 --- a/CPU_emuTests/CPU_Tests.cs +++ b/CPU_emuTests/CPU_Tests.cs @@ -332,7 +332,7 @@ public object[] Cmd_A9_Test(byte b) cpu.WriteByteToMemory(b, 0x200); cpu.SetPC(0x200); - TestHelper.GetPrivateMethod("CallInstruction", cpu).Invoke(cpu, null); + TestHelper.GetPrivateMethod("CallInstruction", cpu).Invoke(cpu, new object[] { cpu.GetType() , (byte)0xA9 }); result[0] = cpu.flags["Z"]; result[1] = cpu.flags["N"]; From d05b1d5b8b76eff0ae3c63009720325b0cd6ed7c Mon Sep 17 00:00:00 2001 From: Michael Bohn Date: Thu, 17 Jul 2025 12:41:36 +0200 Subject: [PATCH 06/12] check for events at Reset_Test --- CPU_emuTests/CPU_Tests.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/CPU_emuTests/CPU_Tests.cs b/CPU_emuTests/CPU_Tests.cs index 25ac4f1..8745d51 100644 --- a/CPU_emuTests/CPU_Tests.cs +++ b/CPU_emuTests/CPU_Tests.cs @@ -1,4 +1,5 @@ +using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.DataCollection; using System.Reflection; @@ -50,10 +51,17 @@ public void SetRegister_Y_Test() [Test] public void Reset_Test() { - + bool eventSetPCRaised = false; + bool eventFlagsUpdateRaised = false; + + cpu.OnProgramCounterUpdate += (object? sender, CPUEventArgs e) => { eventSetPCRaised = true; }; + cpu.OnFlagsUpdate += (object? sender, CPUEventArgs e) => { eventFlagsUpdateRaised = true; }; + cpu.Reset(); - - + + Assert.IsTrue(eventSetPCRaised, "Event for PC update not raised"); + Assert.IsTrue(eventFlagsUpdateRaised, "Event for flags-update not raised"); + Assert.That(cpu.PC, Is.EqualTo(0x200)); Assert.That(cpu.SP, Is.EqualTo(0x1FF)); Assert.That(cpu.A, Is.EqualTo(0)); @@ -68,9 +76,8 @@ public void Reset_Test() Assert.That(cpu.flags["V"], Is.False); Assert.That(cpu.flags["N"], Is.False); - // TODO: Check events from PC and flags update } - + [Test] public void SetVectors_Test() { From caf57f4e730d176e4d149ac273c3d05b71a5331d Mon Sep 17 00:00:00 2001 From: Michael Bohn Date: Fri, 18 Jul 2025 14:34:44 +0200 Subject: [PATCH 07/12] introduced IMemoryBus --- CPU_emu/Interfaces/IMemoryBus.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 CPU_emu/Interfaces/IMemoryBus.cs diff --git a/CPU_emu/Interfaces/IMemoryBus.cs b/CPU_emu/Interfaces/IMemoryBus.cs new file mode 100644 index 0000000..7149b5f --- /dev/null +++ b/CPU_emu/Interfaces/IMemoryBus.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CPU_emu; + +internal interface IMemoryBus +{ + byte Read(ushort address); + void Write(ushort address, byte value); + void Load(ushort address, params byte[] data); + byte[] Dump(ushort address, int length); + + +} From 0cc32ba622f74f1a777ae218cb463d8d7a33d26f Mon Sep 17 00:00:00 2001 From: Michael Bohn Date: Fri, 18 Jul 2025 14:35:16 +0200 Subject: [PATCH 08/12] new type MemoryBus --- CPU_emu/MemoryBus.cs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 CPU_emu/MemoryBus.cs diff --git a/CPU_emu/MemoryBus.cs b/CPU_emu/MemoryBus.cs new file mode 100644 index 0000000..b90681a --- /dev/null +++ b/CPU_emu/MemoryBus.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CPU_emu +{ + internal class MemoryBus : IMemoryBus + { + private readonly byte[] _memory; + + public MemoryBus(int memSize = 1024 * 64) + { + _memory = new byte[memSize]; + } + public byte Read(ushort address) + { + return _memory[address]; + } + + public void Write(ushort address, byte value) + { + _memory[address] = value; + } + + public void Load(ushort address, params byte[] data) + { + Array.Copy(data, 0, _memory, address, data.Length); + } + + public byte[] Dump(ushort address, int length) + { + return _memory.Skip(address).Take(length).ToArray(); + } + + + } +} From 3339673ebb11b8cc65a61ac48761c73260f7a2fa Mon Sep 17 00:00:00 2001 From: Michael Bohn Date: Fri, 18 Jul 2025 14:36:23 +0200 Subject: [PATCH 09/12] minor comment correction --- CPU_emu/CPU_emu.CMD_Methods.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CPU_emu/CPU_emu.CMD_Methods.cs b/CPU_emu/CPU_emu.CMD_Methods.cs index 1f64848..d70669a 100644 --- a/CPU_emu/CPU_emu.CMD_Methods.cs +++ b/CPU_emu/CPU_emu.CMD_Methods.cs @@ -98,7 +98,7 @@ public void Cmd_B4() #region stack push pull - // Push Accumulator on Stack + // Push Accumulator on Stack PHA public void Cmd_48() { PushByteToStack(A,ref _CpuCycle); From 2f46fb266debd61ebb5bc848e28b178abb0ab6eb Mon Sep 17 00:00:00 2001 From: Michael Bohn Date: Fri, 18 Jul 2025 22:15:00 +0200 Subject: [PATCH 10/12] minor change GUI status bar --- CPU_emu/Forms/CPU_emu.Designer.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CPU_emu/Forms/CPU_emu.Designer.cs b/CPU_emu/Forms/CPU_emu.Designer.cs index 7bc2c42..2b8164a 100644 --- a/CPU_emu/Forms/CPU_emu.Designer.cs +++ b/CPU_emu/Forms/CPU_emu.Designer.cs @@ -329,7 +329,7 @@ private void InitializeComponent() toolStripMenuItemStyleTXT.CheckOnClick = true; toolStripMenuItemStyleTXT.CheckState = System.Windows.Forms.CheckState.Checked; toolStripMenuItemStyleTXT.Name = "toolStripMenuItemStyleTXT"; - toolStripMenuItemStyleTXT.Size = new System.Drawing.Size(95, 22); + toolStripMenuItemStyleTXT.Size = new System.Drawing.Size(94, 22); toolStripMenuItemStyleTXT.Text = "TXT"; toolStripMenuItemStyleTXT.Click += toolStripMenuItemStyleTXT_Click; // @@ -337,7 +337,7 @@ private void InitializeComponent() // toolStripMenuItemStyleLED.CheckOnClick = true; toolStripMenuItemStyleLED.Name = "toolStripMenuItemStyleLED"; - toolStripMenuItemStyleLED.Size = new System.Drawing.Size(95, 22); + toolStripMenuItemStyleLED.Size = new System.Drawing.Size(94, 22); toolStripMenuItemStyleLED.Text = "LED"; toolStripMenuItemStyleLED.Click += toolStripMenuItemStyleLED_Click; // @@ -711,7 +711,7 @@ private void InitializeComponent() // toolStripProgressBar1 // toolStripProgressBar1.Name = "toolStripProgressBar1"; - toolStripProgressBar1.Size = new System.Drawing.Size(233, 18); + toolStripProgressBar1.Size = new System.Drawing.Size(300, 18); toolStripProgressBar1.Step = 1; toolStripProgressBar1.Style = System.Windows.Forms.ProgressBarStyle.Continuous; toolStripProgressBar1.Visible = false; @@ -725,7 +725,7 @@ private void InitializeComponent() // toolStripStatusLabelKernal // toolStripStatusLabelKernal.Name = "toolStripStatusLabelKernal"; - toolStripStatusLabelKernal.Size = new System.Drawing.Size(24, 19); + toolStripStatusLabelKernal.Size = new System.Drawing.Size(25, 19); toolStripStatusLabelKernal.Text = "0x0"; // // toolStripStatusLabel2 @@ -737,7 +737,7 @@ private void InitializeComponent() // toolStripStatusLabelBasic // toolStripStatusLabelBasic.Name = "toolStripStatusLabelBasic"; - toolStripStatusLabelBasic.Size = new System.Drawing.Size(24, 19); + toolStripStatusLabelBasic.Size = new System.Drawing.Size(25, 19); toolStripStatusLabelBasic.Text = "0x0"; // // toolStripStatusLabel3 From e887868f54df780ca559c7375549cdeed83d8b65 Mon Sep 17 00:00:00 2001 From: Michael Bohn Date: Fri, 18 Jul 2025 22:41:43 +0200 Subject: [PATCH 11/12] mem read/write => memoryBus --- CPU_emu/Class_CPU.cs | 105 +++++++++++++++++++++++-------------------- CPU_emu/MemoryBus.cs | 4 ++ 2 files changed, 60 insertions(+), 49 deletions(-) diff --git a/CPU_emu/Class_CPU.cs b/CPU_emu/Class_CPU.cs index d0f2a30..c01668b 100644 --- a/CPU_emu/Class_CPU.cs +++ b/CPU_emu/Class_CPU.cs @@ -1,4 +1,5 @@ -using CPU_emulator; +using CPU_emu; +using CPU_emulator; using System; using System.Collections.Generic; using System.ComponentModel; @@ -31,6 +32,8 @@ public partial class CPU private const uint MAX_MEM = 1024 * 64; private byte[] Data = new byte[MAX_MEM]; + MemoryBus _memoryBus; + private byte NegativeFlagBit = 0b10000000, OverflowFlagBit = 0b01000000, @@ -72,6 +75,7 @@ public byte[] Memory public CPU() { + _memoryBus = new MemoryBus(ref Data); SetVectors(); } @@ -107,51 +111,51 @@ public void Reset() } - private void LoadInlineTestProg() - { - Data[PC] = 0xB5; - Data[PC + 1] = 0x0b; - Data[PC + 2] = 0x48; - Data[PC + 3] = 0xA9; - Data[PC + 4] = 0xac; - Data[PC + 5] = 0x48; - Data[PC + 6] = 0xA9; - Data[PC + 7] = 0x00; - Data[PC + 8] = 0x48; - Data[PC + 9] = 0xA9; - Data[PC + 10] = 0xae; - Data[PC + 11] = 0x48; - - Data[PC + 12] = 0x48; - Data[PC + 13] = 0x48; - Data[PC + 14] = 0x48; - Data[PC + 15] = 0x48; - - Data[PC + 16] = 0x48; - Data[PC + 17] = 0x48; - Data[PC + 18] = 0x48; - Data[PC + 19] = 0x48; - - Data[PC + 20] = 0x48; - Data[PC + 21] = 0x48; - Data[PC + 22] = 0x48; - Data[PC + 23] = 0x48; - Data[PC + 24] = 0x48; - Data[PC + 25] = 0x48; - Data[PC + 26] = 0x48; - Data[PC + 27] = 0x48; - - Data[PC + 28] = 0x48; - Data[PC + 29] = 0x68; - Data[PC + 30] = 0x68; - Data[PC + 31] = 0x68; - Data[PC + 32] = 0x68; - Data[PC + 33] = 0x68; - Data[PC + 34] = 0x68; - Data[PC + 35] = 0x68; - - OnMemoryUpdate?.Invoke(this, new CPUEventArgs(this)); - } + //private void LoadInlineTestProg() + //{ + // Data[PC] = 0xB5; + // Data[PC + 1] = 0x0b; + // Data[PC + 2] = 0x48; + // Data[PC + 3] = 0xA9; + // Data[PC + 4] = 0xac; + // Data[PC + 5] = 0x48; + // Data[PC + 6] = 0xA9; + // Data[PC + 7] = 0x00; + // Data[PC + 8] = 0x48; + // Data[PC + 9] = 0xA9; + // Data[PC + 10] = 0xae; + // Data[PC + 11] = 0x48; + + // Data[PC + 12] = 0x48; + // Data[PC + 13] = 0x48; + // Data[PC + 14] = 0x48; + // Data[PC + 15] = 0x48; + + // Data[PC + 16] = 0x48; + // Data[PC + 17] = 0x48; + // Data[PC + 18] = 0x48; + // Data[PC + 19] = 0x48; + + // Data[PC + 20] = 0x48; + // Data[PC + 21] = 0x48; + // Data[PC + 22] = 0x48; + // Data[PC + 23] = 0x48; + // Data[PC + 24] = 0x48; + // Data[PC + 25] = 0x48; + // Data[PC + 26] = 0x48; + // Data[PC + 27] = 0x48; + + // Data[PC + 28] = 0x48; + // Data[PC + 29] = 0x68; + // Data[PC + 30] = 0x68; + // Data[PC + 31] = 0x68; + // Data[PC + 32] = 0x68; + // Data[PC + 33] = 0x68; + // Data[PC + 34] = 0x68; + // Data[PC + 35] = 0x68; + + // OnMemoryUpdate?.Invoke(this, new CPUEventArgs(this)); + //} public void Start() { @@ -262,7 +266,8 @@ private void SetZeroAndNegativeFlags(byte register) private byte FetchByte() { - byte data = Data[PC]; + //byte data = Data[PC]; + byte data = _memoryBus.Read((ushort)PC); IncrementPC(); IncrementCpuCycle(1); return data; @@ -281,13 +286,15 @@ private ushort FetchWord(ref ulong CpuCycle) public void WriteByteToMemory(byte b,ushort address) { - Data[address] = b; + //Data[address] = b; + _memoryBus.Write(address, b); OnMemoryUpdate?.Invoke(this, new CPUEventArgs(this)); } private byte ReadByteFromMemory(ushort address) { - return Data[address]; + //return Data[address]; + return _memoryBus.Read(address); } private ushort ReadWordFromMemory(ushort address) diff --git a/CPU_emu/MemoryBus.cs b/CPU_emu/MemoryBus.cs index b90681a..83c6312 100644 --- a/CPU_emu/MemoryBus.cs +++ b/CPU_emu/MemoryBus.cs @@ -14,6 +14,10 @@ public MemoryBus(int memSize = 1024 * 64) { _memory = new byte[memSize]; } + public MemoryBus(ref byte[] memory) + { + _memory = memory; + } public byte Read(ushort address) { return _memory[address]; From 93cebc30473e1c643846faea6349a464b8a0e738 Mon Sep 17 00:00:00 2001 From: Michael Bohn Date: Fri, 18 Jul 2025 22:42:49 +0200 Subject: [PATCH 12/12] remove LoadInlineTestProg() --- CPU_emu/Class_CPU.cs | 46 +------------------------------------------- 1 file changed, 1 insertion(+), 45 deletions(-) diff --git a/CPU_emu/Class_CPU.cs b/CPU_emu/Class_CPU.cs index c01668b..068594f 100644 --- a/CPU_emu/Class_CPU.cs +++ b/CPU_emu/Class_CPU.cs @@ -111,51 +111,7 @@ public void Reset() } - //private void LoadInlineTestProg() - //{ - // Data[PC] = 0xB5; - // Data[PC + 1] = 0x0b; - // Data[PC + 2] = 0x48; - // Data[PC + 3] = 0xA9; - // Data[PC + 4] = 0xac; - // Data[PC + 5] = 0x48; - // Data[PC + 6] = 0xA9; - // Data[PC + 7] = 0x00; - // Data[PC + 8] = 0x48; - // Data[PC + 9] = 0xA9; - // Data[PC + 10] = 0xae; - // Data[PC + 11] = 0x48; - - // Data[PC + 12] = 0x48; - // Data[PC + 13] = 0x48; - // Data[PC + 14] = 0x48; - // Data[PC + 15] = 0x48; - - // Data[PC + 16] = 0x48; - // Data[PC + 17] = 0x48; - // Data[PC + 18] = 0x48; - // Data[PC + 19] = 0x48; - - // Data[PC + 20] = 0x48; - // Data[PC + 21] = 0x48; - // Data[PC + 22] = 0x48; - // Data[PC + 23] = 0x48; - // Data[PC + 24] = 0x48; - // Data[PC + 25] = 0x48; - // Data[PC + 26] = 0x48; - // Data[PC + 27] = 0x48; - - // Data[PC + 28] = 0x48; - // Data[PC + 29] = 0x68; - // Data[PC + 30] = 0x68; - // Data[PC + 31] = 0x68; - // Data[PC + 32] = 0x68; - // Data[PC + 33] = 0x68; - // Data[PC + 34] = 0x68; - // Data[PC + 35] = 0x68; - - // OnMemoryUpdate?.Invoke(this, new CPUEventArgs(this)); - //} + public void Start() {