1
0
mirror of https://github.com/MoleskiCoder/EightBitNet.git synced 2025-04-28 05:49:27 +00:00

Code analysis corrections.

This commit is contained in:
Adrian Conlon 2024-10-09 22:15:25 +01:00
parent 647be6f224
commit f0815d4150
13 changed files with 170 additions and 115 deletions

@ -14,6 +14,7 @@ namespace EightBit
public override void PokeWord(ushort address, Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
Bus.Poke(address, value.High);
Bus.Poke(++address, value.Low);
}
@ -50,12 +51,14 @@ namespace EightBit
protected override void PushWord(Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
Push(value.Low);
Push(value.High);
}
protected override void SetWord(Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
MemoryWrite(value.High);
++Bus.Address.Word;
MemoryWrite(value.Low);
@ -63,6 +66,7 @@ namespace EightBit
protected override void SetWordPaged(Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
MemoryWrite(value.High);
++Bus.Address.Low;
MemoryWrite(value.Low);

@ -28,13 +28,21 @@ namespace EightBit
public byte Peek(ushort absolute) => Reference(absolute);
public byte Peek(Register16 absolute) => Peek(absolute.Word);
public byte Peek(Register16 absolute)
{
ArgumentNullException.ThrowIfNull(absolute);
return Peek(absolute.Word);
}
public void Poke(byte value) => Reference() = value;
public void Poke(ushort absolute, byte value) => Reference(absolute) = value;
public void Poke(Register16 absolute, byte value) => Poke(absolute.Word, value);
public void Poke(Register16 absolute, byte value)
{
ArgumentNullException.ThrowIfNull(absolute);
Poke(absolute.Word, value);
}
public byte Read()
{
@ -50,7 +58,11 @@ namespace EightBit
return Read();
}
public byte Read(Register16 absolute) => Read(absolute.Low, absolute.High);
public byte Read(Register16 absolute)
{
ArgumentNullException.ThrowIfNull(absolute);
return Read(absolute.Low, absolute.High);
}
public byte Read(byte low, byte high)
{
@ -77,7 +89,11 @@ namespace EightBit
Write(value);
}
public void Write(Register16 absolute, byte value) => Write(absolute.Low, absolute.High, value);
public void Write(Register16 absolute, byte value)
{
ArgumentNullException.ThrowIfNull(absolute);
Write(absolute.Low, absolute.High, value);
}
public void Write(byte low, byte high, byte value)
{
@ -116,7 +132,11 @@ namespace EightBit
return ref mapped.Memory.Reference(offset);
}
protected ref byte Reference(Register16 absolute) => ref Reference(absolute.Word);
protected ref byte Reference(Register16 absolute)
{
ArgumentNullException.ThrowIfNull(absolute);
return ref Reference(absolute.Word);
}
protected ref byte Reference() => ref Reference(Address);

@ -15,6 +15,7 @@ namespace EightBit
public override void PokeWord(ushort address, Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
Bus.Poke(address, value.Low);
Bus.Poke(++address, value.High);
}
@ -51,12 +52,14 @@ namespace EightBit
protected override void PushWord(Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
Push(value.High);
Push(value.Low);
}
protected override void SetWord(Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
MemoryWrite(value.Low);
++Bus.Address.Word;
MemoryWrite(value.High);
@ -64,6 +67,7 @@ namespace EightBit
protected override void SetWordPaged(Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
MemoryWrite(value.Low);
++Bus.Address.Low;
MemoryWrite(value.High);

@ -176,9 +176,17 @@ namespace EightBit
MemoryWrite(data);
}
protected void MemoryWrite(Register16 address, byte data) => MemoryWrite(address.Low, address.High, data);
protected void MemoryWrite(Register16 address, byte data)
{
ArgumentNullException.ThrowIfNull(address);
MemoryWrite(address.Low, address.High, data);
}
protected void MemoryWrite(Register16 address) => MemoryWrite(address.Low, address.High);
protected void MemoryWrite(Register16 address)
{
ArgumentNullException.ThrowIfNull(address);
MemoryWrite(address.Low, address.High);
}
protected void MemoryWrite(byte data)
{
@ -202,7 +210,11 @@ namespace EightBit
return MemoryRead();
}
protected byte MemoryRead(Register16 address) => MemoryRead(address.Low, address.High);
protected byte MemoryRead(Register16 address)
{
ArgumentNullException.ThrowIfNull(address);
return MemoryRead(address.Low, address.High);
}
protected virtual byte MemoryRead() => BusRead();
@ -223,6 +235,7 @@ namespace EightBit
protected Register16 GetWordPaged(Register16 address)
{
ArgumentNullException.ThrowIfNull(address);
return GetWordPaged(address.High, address.Low);
}
@ -236,6 +249,7 @@ namespace EightBit
protected void SetWordPaged(Register16 address, Register16 value)
{
ArgumentNullException.ThrowIfNull(address);
SetWordPaged(address.High, address.Low, value);
}

@ -46,6 +46,7 @@ namespace EightBit
public Register16(Register16 rhs)
{
ArgumentNullException.ThrowIfNull(rhs);
Low = rhs.Low;
High = rhs.High;
}
@ -65,7 +66,11 @@ namespace EightBit
public ref byte High => ref _high;
public static bool operator ==(Register16 left, Register16 right) => left.Equals(right);
public static bool operator ==(Register16 left, Register16 right)
{
ArgumentNullException.ThrowIfNull(left);
return left.Equals(right);
}
public static bool operator !=(Register16 left, Register16 right) => !(left == right);
@ -99,6 +104,7 @@ namespace EightBit
public void Assign(Register16 from)
{
ArgumentNullException.ThrowIfNull(from);
Assign(from._low, from._high);
}
}

@ -12,6 +12,9 @@ namespace EightBit
public static int Load(Stream file, ref byte[] output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1)
{
ArgumentNullException.ThrowIfNull(file);
ArgumentNullException.ThrowIfNull(output);
var size = (int)file.Length;
if ((maximumSize > 0) && ((size - readOffset) > maximumSize))
@ -61,6 +64,8 @@ namespace EightBit
public override int Load(byte[] from, int writeOffset = 0, int readOffset = 0, int limit = -1)
{
ArgumentNullException.ThrowIfNull(from);
if (limit < 0)
{
limit = Math.Min(from.Length, Size - readOffset);

@ -16,11 +16,11 @@
public bool Valid { get; private set; }
public bool Invalid => !this.Valid;
public bool Invalid => !Valid;
public bool Unimplemented => this.Invalid && this.CycleCountMismatch && (this.Cycles == 1);
public bool Unimplemented => Invalid && CycleCountMismatch && (Cycles == 1);
public bool Implemented => !this.Unimplemented;
public bool Implemented => !Unimplemented;
public List<string> Messages { get; } = [];
@ -28,67 +28,67 @@
public Checker(TestRunner runner)
{
this.Runner = runner;
this.Disassembler = new(this.Runner, (M6502.Core)this.Runner.CPU, this.Symbols);
Runner = runner;
Disassembler = new(Runner, (M6502.Core)Runner.CPU, Symbols);
}
public void Check(Test test)
{
var cpu = this.Runner.CPU;
var cpu = Runner.CPU;
this.Reset();
Reset();
this.Runner.RaisePOWER();
this.InitialiseState(test);
Runner.RaisePOWER();
InitialiseState(test);
var pc = cpu.PC.Word;
this.Cycles = cpu.Step();
this.Runner.LowerPOWER();
Cycles = cpu.Step();
Runner.LowerPOWER();
this.Valid = this.CheckState(test);
Valid = CheckState(test);
if (this.Unimplemented)
if (Unimplemented)
{
this.Messages.Add("Unimplemented");
Messages.Add("Unimplemented");
return;
}
Debug.Assert(this.Implemented);
if (this.Invalid)
Debug.Assert(Implemented);
if (Invalid)
{
this.AddDisassembly(pc);
AddDisassembly(pc);
var final = test.Final ?? throw new InvalidOperationException("Final test state cannot be null");
this.Raise("PC", final.PC, cpu.PC.Word);
this.Raise("S", final.S, cpu.S);
this.Raise("A", final.A, cpu.A);
this.Raise("X", final.X, cpu.X);
this.Raise("Y", final.Y, cpu.Y);
this.Raise("P", final.P, cpu.P);
Raise("PC", final.PC, cpu.PC.Word);
Raise("S", final.S, cpu.S);
Raise("A", final.A, cpu.A);
Raise("X", final.X, cpu.X);
Raise("Y", final.Y, cpu.Y);
Raise("P", final.P, cpu.P);
if (test.Cycles == null)
{
throw new InvalidOperationException("test cycles cannot be null");
}
this.Messages.Add($"Fixed page is: {cpu.FixedPage:X2}");
Messages.Add($"Fixed page is: {cpu.FixedPage:X2}");
this.Messages.Add($"Stepped cycles: {this.Cycles}, expected events: {test.Cycles.Count}, actual events: {this.ActualCycles.Count}");
Messages.Add($"Stepped cycles: {Cycles}, expected events: {test.Cycles.Count}, actual events: {ActualCycles.Count}");
this.DumpCycles("-- Expected cycles", test.AvailableCycles());
this.DumpCycles("-- Actual cycles", this.ActualCycles);
DumpCycles("-- Expected cycles", test.AvailableCycles());
DumpCycles("-- Actual cycles", ActualCycles);
}
}
private void Reset()
{
this.Messages.Clear();
this.ActualCycles.Clear();
Messages.Clear();
ActualCycles.Clear();
this.CycleCountMismatch = false;
this.Cycles = 0;
this.Valid = false;
CycleCountMismatch = false;
Cycles = 0;
Valid = false;
}
private bool Check(string what, ushort expected, ushort actual)
@ -96,7 +96,7 @@
var success = actual == expected;
if (!success)
{
this.Raise(what, expected, actual);
Raise(what, expected, actual);
}
return success;
}
@ -106,7 +106,7 @@
var success = actual == expected;
if (!success)
{
this.Raise(what, expected, actual);
Raise(what, expected, actual);
}
return success;
}
@ -118,7 +118,7 @@
var success = actual == expected;
if (!success)
{
this.Raise(what, expected, actual);
Raise(what, expected, actual);
}
return success;
}
@ -128,7 +128,7 @@
var success = actual == expected;
if (!success)
{
this.Raise($"{what}: {address}", expected, actual);
Raise($"{what}: {address}", expected, actual);
}
return success;
}
@ -138,32 +138,32 @@
string message;
try
{
message = this.Disassemble(address);
message = Disassemble(address);
}
catch (InvalidOperationException error)
{
message = $"Disassembly problem: {error.Message}";
}
this.Messages.Add(message);
Messages.Add(message);
}
private string Disassemble(ushort address) => this.Disassembler.Disassemble(address);
private string Disassemble(ushort address) => Disassembler.Disassemble(address);
private bool CheckState(Test test)
{
var cpu = this.Runner.CPU;
var ram = this.Runner.RAM;
var cpu = Runner.CPU;
var ram = Runner.RAM;
var expectedCycles = test.AvailableCycles();
var actualCycles = this.ActualCycles;
var actualCycles = ActualCycles;
var actualIDX = 0;
foreach (var expectedCycle in expectedCycles) {
if (actualIDX >= actualCycles.Count)
{
this.CycleCountMismatch = true;
CycleCountMismatch = true;
return false; // more expected cycles than actual
}
@ -171,40 +171,40 @@
var expectedAddress = expectedCycle.Address;
var actualAddress = actualCycle.Address;
_ = this.Check("Cycle address", expectedAddress, actualAddress);
_ = Check("Cycle address", expectedAddress, actualAddress);
var expectedValue = expectedCycle.Value;
var actualValue = actualCycle.Value;
_ = this.Check("Cycle value", expectedValue, actualValue);
_ = Check("Cycle value", expectedValue, actualValue);
var expectedAction = expectedCycle.Type;
var actualAction = actualCycle.Type;
_ = this.Check("Cycle action", expectedAction, actualAction);
_ = Check("Cycle action", expectedAction, actualAction);
}
if (actualIDX < actualCycles.Count)
{
this.CycleCountMismatch = true;
CycleCountMismatch = true;
return false; // less expected cycles than actual
}
if (this.Messages.Count > 0)
if (Messages.Count > 0)
{
return false;
}
var final = test.Final ?? throw new InvalidOperationException("Final state cannot be null");
var pc_good = this.Check("PC", final.PC, cpu.PC.Word);
var s_good = this.Check("S", final.S, cpu.S);
var a_good = this.Check("A", final.A, cpu.A);
var x_good = this.Check("X", final.X, cpu.X);
var y_good = this.Check("Y", final.Y, cpu.Y);
var p_good = this.Check("P", final.P, cpu.P);
var pc_good = Check("PC", final.PC, cpu.PC.Word);
var s_good = Check("S", final.S, cpu.S);
var a_good = Check("A", final.A, cpu.A);
var x_good = Check("X", final.X, cpu.X);
var y_good = Check("Y", final.Y, cpu.Y);
var p_good = Check("P", final.P, cpu.P);
if (!p_good)
{
this.Messages.Add($"Expected flags: {Disassembler.DumpFlags(final.P)}");
this.Messages.Add($"Actual flags : {Disassembler.DumpFlags(cpu.P)}");
Messages.Add($"Expected flags: {Disassembler.DumpFlags(final.P)}");
Messages.Add($"Actual flags : {Disassembler.DumpFlags(cpu.P)}");
}
if (final.RAM == null)
@ -223,7 +223,7 @@
var address = (ushort)entry[0];
var value = (byte)entry[1];
var ramGood = this.Check("RAM", address, value, ram.Peek(address));
var ramGood = Check("RAM", address, value, ram.Peek(address));
if (!ramGood && !ramProblem)
{
ramProblem = true;
@ -236,28 +236,28 @@
&& !ramProblem;
}
private void Raise(string what, ushort expected, ushort actual) => this.Messages.Add($"{what}: expected: {expected:X4}, actual: {actual:X4}");
private void Raise(string what, ushort expected, ushort actual) => Messages.Add($"{what}: expected: {expected:X4}, actual: {actual:X4}");
private void Raise(string what, byte expected, byte actual) => this.Messages.Add($"{what}: expected: {expected:X2}, actual: {actual:X2}");
private void Raise(string what, byte expected, byte actual) => Messages.Add($"{what}: expected: {expected:X2}, actual: {actual:X2}");
private void Raise(string what, string expected, string actual) => this.Messages.Add($"{what}: expected: {expected}, actual: {actual}");
private void Raise(string what, string expected, string actual) => Messages.Add($"{what}: expected: {expected}, actual: {actual}");
public void Initialise()
{
this.Runner.ReadByte += this.Runner_ReadByte;
this.Runner.WrittenByte += this.Runner_WrittenByte;
Runner.ReadByte += Runner_ReadByte;
Runner.WrittenByte += Runner_WrittenByte;
}
private void InitialiseState(Test test)
{
var initial = test.Initial ?? throw new InvalidOperationException("Test cannot have an invalid initial state");
this.InitialiseState(initial);
InitialiseState(initial);
}
private void InitialiseState(State state)
{
var cpu = this.Runner.CPU;
var ram = this.Runner.RAM;
var cpu = Runner.CPU;
var ram = Runner.RAM;
cpu.PC.Word = state.PC;
cpu.S = state.S;
@ -281,39 +281,39 @@
}
}
private void Runner_ReadByte(object? sender, EventArgs e) => this.AddActualReadCycle(this.Runner.Address, this.Runner.Data);
private void Runner_ReadByte(object? sender, EventArgs e) => AddActualReadCycle(Runner.Address, Runner.Data);
private void Runner_WrittenByte(object? sender, EventArgs e) => this.AddActualWriteCycle(this.Runner.Address, this.Runner.Data);
private void Runner_WrittenByte(object? sender, EventArgs e) => AddActualWriteCycle(Runner.Address, Runner.Data);
private void AddActualReadCycle(EightBit.Register16 address, byte value) => this.AddActualCycle(address, value, "read");
private void AddActualReadCycle(EightBit.Register16 address, byte value) => AddActualCycle(address, value, "read");
private void AddActualWriteCycle(EightBit.Register16 address, byte value) => this.AddActualCycle(address, value, "write");
private void AddActualWriteCycle(EightBit.Register16 address, byte value) => AddActualCycle(address, value, "write");
private void AddActualCycle(EightBit.Register16 address, byte value, string action) => this.AddActualCycle(address.Word, value, action);
private void AddActualCycle(EightBit.Register16 address, byte value, string action) => AddActualCycle(address.Word, value, action);
private void AddActualCycle(ushort address, byte value, string action) => this.ActualCycles.Add(new Cycle(address, value, action));
private void AddActualCycle(ushort address, byte value, string action) => ActualCycles.Add(new Cycle(address, value, action));
private void DumpCycle(ushort address, byte value, string? action)
{
ArgumentNullException.ThrowIfNull(action);
this.Messages.Add($"Address: {address:X4}, value: {value:X2}, action: {action}");
Messages.Add($"Address: {address:X4}, value: {value:X2}, action: {action}");
}
private void DumpCycle(Cycle cycle) => this.DumpCycle(cycle.Address, cycle.Value, cycle.Type);
private void DumpCycle(Cycle cycle) => DumpCycle(cycle.Address, cycle.Value, cycle.Type);
private void DumpCycles(IEnumerable<Cycle>? cycles)
{
ArgumentNullException.ThrowIfNull(cycles);
foreach (var cycle in cycles)
{
this.DumpCycle(cycle);
DumpCycle(cycle);
}
}
private void DumpCycles(string which, IEnumerable<Cycle>? events)
{
this.Messages.Add(which);
this.DumpCycles(events);
Messages.Add(which);
DumpCycles(events);
}
}
}

