From 69a0865ee90960eaa6eb6c442b566eef5f7c4410 Mon Sep 17 00:00:00 2001 From: Adrian Conlon Date: Sat, 2 May 2026 17:02:36 +0100 Subject: [PATCH] Start work towards WDC 65C02 implementation --- EightBit/EightBit.csproj | 4 +-- LR35902/SM83.HarteTest/Checker.cs | 4 +++ LR35902/SM83.HarteTest/Cycle.cs | 9 +++-- LR35902/SM83.HarteTest/Program.cs | 2 +- M6502/Core.cs | 36 ++++++++++---------- M6502/M6502.HarteTest/M6502.HarteTest.csproj | 8 +++++ M6502/M6502.Symbols/M6502.Symbols.csproj | 8 +++++ M6502/M6502.Test/Configuration.cs | 2 +- M6502/WDC65C02.cs | 14 ++++++-- Z80/Z80.HarteTest/Program.cs | 2 +- 10 files changed, 61 insertions(+), 28 deletions(-) diff --git a/EightBit/EightBit.csproj b/EightBit/EightBit.csproj index 12f6aa0..2a42ca0 100644 --- a/EightBit/EightBit.csproj +++ b/EightBit/EightBit.csproj @@ -12,11 +12,11 @@ - 8 + 9999 - 8 + 9999 diff --git a/LR35902/SM83.HarteTest/Checker.cs b/LR35902/SM83.HarteTest/Checker.cs index bf98b29..29814ac 100644 --- a/LR35902/SM83.HarteTest/Checker.cs +++ b/LR35902/SM83.HarteTest/Checker.cs @@ -180,8 +180,12 @@ var actualAddress = actualCycle.Address; _ = this.Check("Cycle address", expectedAddress, actualAddress); + Debug.Assert(expectedCycle.Value is not null); var expectedValue = (byte)expectedCycle.Value; + + Debug.Assert(actualCycle.Value is not null); var actualValue = (byte)actualCycle.Value; + _ = this.Check("Cycle value", expectedValue, actualValue); var expectedAction = expectedCycle.Type; diff --git a/LR35902/SM83.HarteTest/Cycle.cs b/LR35902/SM83.HarteTest/Cycle.cs index 7b001ad..c1cbb4e 100644 --- a/LR35902/SM83.HarteTest/Cycle.cs +++ b/LR35902/SM83.HarteTest/Cycle.cs @@ -1,4 +1,6 @@ -namespace SM83.HarteTest +using System.Diagnostics; + +namespace SM83.HarteTest { internal sealed class Cycle { @@ -26,7 +28,10 @@ this.Address = AsElement(input[0]).GetUInt16(); this.Value = AsElement(input[1]).GetByte(); - this.Type = AsElement(input[2]).GetString(); + + var possibleType = AsElement(input[2]).GetString(); + Debug.Assert(possibleType != null); + this.Type = possibleType; } private static System.Text.Json.JsonElement AsElement(object part) => (System.Text.Json.JsonElement)part; diff --git a/LR35902/SM83.HarteTest/Program.cs b/LR35902/SM83.HarteTest/Program.cs index b4aae60..1d43f2b 100644 --- a/LR35902/SM83.HarteTest/Program.cs +++ b/LR35902/SM83.HarteTest/Program.cs @@ -4,7 +4,7 @@ namespace SM83.HarteTest { - public static class Program + internal static class Program { public static async Task Main(string[] _) { diff --git a/M6502/Core.cs b/M6502/Core.cs index c506f26..1cf42dd 100644 --- a/M6502/Core.cs +++ b/M6502/Core.cs @@ -349,7 +349,7 @@ namespace M6502 case 0x25: this.ZeroPage(); this.AND(); break; // AND (zero page) case 0x26: this.ZeroPage(); this.ROL(); break; // ROL (zero page) case 0x28: this.PLP(); break; // PLP (implied) - case 0x29: this.FetchByte(); this.AND(); break; // AND (immediate) + case 0x29: this.Immediate(); this.AND(); break; // AND (immediate) case 0x2a: this.ROLA(); break; // ROL A (implied) case 0x2c: this.Absolute(); this.BIT(); break; // BIT (absolute) case 0x2d: this.Absolute(); this.AND(); break; // AND (absolute) @@ -710,54 +710,54 @@ namespace M6502 #region Address and read - protected byte Immediate() => this.FetchByte(); + protected void Immediate() => this.FetchByte(); - protected byte Absolute() + protected void Absolute() { this.AbsoluteAddress(); - return this.MemoryRead(); + this.MemoryRead(); } - protected byte ZeroPage() + protected void ZeroPage() { this.ZeroPageAddress(); - return this.MemoryRead(); + this.MemoryRead(); } - protected byte ZeroPageX() + protected void ZeroPageX() { this.ZeroPageXAddress(); - return this.MemoryRead(); + this.MemoryRead(); } - protected byte ZeroPageY() + protected void ZeroPageY() { this.ZeroPageYAddress(); - return this.MemoryRead(); + this.MemoryRead(); } - protected byte IndexedIndirectX() + protected void IndexedIndirectX() { this.IndexedIndirectXAddress(); - return this.MemoryRead(); + this.MemoryRead(); } - protected byte AbsoluteX() + protected void AbsoluteX() { this.AbsoluteXAddress(); - return this.MaybeFixupRead(); + this.MaybeFixupRead(); } - protected byte AbsoluteY() + protected void AbsoluteY() { this.AbsoluteYAddress(); - return this.MaybeFixupRead(); + this.MaybeFixupRead(); } - protected byte IndirectIndexedY() + protected void IndirectIndexedY() { this.IndirectIndexedYAddress(); - return this.MaybeFixupRead(); + this.MaybeFixupRead(); } #endregion diff --git a/M6502/M6502.HarteTest/M6502.HarteTest.csproj b/M6502/M6502.HarteTest/M6502.HarteTest.csproj index 1d785d0..dec17c0 100644 --- a/M6502/M6502.HarteTest/M6502.HarteTest.csproj +++ b/M6502/M6502.HarteTest/M6502.HarteTest.csproj @@ -9,6 +9,14 @@ latest-all + + 9999 + + + + 9999 + + diff --git a/M6502/M6502.Symbols/M6502.Symbols.csproj b/M6502/M6502.Symbols/M6502.Symbols.csproj index 949de0e..f90668c 100644 --- a/M6502/M6502.Symbols/M6502.Symbols.csproj +++ b/M6502/M6502.Symbols/M6502.Symbols.csproj @@ -8,4 +8,12 @@ latest-all + + 9999 + + + + 9999 + + diff --git a/M6502/M6502.Test/Configuration.cs b/M6502/M6502.Test/Configuration.cs index 2a22c7a..ccd20cf 100644 --- a/M6502/M6502.Test/Configuration.cs +++ b/M6502/M6502.Test/Configuration.cs @@ -6,7 +6,7 @@ namespace M6502.Test { using EightBit; - internal class Configuration + internal sealed class Configuration { public bool DebugMode { get; set; } diff --git a/M6502/WDC65C02.cs b/M6502/WDC65C02.cs index e0205eb..2669ef8 100644 --- a/M6502/WDC65C02.cs +++ b/M6502/WDC65C02.cs @@ -95,6 +95,7 @@ namespace M6502 case 0x52: this.ZeroPageIndirect(); this.EOR(); break; // EOR (zp) case 0x53: break; // null + case 0x54: this.ZeroPageX(); break; // zp,x NOP case 0x57: this.ZeroPage(); this.RMB5(); break; // RMB5 zp case 0x5a: this.PHY(); break; // PHY s case 0x5b: break; // null @@ -121,7 +122,7 @@ namespace M6502 case 0x80: this.BRA(); break; // BRA r case 0x83: break; // null case 0x87: this.ZeroPage(); this.SMB0(); break; // SMB0 zp - case 0x89: break; // BIT # (TBC) + case 0x89: this.Immediate(); this.BIT_immediate(); break; // BIT # (TBC) case 0x8b: break; // null case 0x8f: this.ZeroPage(); this.BBS0(); break; // BBS0 r @@ -130,7 +131,7 @@ namespace M6502 case 0x97: this.ZeroPage(); this.SMB1(); break; // SMB1 zp case 0x9b: break; // null case 0x9c: this.AbsoluteAddress(); this.STZ(); break; // STZ a - case 0x9e: this.AbsoluteXAddress(); this.STZ(); break; // STZ a,x + case 0x9e: this.AbsoluteXAddress(); this.Fixup(); this.STZ(); break; // STZ a,x case 0x9f: this.ZeroPage(); this.BBS1(); break; // BBS1 r case 0xa3: break; // null @@ -151,10 +152,11 @@ namespace M6502 case 0xd2: this.ZeroPageIndirect(); this.CMP(); break; // CMP (zp) case 0xd3: break; // null + case 0xd4: this.ZeroPageX(); break; // zp,x NOP case 0xd7: this.ZeroPage(); this.SMB5(); break; // SMB5 zp case 0xda: this.PHX(); break; // PHX s case 0xdb: this.STP(); break; // STP i - case 0xdc: this.SwallowRead(); break; // null + case 0xdc: this.Absolute(); break; // null case 0xdf: this.ZeroPage(); this.BBS5(); break; // BBS5 r case 0xe3: break; // null @@ -164,6 +166,7 @@ namespace M6502 case 0xf2: this.ZeroPageIndirect(); this.SBC(); break; // SBC (zp) case 0xf3: break; // null + case 0xf4: this.ZeroPageX(); break; // zp,x NOP case 0xf7: this.ZeroPage(); this.SMB7(); break; // SMB7 zp case 0xfa: this.PLX(); break; // PLX s case 0xfb: break; // null @@ -273,6 +276,11 @@ namespace M6502 #endregion + private void BIT_immediate() + { + this.AdjustZero((byte)(this.A & this.Bus.Data)); + } + private void INCA() { this.SwallowRead(); diff --git a/Z80/Z80.HarteTest/Program.cs b/Z80/Z80.HarteTest/Program.cs index 3e587ed..cd7d4ab 100644 --- a/Z80/Z80.HarteTest/Program.cs +++ b/Z80/Z80.HarteTest/Program.cs @@ -4,7 +4,7 @@ namespace Z80.HarteTest { - public static class Program + internal static class Program { public static async Task Main(string[] _) {