diff --git a/EightBit/IntelProcessor.cs b/EightBit/IntelProcessor.cs index 0665f5d..ca74ebe 100644 --- a/EightBit/IntelProcessor.cs +++ b/EightBit/IntelProcessor.cs @@ -20,7 +20,7 @@ namespace EightBit { for (var i = 0; i < 0x100; ++i) { - this.decodedOpCodes[i] = new IntelOpCodeDecoded((byte)i); + this.decodedOpCodes[i] = new((byte)i); } } @@ -32,9 +32,9 @@ namespace EightBit public event EventHandler? LoweredHALT; - public Register16 SP { get; } = new Register16((ushort)Mask.Sixteen); + public Register16 SP { get; } = new((ushort)Mask.Sixteen); - public Register16 MEMPTR { get; } = new Register16((ushort)Mask.Sixteen); + public Register16 MEMPTR { get; } = new((ushort)Mask.Sixteen); public abstract Register16 AF { get; } diff --git a/M6502/M6502.HarteTest/Checker.cs b/M6502/M6502.HarteTest/Checker.cs index be11a0c..537f669 100644 --- a/M6502/M6502.HarteTest/Checker.cs +++ b/M6502/M6502.HarteTest/Checker.cs @@ -1,6 +1,8 @@ namespace M6502.HarteTest { - internal class Checker + using System.Diagnostics; + + internal sealed class Checker { private TestRunner Runner { get; } @@ -27,15 +29,14 @@ public Checker(TestRunner runner) { this.Runner = runner; - this.Disassembler = new EightBit.Disassembler(this.Runner, this.Runner.CPU, this.Symbols); + this.Disassembler = new(this.Runner, this.Runner.CPU, this.Symbols); } public void Check(Test test) { var cpu = this.Runner.CPU; - this.Messages.Clear(); - this.ActualCycles.Clear(); + this.Reset(); this.Runner.RaisePOWER(); this.InitialiseState(test); @@ -52,7 +53,8 @@ return; } - if (this.Invalid && this.Implemented) + Debug.Assert(this.Implemented); + if (this.Invalid) { this.AddDisassembly(pc); @@ -79,6 +81,16 @@ } } + private void Reset() + { + this.Messages.Clear(); + this.ActualCycles.Clear(); + + this.CycleCountMismatch = false; + this.Cycles = 0; + this.Valid = false; + } + private bool Check(string what, ushort expected, ushort actual) { var success = actual == expected; @@ -143,34 +155,34 @@ var cpu = this.Runner.CPU; var ram = this.Runner.RAM; - var expected_cycles = test.AvailableCycles() ?? throw new InvalidOperationException("Expected cycles cannot be null"); - var actual_cycles = this.ActualCycles; + var expectedCycles = test.AvailableCycles(); + var actualCycles = this.ActualCycles; - var actual_idx = 0; - foreach (var expected_cycle in expected_cycles) { + var actualIDX = 0; + foreach (var expectedCycle in expectedCycles) { - if (actual_idx >= actual_cycles.Count) + if (actualIDX >= actualCycles.Count) { this.CycleCountMismatch = true; return false; // more expected cycles than actual } - var actual_cycle = actual_cycles[actual_idx++]; + var actualCycle = actualCycles[actualIDX++]; - var expected_address = expected_cycle.Address; - var actual_address = actual_cycle.Address; - _ = this.Check("Cycle address", expected_address, actual_address); + var expectedAddress = expectedCycle.Address; + var actualAddress = actualCycle.Address; + _ = this.Check("Cycle address", expectedAddress, actualAddress); - var expected_value = expected_cycle.Value; - var actual_value = actual_cycle.Value; - _ = this.Check("Cycle value", expected_value, actual_value); + var expectedValue = expectedCycle.Value; + var actualValue = actualCycle.Value; + _ = this.Check("Cycle value", expectedValue, actualValue); - var expected_action = expected_cycle.Type; - var actual_action = actual_cycle.Type; - _ = this.Check("Cycle action", expected_action, actual_action); + var expectedAction = expectedCycle.Type; + var actualAction = actualCycle.Type; + _ = this.Check("Cycle action", expectedAction, actualAction); } - if (actual_idx < actual_cycles.Count) + if (actualIDX < actualCycles.Count) { this.CycleCountMismatch = true; return false; // less expected cycles than actual @@ -194,7 +206,7 @@ throw new InvalidOperationException("Expected RAM cannot be null"); } - var ram_problem = false; + var ramProblem = false; foreach (var entry in final.RAM) { if (entry.Length != 2) @@ -205,17 +217,17 @@ var address = (ushort)entry[0]; var value = (byte)entry[1]; - var ram_good = this.Check("RAM", address, value, ram.Peek(address)); - if (!ram_good && !ram_problem) + var ramGood = this.Check("RAM", address, value, ram.Peek(address)); + if (!ramGood && !ramProblem) { - ram_problem = true; + ramProblem = true; } } return pc_good && s_good && a_good && x_good && y_good && p_good - && !ram_problem; + && !ramProblem; } private void Raise(string what, ushort expected, ushort actual) => this.Messages.Add($"{what}: expected: {expected:X4}, actual: {actual:X4}"); diff --git a/M6502/M6502.HarteTest/Cycle.cs b/M6502/M6502.HarteTest/Cycle.cs index 77d9cd1..d57e32e 100644 --- a/M6502/M6502.HarteTest/Cycle.cs +++ b/M6502/M6502.HarteTest/Cycle.cs @@ -1,6 +1,6 @@ namespace M6502.HarteTest { - public class Cycle + public sealed class Cycle { public ushort Address { get; set; } @@ -22,9 +22,11 @@ throw new ArgumentOutOfRangeException(nameof(input), input, "Cycles can only have three elements"); } - this.Address = ((System.Text.Json.JsonElement)input[0]).GetUInt16(); - this.Value = ((System.Text.Json.JsonElement)input[1]).GetByte(); - this.Type = ((System.Text.Json.JsonElement)input[2]).GetString(); + this.Address = AsElement(input[0]).GetUInt16(); + this.Value = AsElement(input[1]).GetByte(); + this.Type = AsElement(input[2]).GetString(); } + + private static System.Text.Json.JsonElement AsElement(object part) => (System.Text.Json.JsonElement)part; } } diff --git a/M6502/M6502.HarteTest/OpcodeTestSuite.cs b/M6502/M6502.HarteTest/OpcodeTestSuite.cs index 8b7a82b..a525a1e 100644 --- a/M6502/M6502.HarteTest/OpcodeTestSuite.cs +++ b/M6502/M6502.HarteTest/OpcodeTestSuite.cs @@ -3,7 +3,7 @@ using System.Text.Json; using System.Text.Json.Serialization; - internal class OpcodeTestSuite(string path) : IDisposable + internal sealed class OpcodeTestSuite(string path) : IDisposable { private static readonly JsonSerializerOptions SerializerOptions = new() { @@ -18,7 +18,7 @@ public IAsyncEnumerable TestsAsync => JsonSerializer.DeserializeAsyncEnumerable(this.stream, SerializerOptions); - protected virtual void Dispose(bool disposing) + private void Dispose(bool disposing) { if (!this.disposed) { diff --git a/M6502/M6502.HarteTest/ProcessorTestSuite.cs b/M6502/M6502.HarteTest/ProcessorTestSuite.cs index 7a2681b..0e89b27 100644 --- a/M6502/M6502.HarteTest/ProcessorTestSuite.cs +++ b/M6502/M6502.HarteTest/ProcessorTestSuite.cs @@ -1,6 +1,6 @@ namespace M6502.HarteTest { - internal class ProcessorTestSuite(string location) + internal sealed class ProcessorTestSuite(string location) { public string Location { get; set; } = location; diff --git a/M6502/M6502.HarteTest/State.cs b/M6502/M6502.HarteTest/State.cs index 9a39bf4..efd2d3b 100644 --- a/M6502/M6502.HarteTest/State.cs +++ b/M6502/M6502.HarteTest/State.cs @@ -1,6 +1,6 @@ namespace M6502.HarteTest { - public class State + public sealed class State { public ushort PC { get; set; } diff --git a/M6502/M6502.HarteTest/Test.cs b/M6502/M6502.HarteTest/Test.cs index effd292..36d470b 100644 --- a/M6502/M6502.HarteTest/Test.cs +++ b/M6502/M6502.HarteTest/Test.cs @@ -1,6 +1,6 @@ namespace M6502.HarteTest { - public class Test + public sealed class Test { public string? Name { get; set; } @@ -22,15 +22,5 @@ yield return new Cycle(cycle); } } - - public Cycle CycleAt(int index) - { - if (this.Cycles == null) - { - throw new InvalidOperationException("Cycles have not been initialised"); - } - - return new Cycle(this.Cycles[index]); - } } } diff --git a/M6502/M6502.HarteTest/TestRunner.cs b/M6502/M6502.HarteTest/TestRunner.cs index 5479eec..5ea0e41 100644 --- a/M6502/M6502.HarteTest/TestRunner.cs +++ b/M6502/M6502.HarteTest/TestRunner.cs @@ -2,7 +2,7 @@ { using EightBit; - internal class TestRunner : Bus + internal sealed class TestRunner : Bus { public Ram RAM { get; } = new(0x10000); @@ -26,7 +26,7 @@ base.LowerPOWER(); } - public override MemoryMapping Mapping(ushort absolute) => this.mapping; + public override MemoryMapping Mapping(ushort _) => this.mapping; public override void RaisePOWER() { diff --git a/M6502/M6502.Symbols/Parser.cs b/M6502/M6502.Symbols/Parser.cs index 08fec27..603bd77 100644 --- a/M6502/M6502.Symbols/Parser.cs +++ b/M6502/M6502.Symbols/Parser.cs @@ -306,7 +306,7 @@ private void ExtractTypes() => this.Extract("type", this.Types); - private void Extract(string key, List into) where T : IdentifiableSection//, new() + private void Extract(string key, List into) where T : IdentifiableSection { if (this._parsed == null) { @@ -420,12 +420,12 @@ if (key is "version") { - this._version = new Version(this); + this._version = new(this); this._version.Parse(BuildDictionary(parts)); } else if (key is "info") { - this._information = new Information(this); + this._information = new(this); this._information.Parse(BuildDictionary(parts)); } else diff --git a/M6502/M6502.Test/Board.cs b/M6502/M6502.Test/Board.cs index 9e3f303..03a02d6 100644 --- a/M6502/M6502.Test/Board.cs +++ b/M6502/M6502.Test/Board.cs @@ -12,8 +12,8 @@ namespace M6502.Test internal class Board : Bus { private readonly Configuration configuration; - private readonly Ram ram; - private readonly EightBit.Files.Symbols.Parser symbols; + private readonly Ram ram = new(0x10000); + private readonly EightBit.Files.Symbols.Parser symbols = new(); private readonly Disassembler disassembler; private readonly Profiler profiler; private readonly MemoryMapping mapping; @@ -30,12 +30,10 @@ namespace M6502.Test public Board(Configuration configuration) { this.configuration = configuration; - this.ram = new Ram(0x10000); - this.CPU = new M6502(this); - this.symbols = new EightBit.Files.Symbols.Parser(); - this.disassembler = new Disassembler(this, this.CPU, this.symbols); - this.mapping = new MemoryMapping(this.ram, 0x0000, (ushort)Mask.Sixteen, AccessLevel.ReadWrite); - this.profiler = new Profiler(this.CPU, this.disassembler, this.symbols, this.configuration.Profile); + this.CPU = new(this); + this.disassembler = new(this, this.CPU, this.symbols); + this.mapping = new(this.ram, 0x0000, (ushort)Mask.Sixteen, AccessLevel.ReadWrite); + this.profiler = new(this.CPU, this.disassembler, this.symbols, this.configuration.Profile); } public M6502 CPU { get; } diff --git a/M6502/M6502.cs b/M6502/M6502.cs index c26e0f1..4151fd3 100644 --- a/M6502/M6502.cs +++ b/M6502/M6502.cs @@ -18,126 +18,126 @@ namespace EightBit var cycles = this.Cycles; switch (this.OpCode) { - case 0x02: this.Jam(); break; // *JAM - case 0x03: this.IndexedIndirectXRead(); this.SLO(); break; // *SLO (indexed indirect X) - case 0x04: this.ZeroPageRead(); break; // *NOP (zero page) - case 0x07: this.ZeroPageRead(); this.SLO(); break; // *SLO (zero page) - case 0x0b: this.ImmediateRead(); this.ANC(); break; // *ANC (immediate) - case 0x0c: this.AbsoluteRead(); break; // *NOP (absolute) - case 0x0f: this.AbsoluteRead(); this.SLO(); break; // *SLO (absolute) + case 0x02: this.Jam(); break; // *JAM + case 0x03: this.IndexedIndirectXRead(); this.SLO(); break; // *SLO (indexed indirect X) + case 0x04: this.ZeroPageRead(); break; // *NOP (zero page) + case 0x07: this.ZeroPageRead(); this.SLO(); break; // *SLO (zero page) + case 0x0b: this.ImmediateRead(); this.ANC(); break; // *ANC (immediate) + case 0x0c: this.AbsoluteRead(); break; // *NOP (absolute) + case 0x0f: this.AbsoluteRead(); this.SLO(); break; // *SLO (absolute) - case 0x12: this.Jam(); break; // *JAM - case 0x13: this.IndirectIndexedYAddress(); this.FixupRead(); this.SLO(); break; // *SLO (indirect indexed Y) - case 0x14: this.ZeroPageXRead(); break; // *NOP (zero page, X) - case 0x17: this.ZeroPageXRead(); this.SLO(); break; // *SLO (zero page, X) - case 0x1a: this.SwallowRead(); break; // *NOP (implied) - case 0x1b: this.AbsoluteYAddress(); this.FixupRead(); this.SLO(); break; // *SLO (absolute, Y) - case 0x1c: this.AbsoluteXAddress(); this.MaybeFixupRead(); break; // *NOP (absolute, X) - case 0x1f: this.AbsoluteXAddress(); this.FixupRead(); this.SLO(); break; // *SLO (absolute, X) + case 0x12: this.Jam(); break; // *JAM + case 0x13: this.IndirectIndexedYAddress(); this.FixupRead(); this.SLO(); break; // *SLO (indirect indexed Y) + case 0x14: this.ZeroPageXRead(); break; // *NOP (zero page, X) + case 0x17: this.ZeroPageXRead(); this.SLO(); break; // *SLO (zero page, X) + case 0x1a: this.SwallowRead(); break; // *NOP (implied) + case 0x1b: this.AbsoluteYAddress(); this.FixupRead(); this.SLO(); break; // *SLO (absolute, Y) + case 0x1c: this.AbsoluteXAddress(); this.MaybeFixupRead(); break; // *NOP (absolute, X) + case 0x1f: this.AbsoluteXAddress(); this.FixupRead(); this.SLO(); break; // *SLO (absolute, X) - case 0x22: this.Jam(); break; // *JAM - case 0x23: this.IndexedIndirectXRead(); this.RLA(); ; break; // *RLA (indexed indirect X) - case 0x27: this.ZeroPageRead(); this.RLA(); ; break; // *RLA (zero page) - case 0x2b: this.ImmediateRead(); this.ANC(); break; // *ANC (immediate) - case 0x2f: this.AbsoluteRead(); this.RLA(); break; // *RLA (absolute) + case 0x22: this.Jam(); break; // *JAM + case 0x23: this.IndexedIndirectXRead(); this.RLA(); ; break; // *RLA (indexed indirect X) + case 0x27: this.ZeroPageRead(); this.RLA(); ; break; // *RLA (zero page) + case 0x2b: this.ImmediateRead(); this.ANC(); break; // *ANC (immediate) + case 0x2f: this.AbsoluteRead(); this.RLA(); break; // *RLA (absolute) - case 0x32: this.Jam(); break; // *JAM - case 0x33: this.IndirectIndexedYAddress(); this.FixupRead(); this.RLA(); break; // *RLA (indirect indexed Y) - case 0x34: this.ZeroPageXRead(); break; // *NOP (zero page, X) - case 0x37: this.ZeroPageXRead(); this.RLA(); ; break; // *RLA (zero page, X) - case 0x3a: this.SwallowRead(); break; // *NOP (implied) - case 0x3b: this.AbsoluteYAddress(); this.FixupRead(); this.RLA(); break; // *RLA (absolute, Y) - case 0x3c: this.AbsoluteXAddress(); this.MaybeFixupRead(); break; // *NOP (absolute, X) - case 0x3f: this.AbsoluteXAddress(); this.FixupRead(); this.RLA(); break; // *RLA (absolute, X) + case 0x32: this.Jam(); break; // *JAM + case 0x33: this.IndirectIndexedYAddress(); this.FixupRead(); this.RLA(); break; // *RLA (indirect indexed Y) + case 0x34: this.ZeroPageXRead(); break; // *NOP (zero page, X) + case 0x37: this.ZeroPageXRead(); this.RLA(); ; break; // *RLA (zero page, X) + case 0x3a: this.SwallowRead(); break; // *NOP (implied) + case 0x3b: this.AbsoluteYAddress(); this.FixupRead(); this.RLA(); break; // *RLA (absolute, Y) + case 0x3c: this.AbsoluteXAddress(); this.MaybeFixupRead(); break; // *NOP (absolute, X) + case 0x3f: this.AbsoluteXAddress(); this.FixupRead(); this.RLA(); break; // *RLA (absolute, X) - case 0x42: this.Jam(); break; // *JAM - case 0x43: this.IndexedIndirectXRead(); this.SRE(); break; // *SRE (indexed indirect X) - case 0x44: this.ZeroPageRead(); break; // *NOP (zero page) - case 0x47: this.ZeroPageRead(); this.SRE(); break; // *SRE (zero page) - case 0x4b: this.ImmediateRead(); this.ASR(); break; // *ASR (immediate) - case 0x4f: this.AbsoluteRead(); this.SRE(); break; // *SRE (absolute) + case 0x42: this.Jam(); break; // *JAM + case 0x43: this.IndexedIndirectXRead(); this.SRE(); break; // *SRE (indexed indirect X) + case 0x44: this.ZeroPageRead(); break; // *NOP (zero page) + case 0x47: this.ZeroPageRead(); this.SRE(); break; // *SRE (zero page) + case 0x4b: this.ImmediateRead(); this.ASR(); break; // *ASR (immediate) + case 0x4f: this.AbsoluteRead(); this.SRE(); break; // *SRE (absolute) - case 0x52: this.Jam(); break; // *JAM - case 0x53: this.IndirectIndexedYAddress(); this.FixupRead(); this.SRE(); break; // *SRE (indirect indexed Y) - case 0x54: this.ZeroPageXRead(); break; // *NOP (zero page, X) - case 0x57: this.ZeroPageXRead(); this.SRE(); break; // *SRE (zero page, X) - case 0x5a: this.SwallowRead(); break; // *NOP (implied) - case 0x5b: this.AbsoluteYAddress(); this.FixupRead(); this.SRE(); break; // *SRE (absolute, Y) - case 0x5c: this.AbsoluteXAddress(); this.MaybeFixupRead(); break; // *NOP (absolute, X) - case 0x5f: this.AbsoluteXAddress(); this.FixupRead(); this.SRE(); break; // *SRE (absolute, X) + case 0x52: this.Jam(); break; // *JAM + case 0x53: this.IndirectIndexedYAddress(); this.FixupRead(); this.SRE(); break; // *SRE (indirect indexed Y) + case 0x54: this.ZeroPageXRead(); break; // *NOP (zero page, X) + case 0x57: this.ZeroPageXRead(); this.SRE(); break; // *SRE (zero page, X) + case 0x5a: this.SwallowRead(); break; // *NOP (implied) + case 0x5b: this.AbsoluteYAddress(); this.FixupRead(); this.SRE(); break; // *SRE (absolute, Y) + case 0x5c: this.AbsoluteXAddress(); this.MaybeFixupRead(); break; // *NOP (absolute, X) + case 0x5f: this.AbsoluteXAddress(); this.FixupRead(); this.SRE(); break; // *SRE (absolute, X) - case 0x62: this.Jam(); break; // *JAM - case 0x63: this.IndexedIndirectXRead(); this.RRA(); break; // *RRA (indexed indirect X) - case 0x64: this.ZeroPageRead(); break; // *NOP (zero page) - case 0x67: this.ZeroPageRead(); this.RRA(); break; // *RRA (zero page) - case 0x6b: this.ImmediateRead(); this.ARR(); break; // *ARR (immediate) - case 0x6f: this.AbsoluteRead(); this.RRA(); break; // *RRA (absolute) + case 0x62: this.Jam(); break; // *JAM + case 0x63: this.IndexedIndirectXRead(); this.RRA(); break; // *RRA (indexed indirect X) + case 0x64: this.ZeroPageRead(); break; // *NOP (zero page) + case 0x67: this.ZeroPageRead(); this.RRA(); break; // *RRA (zero page) + case 0x6b: this.ImmediateRead(); this.ARR(); break; // *ARR (immediate) + case 0x6f: this.AbsoluteRead(); this.RRA(); break; // *RRA (absolute) - case 0x72: this.Jam(); break; // *JAM - case 0x73: this.IndirectIndexedYAddress(); this.FixupRead(); this.RRA(); break; // *RRA (indirect indexed Y) - case 0x74: this.ZeroPageXRead(); break; // *NOP (zero page, X) - case 0x77: this.ZeroPageXRead(); this.RRA(); break; // *RRA (zero page, X) - case 0x7a: this.SwallowRead(); break; // *NOP (implied) - case 0x7b: this.AbsoluteYAddress(); this.FixupRead(); this.RRA(); break; // *RRA (absolute, Y) - case 0x7c: this.AbsoluteXAddress(); this.MaybeFixupRead(); break; // *NOP (absolute, X) - case 0x7f: this.AbsoluteXAddress(); this.FixupRead(); this.RRA(); break; // *RRA (absolute, X) + case 0x72: this.Jam(); break; // *JAM + case 0x73: this.IndirectIndexedYAddress(); this.FixupRead(); this.RRA(); break; // *RRA (indirect indexed Y) + case 0x74: this.ZeroPageXRead(); break; // *NOP (zero page, X) + case 0x77: this.ZeroPageXRead(); this.RRA(); break; // *RRA (zero page, X) + case 0x7a: this.SwallowRead(); break; // *NOP (implied) + case 0x7b: this.AbsoluteYAddress(); this.FixupRead(); this.RRA(); break; // *RRA (absolute, Y) + case 0x7c: this.AbsoluteXAddress(); this.MaybeFixupRead(); break; // *NOP (absolute, X) + case 0x7f: this.AbsoluteXAddress(); this.FixupRead(); this.RRA(); break; // *RRA (absolute, X) - case 0x80: this.ImmediateRead(); break; // *NOP (immediate) - case 0x82: this.ImmediateRead(); break; // *NOP (immediate) - case 0x83: this.IndexedIndirectXAddress(); this.MemoryWrite((byte)(this.A & this.X)); break; // *SAX (indexed indirect X) - case 0x87: this.ZeroPageAddress(); this.MemoryWrite((byte)(this.A & this.X)); break; // *SAX (zero page) - case 0x89: this.ImmediateRead(); break; // *NOP (immediate) - case 0x8b: this.ImmediateRead(); this.ANE(); break; // *ANE (immediate) - case 0x8f: this.AbsoluteAddress(); this.MemoryWrite((byte)(this.A & this.X)); break; // *SAX (absolute) + case 0x80: this.ImmediateRead(); break; // *NOP (immediate) + case 0x82: this.ImmediateRead(); break; // *NOP (immediate) + case 0x83: this.IndexedIndirectXAddress(); this.MemoryWrite((byte)(this.A & this.X)); break; // *SAX (indexed indirect X) + case 0x87: this.ZeroPageAddress(); this.MemoryWrite((byte)(this.A & this.X)); break; // *SAX (zero page) + case 0x89: this.ImmediateRead(); break; // *NOP (immediate) + case 0x8b: this.ImmediateRead(); this.ANE(); break; // *ANE (immediate) + case 0x8f: this.AbsoluteAddress(); this.MemoryWrite((byte)(this.A & this.X)); break; // *SAX (absolute) - case 0x92: this.Jam(); break; // *JAM - case 0x93: this.IndirectIndexedYAddress(); this.Fixup(); this.SHA(); break; // *SHA (indirect indexed, Y) - case 0x97: this.ZeroPageYAddress(); this.MemoryWrite((byte)(this.A & this.X)); break; // *SAX (zero page, Y) - case 0x9b: this.AbsoluteYAddress(); this.Fixup(); this.TAS(); break; // *TAS (absolute, Y) - case 0x9c: this.AbsoluteXAddress(); this.Fixup(); this.SYA(); break; // *SYA (absolute, X) - case 0x9e: this.AbsoluteYAddress(); this.Fixup(); this.SXA(); break; // *SXA (absolute, Y) - case 0x9f: this.AbsoluteYAddress(); this.Fixup(); this.SHA(); break; // *SHA (absolute, Y) + case 0x92: this.Jam(); break; // *JAM + case 0x93: this.IndirectIndexedYAddress(); this.Fixup(); this.SHA(); break; // *SHA (indirect indexed, Y) + case 0x97: this.ZeroPageYAddress(); this.MemoryWrite((byte)(this.A & this.X)); break; // *SAX (zero page, Y) + case 0x9b: this.AbsoluteYAddress(); this.Fixup(); this.TAS(); break; // *TAS (absolute, Y) + case 0x9c: this.AbsoluteXAddress(); this.Fixup(); this.SYA(); break; // *SYA (absolute, X) + case 0x9e: this.AbsoluteYAddress(); this.Fixup(); this.SXA(); break; // *SXA (absolute, Y) + case 0x9f: this.AbsoluteYAddress(); this.Fixup(); this.SHA(); break; // *SHA (absolute, Y) - case 0xa3: this.IndexedIndirectXRead(); this.A = this.X = this.Through(); break; // *LAX (indexed indirect X) - case 0xa7: this.ZeroPageRead(); this.A = this.X = this.Through(); break; // *LAX (zero page) - case 0xab: this.ImmediateRead(); this.ATX(); break; // *ATX (immediate) - case 0xaf: this.AbsoluteRead(); this.A = this.X = this.Through(); break; // *LAX (absolute) + case 0xa3: this.IndexedIndirectXRead(); this.A = this.X = this.Through(); break; // *LAX (indexed indirect X) + case 0xa7: this.ZeroPageRead(); this.A = this.X = this.Through(); break; // *LAX (zero page) + case 0xab: this.ImmediateRead(); this.ATX(); break; // *ATX (immediate) + case 0xaf: this.AbsoluteRead(); this.A = this.X = this.Through(); break; // *LAX (absolute) - case 0xb2: this.Jam(); break; // *JAM - case 0xb3: this.IndirectIndexedYRead(); this.A = this.X = this.Through(); break; // *LAX (indirect indexed Y) - case 0xb7: this.ZeroPageYRead(); this.A = this.X = this.Through(); break; // *LAX (zero page, Y) - case 0xbb: this.AbsoluteYAddress(); this.MaybeFixup(); this.LAS(); break; // *LAS (absolute, Y) - case 0xbf: this.AbsoluteYRead(); this.A = this.X = this.Through(); break; // *LAX (absolute, Y) + case 0xb2: this.Jam(); break; // *JAM + case 0xb3: this.IndirectIndexedYRead(); this.A = this.X = this.Through(); break; // *LAX (indirect indexed Y) + case 0xb7: this.ZeroPageYRead(); this.A = this.X = this.Through(); break; // *LAX (zero page, Y) + case 0xbb: this.AbsoluteYAddress(); this.MaybeFixup(); this.LAS(); break; // *LAS (absolute, Y) + case 0xbf: this.AbsoluteYRead(); this.A = this.X = this.Through(); break; // *LAX (absolute, Y) - case 0xc2: this.ImmediateRead(); break; // *NOP (immediate) - case 0xc3: this.IndexedIndirectXRead(); this.DCP(); break; // *DCP (indexed indirect X) - case 0xc7: this.ZeroPageRead(); this.DCP(); break; // *DCP (zero page) - case 0xcb: this.ImmediateRead(); this.AXS(); break; // *AXS (immediate) - case 0xcf: this.AbsoluteRead(); this.DCP(); break; // *DCP (absolute) + case 0xc2: this.ImmediateRead(); break; // *NOP (immediate) + case 0xc3: this.IndexedIndirectXRead(); this.DCP(); break; // *DCP (indexed indirect X) + case 0xc7: this.ZeroPageRead(); this.DCP(); break; // *DCP (zero page) + case 0xcb: this.ImmediateRead(); this.AXS(); break; // *AXS (immediate) + case 0xcf: this.AbsoluteRead(); this.DCP(); break; // *DCP (absolute) - case 0xd2: this.Jam(); break; // *JAM - case 0xd3: this.IndirectIndexedYAddress(); this.FixupRead(); this.DCP(); break; // *DCP (indirect indexed Y) - case 0xd4: this.ZeroPageXRead(); break; // *NOP (zero page, X) - case 0xd7: this.ZeroPageXRead(); this.DCP(); break; // *DCP (zero page, X) - case 0xda: this.SwallowRead(); break; // *NOP (implied) - case 0xdb: this.AbsoluteYAddress(); this.FixupRead(); this.DCP(); break; // *DCP (absolute, Y) - case 0xdc: this.AbsoluteXAddress(); this.MaybeFixupRead(); break; // *NOP (absolute, X) - case 0xdf: this.AbsoluteXAddress(); this.FixupRead(); this.DCP(); break; // *DCP (absolute, X) + case 0xd2: this.Jam(); break; // *JAM + case 0xd3: this.IndirectIndexedYAddress(); this.FixupRead(); this.DCP(); break; // *DCP (indirect indexed Y) + case 0xd4: this.ZeroPageXRead(); break; // *NOP (zero page, X) + case 0xd7: this.ZeroPageXRead(); this.DCP(); break; // *DCP (zero page, X) + case 0xda: this.SwallowRead(); break; // *NOP (implied) + case 0xdb: this.AbsoluteYAddress(); this.FixupRead(); this.DCP(); break; // *DCP (absolute, Y) + case 0xdc: this.AbsoluteXAddress(); this.MaybeFixupRead(); break; // *NOP (absolute, X) + case 0xdf: this.AbsoluteXAddress(); this.FixupRead(); this.DCP(); break; // *DCP (absolute, X) - case 0xe2: this.ImmediateRead(); break; // *NOP (immediate) - case 0xe3: this.IndexedIndirectXRead(); this.ISB(); break; // *ISB (indexed indirect X) - case 0xe7: this.ZeroPageRead(); this.ISB(); break; // *ISB (zero page) - case 0xeb: this.ImmediateRead(); this.SBC(); break; // *SBC (immediate) - case 0xef: this.AbsoluteRead(); this.ISB(); break; // *ISB (absolute) + case 0xe2: this.ImmediateRead(); break; // *NOP (immediate) + case 0xe3: this.IndexedIndirectXRead(); this.ISB(); break; // *ISB (indexed indirect X) + case 0xe7: this.ZeroPageRead(); this.ISB(); break; // *ISB (zero page) + case 0xeb: this.ImmediateRead(); this.SBC(); break; // *SBC (immediate) + case 0xef: this.AbsoluteRead(); this.ISB(); break; // *ISB (absolute) - case 0xf2: this.Jam(); break; // *JAM - case 0xf3: this.IndirectIndexedYAddress(); this.FixupRead(); this.ISB(); break; // *ISB (indirect indexed Y) - case 0xf4: this.ZeroPageXRead(); break; // *NOP (zero page, X) - case 0xf7: this.ZeroPageXRead(); this.ISB(); break; // *ISB (zero page, X) - case 0xfa: this.SwallowRead(); break; // *NOP (implied) - case 0xfb: this.AbsoluteYAddress(); this.FixupRead(); this.ISB(); break; // *ISB (absolute, Y) - case 0xfc: this.AbsoluteXAddress(); this.MaybeFixupRead(); break; // *NOP (absolute, X) - case 0xff: this.AbsoluteXAddress(); this.FixupRead(); this.ISB(); break; // *ISB (absolute, X) + case 0xf2: this.Jam(); break; // *JAM + case 0xf3: this.IndirectIndexedYAddress(); this.FixupRead(); this.ISB(); break; // *ISB (indirect indexed Y) + case 0xf4: this.ZeroPageXRead(); break; // *NOP (zero page, X) + case 0xf7: this.ZeroPageXRead(); this.ISB(); break; // *ISB (zero page, X) + case 0xfa: this.SwallowRead(); break; // *NOP (implied) + case 0xfb: this.AbsoluteYAddress(); this.FixupRead(); this.ISB(); break; // *ISB (absolute, Y) + case 0xfc: this.AbsoluteXAddress(); this.MaybeFixupRead(); break; // *NOP (absolute, X) + case 0xff: this.AbsoluteXAddress(); this.FixupRead(); this.ISB(); break; // *ISB (absolute, X) } return cycles != this.Cycles; diff --git a/M6502/M6502Core.cs b/M6502/M6502Core.cs index 5dbc3af..bdcd1bc 100644 --- a/M6502/M6502Core.cs +++ b/M6502/M6502Core.cs @@ -361,172 +361,172 @@ namespace EightBit var cycles = this.Cycles; switch (this.OpCode) { - case 0x00: this.SwallowFetch(); this.Interrupt(IRQvector, InterruptSource.software); break; // BRK (implied) - case 0x01: this.IndexedIndirectXRead(); this.OrR(); break; // ORA (indexed indirect X) - case 0x05: this.ZeroPageRead(); this.OrR(); break; // ORA (zero page) - case 0x06: this.ZeroPageRead(); this.ModifyWrite(this.ASL()); break; // ASL (zero page) - case 0x08: this.SwallowRead(); this.PHP(); break; // PHP (implied) - case 0x09: this.ImmediateRead(); this.OrR(); break; // ORA (immediate) - case 0x0a: this.SwallowRead(); A = this.ASL(A); break; // ASL A (implied) - case 0x0d: this.AbsoluteRead(); this.OrR(); break; // ORA (absolute) - case 0x0e: this.AbsoluteRead(); this.ModifyWrite(this.ASL()); break; // ASL (absolute) + case 0x00: this.SwallowFetch(); this.Interrupt(IRQvector, InterruptSource.software); break; // BRK (implied) + case 0x01: this.IndexedIndirectXRead(); this.OrR(); break; // ORA (indexed indirect X) + case 0x05: this.ZeroPageRead(); this.OrR(); break; // ORA (zero page) + case 0x06: this.ZeroPageRead(); this.ModifyWrite(this.ASL()); break; // ASL (zero page) + case 0x08: this.SwallowRead(); this.PHP(); break; // PHP (implied) + case 0x09: this.ImmediateRead(); this.OrR(); break; // ORA (immediate) + case 0x0a: this.SwallowRead(); A = this.ASL(A); break; // ASL A (implied) + case 0x0d: this.AbsoluteRead(); this.OrR(); break; // ORA (absolute) + case 0x0e: this.AbsoluteRead(); this.ModifyWrite(this.ASL()); break; // ASL (absolute) - case 0x10: this.BranchNot(this.Negative); break; // BPL (relative) - case 0x11: this.IndirectIndexedYRead(); this.OrR(); break; // ORA (indirect indexed Y) - case 0x15: this.ZeroPageXRead(); this.OrR(); break; // ORA (zero page, X) - case 0x16: this.ZeroPageXRead(); this.ModifyWrite(this.ASL()); break; // ASL (zero page, X) - case 0x18: this.SwallowRead(); this.ResetFlag(StatusBits.CF); break; // CLC (implied) - case 0x19: this.AbsoluteYRead(); this.OrR(); break; // ORA (absolute, Y) - case 0x1d: this.AbsoluteXRead(); this.OrR(); break; // ORA (absolute, X) - case 0x1e: this.AbsoluteXAddress(); this.FixupRead(); this.ModifyWrite(this.ASL()); break; // ASL (absolute, X) + case 0x10: this.BranchNot(this.Negative); break; // BPL (relative) + case 0x11: this.IndirectIndexedYRead(); this.OrR(); break; // ORA (indirect indexed Y) + case 0x15: this.ZeroPageXRead(); this.OrR(); break; // ORA (zero page, X) + case 0x16: this.ZeroPageXRead(); this.ModifyWrite(this.ASL()); break; // ASL (zero page, X) + case 0x18: this.SwallowRead(); this.ResetFlag(StatusBits.CF); break; // CLC (implied) + case 0x19: this.AbsoluteYRead(); this.OrR(); break; // ORA (absolute, Y) + case 0x1d: this.AbsoluteXRead(); this.OrR(); break; // ORA (absolute, X) + case 0x1e: this.AbsoluteXAddress(); this.FixupRead(); this.ModifyWrite(this.ASL()); break; // ASL (absolute, X) - case 0x20: this.JSR(); break; // JSR (absolute) - case 0x21: this.IndexedIndirectXRead(); this.AndR(); break; // AND (indexed indirect X) - case 0x24: this.ZeroPageRead(); this.BIT(); break; // BIT (zero page) - case 0x25: this.ZeroPageRead(); this.AndR(); break; // AND (zero page) - case 0x26: this.ZeroPageRead(); this.ModifyWrite(this.ROL()); break; // ROL (zero page) - case 0x28: this.SwallowRead(); this.PLP(); break; // PLP (implied) - case 0x29: this.ImmediateRead(); this.AndR(); break; // AND (immediate) - case 0x2a: this.SwallowRead(); this.A = this.ROL(this.A); break; // ROL A (implied) - case 0x2c: this.AbsoluteRead(); this.BIT(); break; // BIT (absolute) - case 0x2d: this.AbsoluteRead(); this.AndR(); break; // AND (absolute) - case 0x2e: this.AbsoluteRead(); this.ModifyWrite(this.ROL()); break; // ROL (absolute) + case 0x20: this.JSR(); break; // JSR (absolute) + case 0x21: this.IndexedIndirectXRead(); this.AndR(); break; // AND (indexed indirect X) + case 0x24: this.ZeroPageRead(); this.BIT(); break; // BIT (zero page) + case 0x25: this.ZeroPageRead(); this.AndR(); break; // AND (zero page) + case 0x26: this.ZeroPageRead(); this.ModifyWrite(this.ROL()); break; // ROL (zero page) + case 0x28: this.SwallowRead(); this.PLP(); break; // PLP (implied) + case 0x29: this.ImmediateRead(); this.AndR(); break; // AND (immediate) + case 0x2a: this.SwallowRead(); this.A = this.ROL(this.A); break; // ROL A (implied) + case 0x2c: this.AbsoluteRead(); this.BIT(); break; // BIT (absolute) + case 0x2d: this.AbsoluteRead(); this.AndR(); break; // AND (absolute) + case 0x2e: this.AbsoluteRead(); this.ModifyWrite(this.ROL()); break; // ROL (absolute) - case 0x30: this.Branch(this.Negative); break; // BMI (relative) - case 0x31: this.IndirectIndexedYRead(); this.AndR(); break; // AND (indirect indexed Y) - case 0x35: this.ZeroPageXRead(); this.AndR(); break; // AND (zero page, X) - case 0x36: this.ZeroPageXRead(); this.ModifyWrite(this.ROL()); break; // ROL (zero page, X) - case 0x38: this.SwallowRead(); this.SetFlag(StatusBits.CF); break; // SEC (implied) - case 0x39: this.AbsoluteYRead(); this.AndR(); break; // AND (absolute, Y) - case 0x3d: this.AbsoluteXRead(); this.AndR(); break; // AND (absolute, X) - case 0x3e: this.AbsoluteXAddress(); this.FixupRead(); this.ModifyWrite(this.ROL()); break; // ROL (absolute, X) + case 0x30: this.Branch(this.Negative); break; // BMI (relative) + case 0x31: this.IndirectIndexedYRead(); this.AndR(); break; // AND (indirect indexed Y) + case 0x35: this.ZeroPageXRead(); this.AndR(); break; // AND (zero page, X) + case 0x36: this.ZeroPageXRead(); this.ModifyWrite(this.ROL()); break; // ROL (zero page, X) + case 0x38: this.SwallowRead(); this.SetFlag(StatusBits.CF); break; // SEC (implied) + case 0x39: this.AbsoluteYRead(); this.AndR(); break; // AND (absolute, Y) + case 0x3d: this.AbsoluteXRead(); this.AndR(); break; // AND (absolute, X) + case 0x3e: this.AbsoluteXAddress(); this.FixupRead(); this.ModifyWrite(this.ROL()); break; // ROL (absolute, X) - case 0x40: this.SwallowRead(); this.RTI(); break; // RTI (implied) - case 0x41: this.IndexedIndirectXRead(); this.EorR(); break; // EOR (indexed indirect X) - case 0x45: this.ZeroPageRead(); this.EorR(); break; // EOR (zero page) - case 0x46: this.ZeroPageRead(); this.ModifyWrite(this.LSR()); break; // LSR (zero page) - case 0x48: this.SwallowRead(); this.Push(this.A); break; // PHA (implied) - case 0x49: this.ImmediateRead(); this.EorR(); break; // EOR (immediate) - case 0x4a: this.SwallowRead(); this.A = this.LSR(this.A); break; // LSR A (implied) - case 0x4c: this.AbsoluteAddress(); this.Jump(this.Bus.Address); break; // JMP (absolute) - case 0x4d: this.AbsoluteRead(); this.EorR(); break; // EOR (absolute) - case 0x4e: this.AbsoluteRead(); this.ModifyWrite(this.LSR()); break; // LSR (absolute) + case 0x40: this.SwallowRead(); this.RTI(); break; // RTI (implied) + case 0x41: this.IndexedIndirectXRead(); this.EorR(); break; // EOR (indexed indirect X) + case 0x45: this.ZeroPageRead(); this.EorR(); break; // EOR (zero page) + case 0x46: this.ZeroPageRead(); this.ModifyWrite(this.LSR()); break; // LSR (zero page) + case 0x48: this.SwallowRead(); this.Push(this.A); break; // PHA (implied) + case 0x49: this.ImmediateRead(); this.EorR(); break; // EOR (immediate) + case 0x4a: this.SwallowRead(); this.A = this.LSR(this.A); break; // LSR A (implied) + case 0x4c: this.AbsoluteAddress(); this.Jump(this.Bus.Address); break; // JMP (absolute) + case 0x4d: this.AbsoluteRead(); this.EorR(); break; // EOR (absolute) + case 0x4e: this.AbsoluteRead(); this.ModifyWrite(this.LSR()); break; // LSR (absolute) - case 0x50: this.BranchNot(this.Overflow); break; // BVC (relative) - case 0x51: this.IndirectIndexedYRead(); this.EorR(); break; // EOR (indirect indexed Y) - case 0x55: this.ZeroPageXRead(); this.EorR(); break; // EOR (zero page, X) - case 0x56: this.ZeroPageXRead(); this.ModifyWrite(this.LSR()); break; // LSR (zero page, X) - case 0x58: this.SwallowRead(); this.ResetFlag(StatusBits.IF); break; // CLI (implied) - case 0x59: this.AbsoluteYRead(); this.EorR(); break; // EOR (absolute, Y) - case 0x5d: this.AbsoluteXRead(); this.EorR(); break; // EOR (absolute, X) - case 0x5e: this.AbsoluteXAddress(); this.FixupRead(); this.ModifyWrite(this.LSR()); break; // LSR (absolute, X) + case 0x50: this.BranchNot(this.Overflow); break; // BVC (relative) + case 0x51: this.IndirectIndexedYRead(); this.EorR(); break; // EOR (indirect indexed Y) + case 0x55: this.ZeroPageXRead(); this.EorR(); break; // EOR (zero page, X) + case 0x56: this.ZeroPageXRead(); this.ModifyWrite(this.LSR()); break; // LSR (zero page, X) + case 0x58: this.SwallowRead(); this.ResetFlag(StatusBits.IF); break; // CLI (implied) + case 0x59: this.AbsoluteYRead(); this.EorR(); break; // EOR (absolute, Y) + case 0x5d: this.AbsoluteXRead(); this.EorR(); break; // EOR (absolute, X) + case 0x5e: this.AbsoluteXAddress(); this.FixupRead(); this.ModifyWrite(this.LSR()); break; // LSR (absolute, X) - case 0x60: this.SwallowRead(); this.Return(); break; // RTS (implied) - case 0x61: this.IndexedIndirectXRead(); this.ADC(); break; // ADC (indexed indirect X) - case 0x65: this.ZeroPageRead(); this.ADC(); break; // ADC (zero page) - case 0x66: this.ZeroPageRead(); this.ModifyWrite(this.ROR()); break; // ROR (zero page) - case 0x68: this.SwallowRead(); this.SwallowPop(); this.A = this.Through(this.Pop()); break; // PLA (implied) - case 0x69: this.ImmediateRead(); this.ADC(); break; // ADC (immediate) - case 0x6a: this.SwallowRead(); this.A = this.ROR(this.A); break; // ROR A (implied) - case 0x6c: this.IndirectAddress(); this.Jump(this.Bus.Address); break; // JMP (indirect) - case 0x6d: this.AbsoluteRead(); this.ADC(); break; // ADC (absolute) - case 0x6e: this.AbsoluteRead(); this.ModifyWrite(this.ROR()); break; // ROR (absolute) + case 0x60: this.SwallowRead(); this.Return(); break; // RTS (implied) + case 0x61: this.IndexedIndirectXRead(); this.ADC(); break; // ADC (indexed indirect X) + case 0x65: this.ZeroPageRead(); this.ADC(); break; // ADC (zero page) + case 0x66: this.ZeroPageRead(); this.ModifyWrite(this.ROR()); break; // ROR (zero page) + case 0x68: this.SwallowRead(); this.SwallowPop(); this.A = this.Through(this.Pop()); break; // PLA (implied) + case 0x69: this.ImmediateRead(); this.ADC(); break; // ADC (immediate) + case 0x6a: this.SwallowRead(); this.A = this.ROR(this.A); break; // ROR A (implied) + case 0x6c: this.IndirectAddress(); this.Jump(this.Bus.Address); break; // JMP (indirect) + case 0x6d: this.AbsoluteRead(); this.ADC(); break; // ADC (absolute) + case 0x6e: this.AbsoluteRead(); this.ModifyWrite(this.ROR()); break; // ROR (absolute) - case 0x70: this.Branch(this.Overflow); break; // BVS (relative) - case 0x71: this.IndirectIndexedYRead(); this.ADC(); break; // ADC (indirect indexed Y) - case 0x75: this.ZeroPageXRead(); this.ADC(); break; // ADC (zero page, X) - case 0x76: this.ZeroPageXRead(); this.ModifyWrite(this.ROR()); break; // ROR (zero page, X) - case 0x78: this.SwallowRead(); this.SetFlag(StatusBits.IF); break; // SEI (implied) - case 0x79: this.AbsoluteYRead(); this.ADC(); break; // ADC (absolute, Y) - case 0x7d: this.AbsoluteXRead(); this.ADC(); break; // ADC (absolute, X) - case 0x7e: this.AbsoluteXAddress(); this.FixupRead(); this.ModifyWrite(this.ROR()); break; // ROR (absolute, X) + case 0x70: this.Branch(this.Overflow); break; // BVS (relative) + case 0x71: this.IndirectIndexedYRead(); this.ADC(); break; // ADC (indirect indexed Y) + case 0x75: this.ZeroPageXRead(); this.ADC(); break; // ADC (zero page, X) + case 0x76: this.ZeroPageXRead(); this.ModifyWrite(this.ROR()); break; // ROR (zero page, X) + case 0x78: this.SwallowRead(); this.SetFlag(StatusBits.IF); break; // SEI (implied) + case 0x79: this.AbsoluteYRead(); this.ADC(); break; // ADC (absolute, Y) + case 0x7d: this.AbsoluteXRead(); this.ADC(); break; // ADC (absolute, X) + case 0x7e: this.AbsoluteXAddress(); this.FixupRead(); this.ModifyWrite(this.ROR()); break; // ROR (absolute, X) - case 0x81: this.IndexedIndirectXAddress(); this.MemoryWrite(A); break; // STA (indexed indirect X) - case 0x84: this.ZeroPageAddress(); this.MemoryWrite(this.Y); break; // STY (zero page) - case 0x85: this.ZeroPageAddress(); this.MemoryWrite(this.A); break; // STA (zero page) - case 0x86: this.ZeroPageAddress(); this.MemoryWrite(this.X); break; // STX (zero page) - case 0x88: this.SwallowRead(); this.Y = this.DEC(this.Y); break; // DEY (implied) - case 0x8a: this.SwallowRead(); this.A = this.Through(this.X); break; // TXA (implied) - case 0x8c: this.AbsoluteAddress(); this.MemoryWrite(this.Y); break; // STY (absolute) - case 0x8d: this.AbsoluteAddress(); this.MemoryWrite(this.A); break; // STA (absolute) - case 0x8e: this.AbsoluteAddress(); this.MemoryWrite(this.X); break; // STX (absolute) + case 0x81: this.IndexedIndirectXAddress(); this.MemoryWrite(A); break; // STA (indexed indirect X) + case 0x84: this.ZeroPageAddress(); this.MemoryWrite(this.Y); break; // STY (zero page) + case 0x85: this.ZeroPageAddress(); this.MemoryWrite(this.A); break; // STA (zero page) + case 0x86: this.ZeroPageAddress(); this.MemoryWrite(this.X); break; // STX (zero page) + case 0x88: this.SwallowRead(); this.Y = this.DEC(this.Y); break; // DEY (implied) + case 0x8a: this.SwallowRead(); this.A = this.Through(this.X); break; // TXA (implied) + case 0x8c: this.AbsoluteAddress(); this.MemoryWrite(this.Y); break; // STY (absolute) + case 0x8d: this.AbsoluteAddress(); this.MemoryWrite(this.A); break; // STA (absolute) + case 0x8e: this.AbsoluteAddress(); this.MemoryWrite(this.X); break; // STX (absolute) - case 0x90: this.BranchNot(this.Carry); break; // BCC (relative) - case 0x91: this.IndirectIndexedYAddress(); this.Fixup(); this.MemoryWrite(this.A); break; // STA (indirect indexed Y) - case 0x94: this.ZeroPageXAddress(); this.MemoryWrite(this.Y); break; // STY (zero page, X) - case 0x95: this.ZeroPageXAddress(); this.MemoryWrite(this.A); break; // STA (zero page, X) - case 0x96: this.ZeroPageYAddress(); this.MemoryWrite(this.X); break; // STX (zero page, Y) - case 0x98: this.SwallowRead(); this.A = this.Through(this.Y); break; // TYA (implied) - case 0x99: this.AbsoluteYAddress(); this.Fixup(); this.MemoryWrite(this.A); break; // STA (absolute, Y) - case 0x9a: this.SwallowRead(); this.S = this.X; break; // TXS (implied) - case 0x9d: this.AbsoluteXAddress(); this.Fixup(); this.MemoryWrite(this.A); break; // STA (absolute, X) + case 0x90: this.BranchNot(this.Carry); break; // BCC (relative) + case 0x91: this.IndirectIndexedYAddress(); this.Fixup(); this.MemoryWrite(this.A); break; // STA (indirect indexed Y) + case 0x94: this.ZeroPageXAddress(); this.MemoryWrite(this.Y); break; // STY (zero page, X) + case 0x95: this.ZeroPageXAddress(); this.MemoryWrite(this.A); break; // STA (zero page, X) + case 0x96: this.ZeroPageYAddress(); this.MemoryWrite(this.X); break; // STX (zero page, Y) + case 0x98: this.SwallowRead(); this.A = this.Through(this.Y); break; // TYA (implied) + case 0x99: this.AbsoluteYAddress(); this.Fixup(); this.MemoryWrite(this.A); break; // STA (absolute, Y) + case 0x9a: this.SwallowRead(); this.S = this.X; break; // TXS (implied) + case 0x9d: this.AbsoluteXAddress(); this.Fixup(); this.MemoryWrite(this.A); break; // STA (absolute, X) - case 0xa0: this.ImmediateRead(); this.Y = this.Through(); break; // LDY (immediate) - case 0xa1: this.IndexedIndirectXRead(); this.A = this.Through(); break; // LDA (indexed indirect X) - case 0xa2: this.ImmediateRead(); this.X = this.Through(); break; // LDX (immediate) - case 0xa4: this.ZeroPageRead(); this.Y = this.Through(); break; // LDY (zero page) - case 0xa5: this.ZeroPageRead(); this.A = this.Through(); break; // LDA (zero page) - case 0xa6: this.ZeroPageRead(); this.X = this.Through(); break; // LDX (zero page) - case 0xa8: this.SwallowRead(); this.Y = Through(this.A); break; // TAY (implied) - case 0xa9: this.ImmediateRead(); this.A = this.Through(); break; // LDA (immediate) - case 0xaa: this.SwallowRead(); this.X = this.Through(this.A); break; // TAX (implied) - case 0xac: this.AbsoluteRead(); this.Y = this.Through(); break; // LDY (absolute) - case 0xad: this.AbsoluteRead(); this.A = this.Through(); break; // LDA (absolute) - case 0xae: this.AbsoluteRead(); this.X = this.Through(); break; // LDX (absolute) + case 0xa0: this.ImmediateRead(); this.Y = this.Through(); break; // LDY (immediate) + case 0xa1: this.IndexedIndirectXRead(); this.A = this.Through(); break; // LDA (indexed indirect X) + case 0xa2: this.ImmediateRead(); this.X = this.Through(); break; // LDX (immediate) + case 0xa4: this.ZeroPageRead(); this.Y = this.Through(); break; // LDY (zero page) + case 0xa5: this.ZeroPageRead(); this.A = this.Through(); break; // LDA (zero page) + case 0xa6: this.ZeroPageRead(); this.X = this.Through(); break; // LDX (zero page) + case 0xa8: this.SwallowRead(); this.Y = Through(this.A); break; // TAY (implied) + case 0xa9: this.ImmediateRead(); this.A = this.Through(); break; // LDA (immediate) + case 0xaa: this.SwallowRead(); this.X = this.Through(this.A); break; // TAX (implied) + case 0xac: this.AbsoluteRead(); this.Y = this.Through(); break; // LDY (absolute) + case 0xad: this.AbsoluteRead(); this.A = this.Through(); break; // LDA (absolute) + case 0xae: this.AbsoluteRead(); this.X = this.Through(); break; // LDX (absolute) - case 0xb0: this.Branch(this.Carry); break; // BCS (relative) - case 0xb1: this.IndirectIndexedYRead(); this.A = this.Through(); break; // LDA (indirect indexed Y) - case 0xb4: this.ZeroPageXRead(); this.Y = this.Through(); break; // LDY (zero page, X) - case 0xb5: this.ZeroPageXRead(); this.A = this.Through(); break; // LDA (zero page, X) - case 0xb6: this.ZeroPageYRead(); this.X = this.Through(); break; // LDX (zero page, Y) - case 0xb8: this.SwallowRead(); this.ResetFlag(StatusBits.VF); break; // CLV (implied) - case 0xb9: this.AbsoluteYRead(); this.A = this.Through(); break; // LDA (absolute, Y) - case 0xba: this.SwallowRead(); this.X = this.Through(this.S); break; // TSX (implied) - case 0xbc: this.AbsoluteXRead(); this.Y = this.Through(); break; // LDY (absolute, X) - case 0xbd: this.AbsoluteXRead(); this.A = this.Through(); break; // LDA (absolute, X) - case 0xbe: this.AbsoluteYRead(); this.X = this.Through(); break; // LDX (absolute, Y) + case 0xb0: this.Branch(this.Carry); break; // BCS (relative) + case 0xb1: this.IndirectIndexedYRead(); this.A = this.Through(); break; // LDA (indirect indexed Y) + case 0xb4: this.ZeroPageXRead(); this.Y = this.Through(); break; // LDY (zero page, X) + case 0xb5: this.ZeroPageXRead(); this.A = this.Through(); break; // LDA (zero page, X) + case 0xb6: this.ZeroPageYRead(); this.X = this.Through(); break; // LDX (zero page, Y) + case 0xb8: this.SwallowRead(); this.ResetFlag(StatusBits.VF); break; // CLV (implied) + case 0xb9: this.AbsoluteYRead(); this.A = this.Through(); break; // LDA (absolute, Y) + case 0xba: this.SwallowRead(); this.X = this.Through(this.S); break; // TSX (implied) + case 0xbc: this.AbsoluteXRead(); this.Y = this.Through(); break; // LDY (absolute, X) + case 0xbd: this.AbsoluteXRead(); this.A = this.Through(); break; // LDA (absolute, X) + case 0xbe: this.AbsoluteYRead(); this.X = this.Through(); break; // LDX (absolute, Y) - case 0xc0: this.ImmediateRead(); this.CMP(this.Y); break; // CPY (immediate) - case 0xc1: this.IndexedIndirectXRead(); this.CMP(this.A); break; // CMP (indexed indirect X) - case 0xc4: this.ZeroPageRead(); this.CMP(this.Y); break; // CPY (zero page) - case 0xc5: this.ZeroPageRead(); this.CMP(this.A); break; // CMP (zero page) - case 0xc6: this.ZeroPageRead(); this.ModifyWrite(this.DEC()); break; // DEC (zero page) - case 0xc8: this.SwallowRead(); this.Y = this.INC(this.Y); break; // INY (implied) - case 0xc9: this.ImmediateRead(); this.CMP(this.A); break; // CMP (immediate) - case 0xca: this.SwallowRead(); this.X = this.DEC(this.X); break; // DEX (implied) - case 0xcc: this.AbsoluteRead(); this.CMP(this.Y); break; // CPY (absolute) - case 0xcd: this.AbsoluteRead(); this.CMP(this.A); break; // CMP (absolute) - case 0xce: this.AbsoluteRead(); this.ModifyWrite(this.DEC()); break; // DEC (absolute) + case 0xc0: this.ImmediateRead(); this.CMP(this.Y); break; // CPY (immediate) + case 0xc1: this.IndexedIndirectXRead(); this.CMP(this.A); break; // CMP (indexed indirect X) + case 0xc4: this.ZeroPageRead(); this.CMP(this.Y); break; // CPY (zero page) + case 0xc5: this.ZeroPageRead(); this.CMP(this.A); break; // CMP (zero page) + case 0xc6: this.ZeroPageRead(); this.ModifyWrite(this.DEC()); break; // DEC (zero page) + case 0xc8: this.SwallowRead(); this.Y = this.INC(this.Y); break; // INY (implied) + case 0xc9: this.ImmediateRead(); this.CMP(this.A); break; // CMP (immediate) + case 0xca: this.SwallowRead(); this.X = this.DEC(this.X); break; // DEX (implied) + case 0xcc: this.AbsoluteRead(); this.CMP(this.Y); break; // CPY (absolute) + case 0xcd: this.AbsoluteRead(); this.CMP(this.A); break; // CMP (absolute) + case 0xce: this.AbsoluteRead(); this.ModifyWrite(this.DEC()); break; // DEC (absolute) - case 0xd0: this.BranchNot(this.Zero); break; // BNE (relative) - case 0xd1: this.IndirectIndexedYRead(); this.CMP(this.A); break; // CMP (indirect indexed Y) - case 0xd5: this.ZeroPageXRead(); this.CMP(this.A); break; // CMP (zero page, X) - case 0xd6: this.ZeroPageXRead(); this.ModifyWrite(this.DEC()); break; // DEC (zero page, X) - case 0xd8: this.SwallowRead(); this.ResetFlag(StatusBits.DF); break; // CLD (implied) - case 0xd9: this.AbsoluteYRead(); this.CMP(this.A); break; // CMP (absolute, Y) - case 0xdd: this.AbsoluteXRead(); this.CMP(this.A); break; // CMP (absolute, X) - case 0xde: this.AbsoluteXAddress(); this.FixupRead(); this.ModifyWrite(this.DEC()); break; // DEC (absolute, X) + case 0xd0: this.BranchNot(this.Zero); break; // BNE (relative) + case 0xd1: this.IndirectIndexedYRead(); this.CMP(this.A); break; // CMP (indirect indexed Y) + case 0xd5: this.ZeroPageXRead(); this.CMP(this.A); break; // CMP (zero page, X) + case 0xd6: this.ZeroPageXRead(); this.ModifyWrite(this.DEC()); break; // DEC (zero page, X) + case 0xd8: this.SwallowRead(); this.ResetFlag(StatusBits.DF); break; // CLD (implied) + case 0xd9: this.AbsoluteYRead(); this.CMP(this.A); break; // CMP (absolute, Y) + case 0xdd: this.AbsoluteXRead(); this.CMP(this.A); break; // CMP (absolute, X) + case 0xde: this.AbsoluteXAddress(); this.FixupRead(); this.ModifyWrite(this.DEC()); break; // DEC (absolute, X) - case 0xe0: this.ImmediateRead(); this.CMP(this.X); break; // CPX (immediate) - case 0xe1: this.IndexedIndirectXRead(); this.SBC(); break; // SBC (indexed indirect X) - case 0xe4: this.ZeroPageRead(); this.CMP(this.X); break; // CPX (zero page) - case 0xe5: this.ZeroPageRead(); this.SBC(); break; // SBC (zero page) - case 0xe6: this.ZeroPageRead(); this.ModifyWrite(INC()); break; // INC (zero page) - case 0xe8: this.SwallowRead(); this.X = this.INC(this.X); break; // INX (implied) - case 0xe9: this.ImmediateRead(); this.SBC(); break; // SBC (immediate) - case 0xea: this.SwallowRead(); break; // NOP (implied) - case 0xec: this.AbsoluteRead(); this.CMP(this.X); break; // CPX (absolute) - case 0xed: this.AbsoluteRead(); this.SBC(); break; // SBC (absolute) - case 0xee: this.AbsoluteRead(); this.ModifyWrite(this.INC()); break; // INC (absolute) + case 0xe0: this.ImmediateRead(); this.CMP(this.X); break; // CPX (immediate) + case 0xe1: this.IndexedIndirectXRead(); this.SBC(); break; // SBC (indexed indirect X) + case 0xe4: this.ZeroPageRead(); this.CMP(this.X); break; // CPX (zero page) + case 0xe5: this.ZeroPageRead(); this.SBC(); break; // SBC (zero page) + case 0xe6: this.ZeroPageRead(); this.ModifyWrite(INC()); break; // INC (zero page) + case 0xe8: this.SwallowRead(); this.X = this.INC(this.X); break; // INX (implied) + case 0xe9: this.ImmediateRead(); this.SBC(); break; // SBC (immediate) + case 0xea: this.SwallowRead(); break; // NOP (implied) + case 0xec: this.AbsoluteRead(); this.CMP(this.X); break; // CPX (absolute) + case 0xed: this.AbsoluteRead(); this.SBC(); break; // SBC (absolute) + case 0xee: this.AbsoluteRead(); this.ModifyWrite(this.INC()); break; // INC (absolute) - case 0xf0: this.Branch(this.Zero); break; // BEQ (relative) - case 0xf1: this.IndirectIndexedYRead(); this.SBC(); break; // SBC (indirect indexed Y) - case 0xf5: this.ZeroPageXRead(); this.SBC(); break; // SBC (zero page, X) - case 0xf6: this.ZeroPageXRead(); this.ModifyWrite(this.INC()); break; // INC (zero page, X) - case 0xf8: this.SwallowRead(); this.SetFlag(StatusBits.DF); break; // SED (implied) - case 0xf9: this.AbsoluteYRead(); this.SBC(); break; // SBC (absolute, Y) - case 0xfd: this.AbsoluteXRead(); this.SBC(); break; // SBC (absolute, X) - case 0xfe: this.AbsoluteXAddress(); this.FixupRead(); this.ModifyWrite(this.INC()); break; // INC (absolute, X) + case 0xf0: this.Branch(this.Zero); break; // BEQ (relative) + case 0xf1: this.IndirectIndexedYRead(); this.SBC(); break; // SBC (indirect indexed Y) + case 0xf5: this.ZeroPageXRead(); this.SBC(); break; // SBC (zero page, X) + case 0xf6: this.ZeroPageXRead(); this.ModifyWrite(this.INC()); break; // INC (zero page, X) + case 0xf8: this.SwallowRead(); this.SetFlag(StatusBits.DF); break; // SED (implied) + case 0xf9: this.AbsoluteYRead(); this.SBC(); break; // SBC (absolute, Y) + case 0xfd: this.AbsoluteXRead(); this.SBC(); break; // SBC (absolute, X) + case 0xfe: this.AbsoluteXAddress(); this.FixupRead(); this.ModifyWrite(this.INC()); break; // INC (absolute, X) } return cycles != this.Cycles; diff --git a/M6502/Profiler.cs b/M6502/Profiler.cs index e9784a5..0e283d8 100644 --- a/M6502/Profiler.cs +++ b/M6502/Profiler.cs @@ -128,6 +128,7 @@ { // Dump a profile/disassembly line var source = this.disassembler.Disassemble(address); + Debug.Assert(cycleDistributions != null); this.OnEmitLine(address, source, cycles, count, cycleDistributions); } } @@ -202,7 +203,7 @@ } } - private bool ExtractCycleDistribution(ushort address, out Dictionary cycleDistribution, out long cycleCount, out long hitCount) + private bool ExtractCycleDistribution(ushort address, out Dictionary? cycleDistribution, out long cycleCount, out long hitCount) { cycleDistribution = addressCycleDistributions[address]; if (cycleDistribution == null) @@ -212,6 +213,8 @@ return false; } + Debug.Assert(cycleDistribution.Count > 0); + cycleCount = hitCount = 0L; foreach (var (cycle, count) in cycleDistribution) { @@ -219,6 +222,9 @@ cycleCount += (cycle * count); } + Debug.Assert(hitCount > 0); + Debug.Assert(cycleCount > 0); + return true; } diff --git a/Z80/Z80.Test/Board.cs b/Z80/Z80.Test/Board.cs index aea87ee..e763aaf 100644 --- a/Z80/Z80.Test/Board.cs +++ b/Z80/Z80.Test/Board.cs @@ -19,11 +19,11 @@ namespace Z80.Test public Board(Configuration configuration) { this.configuration = configuration; - this.ram = new Ram(0x10000); - this.ports = new InputOutput(); - this.CPU = new Z80(this, this.ports); - this.disassembler = new Disassembler(this); - this.mapping = new MemoryMapping(this.ram, 0x0000, (ushort)Mask.Sixteen, AccessLevel.ReadWrite); + this.ram = new(0x10000); + this.ports = new(); + this.CPU = new(this, this.ports); + this.disassembler = new(this); + this.mapping = new(this.ram, 0x0000, (ushort)Mask.Sixteen, AccessLevel.ReadWrite); } public Z80 CPU { get; } @@ -81,7 +81,7 @@ namespace Z80.Test } } - private void CPU_ExecutingInstruction_CPM(object sender, System.EventArgs e) + private void CPU_ExecutingInstruction_CPM(object? sender, System.EventArgs e) { if (this.CPU.PC.High != 0) { @@ -105,8 +105,8 @@ namespace Z80.Test } } - private void CPU_LoweredHALT(object sender, System.EventArgs e) => this.LowerPOWER(); + private void CPU_LoweredHALT(object? sender, System.EventArgs e) => this.LowerPOWER(); - private void CPU_ExecutingInstruction_Debug(object sender, System.EventArgs e) => System.Console.Error.WriteLine($"{EightBit.Disassembler.State(this.CPU)}\t{this.disassembler.Disassemble(this.CPU)}"); + private void CPU_ExecutingInstruction_Debug(object? sender, System.EventArgs e) => System.Console.Error.WriteLine($"{EightBit.Disassembler.State(this.CPU)}\t{this.disassembler.Disassemble(this.CPU)}"); } } diff --git a/Z80/Z80.Test/Configuration.cs b/Z80/Z80.Test/Configuration.cs index fa22c9d..a9a1a69 100644 --- a/Z80/Z80.Test/Configuration.cs +++ b/Z80/Z80.Test/Configuration.cs @@ -14,9 +14,9 @@ namespace Z80.Test public bool DebugMode { get; set; } = false; - public Register16 LoadAddress { get; } = new Register16(0x100); + public Register16 LoadAddress { get; } = new(0x100); - public Register16 StartAddress { get; } = new Register16(0x100); + public Register16 StartAddress { get; } = new(0x100); public string RomDirectory { get; } = "roms"; diff --git a/Z80/Z80.Test/TestHarness.cs b/Z80/Z80.Test/TestHarness.cs index 8b7c16e..d8e5396 100644 --- a/Z80/Z80.Test/TestHarness.cs +++ b/Z80/Z80.Test/TestHarness.cs @@ -7,16 +7,14 @@ namespace Z80.Test using System; using System.Diagnostics; - internal class TestHarness : IDisposable + internal class TestHarness(Configuration configuration) : IDisposable { - private readonly Stopwatch timer = new Stopwatch(); - private readonly Board board; + private readonly Stopwatch timer = new(); + private readonly Board board = new(configuration); private long totalCycles = 0; private bool disposed = false; - public TestHarness(Configuration configuration) => this.board = new Board(configuration); - public void Dispose() { this.Dispose(true); diff --git a/Z80/Z80.cs b/Z80/Z80.cs index 00896b3..abd1a0a 100644 --- a/Z80/Z80.cs +++ b/Z80/Z80.cs @@ -118,13 +118,13 @@ namespace EightBit public override Register16 HL => this.registers[this.registerSet, (int)RegisterIndex.IndexHL]; - public Register16 IX { get; } = new Register16(0xffff); + public Register16 IX { get; } = new(0xffff); public byte IXH { get => this.IX.High; set => this.IX.High = value; } public byte IXL { get => this.IX.Low; set => this.IX.Low = value; } - public Register16 IY { get; } = new Register16(0xffff); + public Register16 IY { get; } = new(0xffff); public byte IYH { get => this.IY.High; set => this.IY.High = value; } @@ -410,7 +410,7 @@ namespace EightBit this.DisableInterrupts(); this.IM = 0; - this.REFRESH = new RefreshRegister(0); + this.REFRESH = new(0); this.IV = (byte)Mask.Eight; this.ExxAF();