@ -10,21 +10,23 @@
public Cycle(ushort address, byte value, string type)
{
this.Address = address;
this.Value = value;
this.Type = type;
Address = address;
Value = value;
Type = type;
}
public Cycle(List<object> input)
{
ArgumentNullException.ThrowIfNull(input);
if (input.Count != 3)
{
throw new ArgumentOutOfRangeException(nameof(input), input, "Cycles can only have three elements");
}
this.Address = AsElement(input[0]).GetUInt16();
this.Value = AsElement(input[1]).GetByte();
this.Type = AsElement(input[2]).GetString();
Address = AsElement(input[0]).GetUInt16();
Value = AsElement(input[1]).GetByte();
Type = AsElement(input[2]).GetString();
}
private static System.Text.Json.JsonElement AsElement(object part) => (System.Text.Json.JsonElement)part;

@ -10,30 +10,30 @@
UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow,
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
};
private bool disposed;
private bool _disposed;
public string Path { get; set; } = path;
private readonly FileStream stream = File.Open(path, FileMode.Open);
private readonly FileStream _stream = File.Open(path, FileMode.Open);
public IAsyncEnumerable<Test?> TestsAsync => JsonSerializer.DeserializeAsyncEnumerable<Test>(this.stream, SerializerOptions);
public IAsyncEnumerable<Test?> TestsAsync => JsonSerializer.DeserializeAsyncEnumerable<Test>(_stream, SerializerOptions);
private void Dispose(bool disposing)
{
if (!this.disposed)
if (!_disposed)
{
if (disposing)
{
this.stream.Dispose();
_stream.Dispose();
}
this.disposed = true;
_disposed = true;
}
}
public void Dispose()
{
this.Dispose(disposing: true);
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}

@ -6,7 +6,7 @@
public IEnumerable<OpcodeTestSuite> OpcodeTests()
{
foreach (var filename in Directory.EnumerateFiles(this.Location, "*.json"))
foreach (var filename in Directory.EnumerateFiles(Location, "*.json"))
{
var fileInformation = new FileInfo(filename);
if (fileInformation.Length > 0)

@ -4,13 +4,12 @@
namespace M6502.HarteTest
{
using System.IO;
public static class Program
{
public static async Task Main(string[] _)
{
var directory = @"C:\github\spectrum\libraries\EightBit\modules\65x02\6502\v1";
//var directory = @"C:\github\spectrum\libraries\EightBit\modules\65x02\wdc65c02\v1";
await ProcessTestSuiteAsync(directory);
}

@ -12,12 +12,12 @@
public IEnumerable<Cycle> AvailableCycles()
{
if (this.Cycles == null)
if (Cycles == null)
{
throw new InvalidOperationException("Cycles have not been initialised");
}
foreach (var cycle in this.Cycles)
foreach (var cycle in Cycles)
{
yield return new Cycle(cycle);
}

@ -6,14 +6,15 @@
{
public Ram RAM { get; } = new(0x10000);
public M6502 CPU { get; }
public MOS6502 CPU { get; }
//public WDC65C02 CPU { get; }
private readonly MemoryMapping mapping;
private readonly MemoryMapping _mapping;
public TestRunner()
{
this.CPU = new(this);
this.mapping = new(this.RAM, 0x0000, (ushort)Mask.Sixteen, AccessLevel.ReadWrite);
CPU = new(this);
_mapping = new(RAM, 0x0000, (ushort)Mask.Sixteen, AccessLevel.ReadWrite);
}
public override void Initialize()
@ -22,21 +23,21 @@
public override void LowerPOWER()
{
this.CPU.LowerPOWER();
CPU.LowerPOWER();
base.LowerPOWER();
}
public override MemoryMapping Mapping(ushort _) => this.mapping;
public override MemoryMapping Mapping(ushort _) => _mapping;
public override void RaisePOWER()
{
base.RaisePOWER();
this.CPU.RaisePOWER();
this.CPU.RaiseRESET();
this.CPU.RaiseINT();
this.CPU.RaiseNMI();
this.CPU.RaiseSO();
this.CPU.RaiseRDY();
CPU.RaisePOWER();
CPU.RaiseRESET();
CPU.RaiseINT();
CPU.RaiseNMI();
CPU.RaiseSO();
CPU.RaiseRDY();
}
}
}