diff --git a/EightBit/BigEndianProcessor.cs b/EightBit/BigEndianProcessor.cs index 808857d..494f956 100644 --- a/EightBit/BigEndianProcessor.cs +++ b/EightBit/BigEndianProcessor.cs @@ -3,14 +3,9 @@ // namespace EightBit { - public abstract class BigEndianProcessor : Processor + public abstract class BigEndianProcessor(Bus memory) : Processor(memory) { - private readonly Register16 intermediate = new Register16(); - - protected BigEndianProcessor(Bus memory) - : base(memory) - { - } + private readonly Register16 intermediate = new(); public override Register16 PeekWord(ushort address) { diff --git a/EightBit/Bus.cs b/EightBit/Bus.cs index 6e8f72c..6bbe12e 100644 --- a/EightBit/Bus.cs +++ b/EightBit/Bus.cs @@ -10,13 +10,13 @@ namespace EightBit { private byte data; - public event EventHandler WritingByte; + public event EventHandler? WritingByte; - public event EventHandler WrittenByte; + public event EventHandler? WrittenByte; - public event EventHandler ReadingByte; + public event EventHandler? ReadingByte; - public event EventHandler ReadByte; + public event EventHandler? ReadByte; public byte Data { get => this.data; set => this.data = value; } @@ -113,7 +113,7 @@ namespace EightBit protected ref byte Reference(ushort absolute) { var mapped = this.Mapping(absolute); - var offset = (ushort)((absolute - mapped.Begin) & mapped.Mask); + var offset = (ushort)mapped.Offset(absolute); if (mapped.Access == AccessLevel.ReadOnly) { this.Data = mapped.Memory.Peek(offset); @@ -131,16 +131,14 @@ namespace EightBit protected void LoadHexFile(string path) { - using (var file = new IntelHexFile(path)) + using var file = new IntelHexFile(path); + foreach (var chunk in file.Parse()) { - foreach (var chunk in file.Parse()) - { - var address = chunk.Item1; - var content = chunk.Item2; - var mapped = this.Mapping(address); - var offset = address - mapped.Begin; - mapped.Memory.Load(content, offset); - } + var address = chunk.Item1; + var content = chunk.Item2; + var mapped = this.Mapping(address); + var offset = address - mapped.Begin; + mapped.Memory.Load(content, offset); } } } diff --git a/EightBit/ClockedChip.cs b/EightBit/ClockedChip.cs index e7fa577..8da94a2 100644 --- a/EightBit/ClockedChip.cs +++ b/EightBit/ClockedChip.cs @@ -12,7 +12,7 @@ namespace EightBit { } - public event EventHandler Ticked; + public event EventHandler? Ticked; public int Cycles { get; protected set; } diff --git a/EightBit/Device.cs b/EightBit/Device.cs index 04c96dc..44eb97a 100644 --- a/EightBit/Device.cs +++ b/EightBit/Device.cs @@ -14,13 +14,13 @@ namespace EightBit { } - public event EventHandler RaisingPOWER; + public event EventHandler? RaisingPOWER; - public event EventHandler RaisedPOWER; + public event EventHandler? RaisedPOWER; - public event EventHandler LoweringPOWER; + public event EventHandler? LoweringPOWER; - public event EventHandler LoweredPOWER; + public event EventHandler? LoweredPOWER; public bool Powered => this.POWER.Raised(); diff --git a/EightBit/InputOutput.cs b/EightBit/InputOutput.cs index 89171e2..efe5e4c 100644 --- a/EightBit/InputOutput.cs +++ b/EightBit/InputOutput.cs @@ -15,13 +15,13 @@ namespace EightBit { } - public event EventHandler ReadingPort; + public event EventHandler? ReadingPort; - public event EventHandler ReadPort; + public event EventHandler? ReadPort; - public event EventHandler WritingPort; + public event EventHandler? WritingPort; - public event EventHandler WrittenPort; + public event EventHandler? WrittenPort; public byte Read(byte port) => this.ReadInputPort(port); diff --git a/EightBit/IntelHexFile.cs b/EightBit/IntelHexFile.cs index 9f6d9e2..ef444de 100644 --- a/EightBit/IntelHexFile.cs +++ b/EightBit/IntelHexFile.cs @@ -8,14 +8,12 @@ namespace EightBit using System.Collections.Generic; using System.IO; - public class IntelHexFile : IDisposable + public class IntelHexFile(string path) : IDisposable { - private readonly StreamReader reader; + private readonly StreamReader reader = File.OpenText(path); private bool eof; private bool disposed = false; - public IntelHexFile(string path) => this.reader = File.OpenText(path); - public void Dispose() { this.Dispose(true); @@ -27,7 +25,7 @@ namespace EightBit this.eof = false; while (!this.reader.EndOfStream && !this.eof) { - var line = this.reader.ReadLine(); + var line = this.reader.ReadLine() ?? throw new InvalidOperationException("Early EOF detected"); var parsed = this.Parse(line); if (parsed != null) { @@ -78,14 +76,14 @@ namespace EightBit return data; } - private Tuple Parse(string line) + private Tuple? Parse(string line) { if (string.IsNullOrEmpty(line)) { throw new ArgumentNullException(nameof(line)); } - var colon = line.Substring(0, 1); + var colon = line[..1]; if (colon != ":") { throw new ArgumentOutOfRangeException(nameof(line), "Invalid hex file: line does not begin with a colon"); diff --git a/EightBit/IntelProcessor.cs b/EightBit/IntelProcessor.cs index 588754e..f5455ca 100644 --- a/EightBit/IntelProcessor.cs +++ b/EightBit/IntelProcessor.cs @@ -8,8 +8,8 @@ namespace EightBit public abstract class IntelProcessor : LittleEndianProcessor { - private static readonly int[] HalfCarryTableAdd = new int[8] { 0, 0, 1, 0, 1, 0, 1, 1 }; - private static readonly int[] HalfCarryTableSub = new int[8] { 0, 1, 1, 1, 0, 0, 0, 1 }; + private static readonly int[] HalfCarryTableAdd = [0, 0, 1, 0, 1, 0, 1, 1]; + private static readonly int[] HalfCarryTableSub = [0, 1, 1, 1, 0, 0, 0, 1]; private readonly IntelOpCodeDecoded[] decodedOpCodes = new IntelOpCodeDecoded[0x100]; @@ -24,13 +24,13 @@ namespace EightBit } } - public event EventHandler RaisingHALT; + public event EventHandler? RaisingHALT; - public event EventHandler RaisedHALT; + public event EventHandler? RaisedHALT; - public event EventHandler LoweringHALT; + public event EventHandler? LoweringHALT; - public event EventHandler LoweredHALT; + public event EventHandler? LoweredHALT; public Register16 SP { get; } = new Register16((ushort)Mask.Sixteen); diff --git a/EightBit/LittleEndianProcessor.cs b/EightBit/LittleEndianProcessor.cs index 66ff1d8..efac777 100644 --- a/EightBit/LittleEndianProcessor.cs +++ b/EightBit/LittleEndianProcessor.cs @@ -4,14 +4,9 @@ namespace EightBit { - public abstract class LittleEndianProcessor : Processor + public abstract class LittleEndianProcessor(Bus memory) : Processor(memory) { - private readonly Register16 intermediate = new Register16(); - - protected LittleEndianProcessor(Bus memory) - : base(memory) - { - } + private readonly Register16 intermediate = new(); public override Register16 PeekWord(ushort address) { diff --git a/EightBit/MemoryMapping.cs b/EightBit/MemoryMapping.cs index 22b8bb9..e3291f1 100644 --- a/EightBit/MemoryMapping.cs +++ b/EightBit/MemoryMapping.cs @@ -4,27 +4,24 @@ namespace EightBit { - public class MemoryMapping + public class MemoryMapping(Memory memory, ushort begin, ushort mask, AccessLevel access) { - public MemoryMapping(Memory memory, ushort begin, ushort mask, AccessLevel access) - { - this.Memory = memory; - this.Begin = begin; - this.Mask = mask; - this.Access = access; - } - public MemoryMapping(Memory memory, ushort begin, Mask mask, AccessLevel access) : this(memory, begin, (ushort)mask, access) { } - public Memory Memory { get; set; } + public Memory Memory { get; set; } = memory; - public ushort Begin { get; set; } + public ushort Begin { get; set; } = begin; - public ushort Mask { get; set; } + public ushort Mask { get; set; } = mask; - public AccessLevel Access { get; set; } + public AccessLevel Access { get; set; } = access; + + public int Offset(ushort absolute) + { + return (absolute - this.Begin) & this.Mask; + } } } diff --git a/EightBit/PortEventArgs.cs b/EightBit/PortEventArgs.cs index 4c20425..a814c96 100644 --- a/EightBit/PortEventArgs.cs +++ b/EightBit/PortEventArgs.cs @@ -6,10 +6,8 @@ namespace EightBit { using System; - public sealed class PortEventArgs : EventArgs + public sealed class PortEventArgs(byte value) : EventArgs { - public PortEventArgs(byte value) => this.Port = value; - - public byte Port { get; } + public byte Port { get; } = value; } } diff --git a/EightBit/Processor.cs b/EightBit/Processor.cs index cbd105b..1fa2602 100644 --- a/EightBit/Processor.cs +++ b/EightBit/Processor.cs @@ -6,34 +6,32 @@ namespace EightBit { using System; - public abstract class Processor : ClockedChip + public abstract class Processor(Bus memory) : ClockedChip { private PinLevel resetLine; private PinLevel intLine; - protected Processor(Bus memory) => this.Bus = memory; + public event EventHandler? RaisingRESET; - public event EventHandler RaisingRESET; + public event EventHandler? RaisedRESET; - public event EventHandler RaisedRESET; + public event EventHandler? LoweringRESET; - public event EventHandler LoweringRESET; + public event EventHandler? LoweredRESET; - public event EventHandler LoweredRESET; + public event EventHandler? RaisingINT; - public event EventHandler RaisingINT; + public event EventHandler? RaisedINT; - public event EventHandler RaisedINT; + public event EventHandler? LoweringINT; - public event EventHandler LoweringINT; - - public event EventHandler LoweredINT; + public event EventHandler? LoweredINT; public ref PinLevel RESET => ref this.resetLine; public ref PinLevel INT => ref this.intLine; - public Bus Bus { get; } + public Bus Bus { get; } = memory; public Register16 PC { get; } = new Register16(); diff --git a/EightBit/Ram.cs b/EightBit/Ram.cs index 2dc36ce..f381051 100644 --- a/EightBit/Ram.cs +++ b/EightBit/Ram.cs @@ -4,13 +4,8 @@ namespace EightBit { - public class Ram : Rom + public class Ram(int size) : Rom(size) { - public Ram(int size) - : base(size) - { - } - public Ram() : this(0) { diff --git a/EightBit/Register16.cs b/EightBit/Register16.cs index f174970..16813b1 100644 --- a/EightBit/Register16.cs +++ b/EightBit/Register16.cs @@ -69,12 +69,26 @@ namespace EightBit public static bool operator !=(Register16 left, Register16 right) => !(left == right); - public override bool Equals(object obj) + public override int GetHashCode() => this.Word; + + public override bool Equals(object? obj) { - var rhs = obj as Register16; - return rhs == null ? false : rhs.Low == this.Low && rhs.High == this.High; + return Equals(obj as Register16); } - public override int GetHashCode() => this.Word; + public bool Equals(Register16? rhs) + { + if (ReferenceEquals(this, rhs)) + { + return true; + } + + if (rhs is null) + { + return false; + } + + return rhs.Low == this.Low && rhs.High == this.High; + } } } diff --git a/EightBit/Rom.cs b/EightBit/Rom.cs index df677dd..15e903d 100644 --- a/EightBit/Rom.cs +++ b/EightBit/Rom.cs @@ -7,11 +7,9 @@ namespace EightBit using System; using System.IO; - public class Rom : Memory + public class Rom(int size) : Memory { - private byte[] bytes; - - public Rom(int size) => this.bytes = new byte[size]; + private byte[] bytes = new byte[size]; public Rom() : this(0) @@ -53,10 +51,8 @@ namespace EightBit public static int Load(string path, ref byte[] output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1) { - using (var file = File.Open(path, FileMode.Open)) - { - return Load(file, ref output, writeOffset, readOffset, limit, maximumSize); - } + using var file = File.Open(path, FileMode.Open); + return Load(file, ref output, writeOffset, readOffset, limit, maximumSize); } public override int Load(FileStream file, int writeOffset = 0, int readOffset = 0, int limit = -1) diff --git a/EightBit/UnusedMemory.cs b/EightBit/UnusedMemory.cs index cdd97de..66f635b 100644 --- a/EightBit/UnusedMemory.cs +++ b/EightBit/UnusedMemory.cs @@ -6,16 +6,10 @@ namespace EightBit { using System.IO; - public class UnusedMemory : Memory + public class UnusedMemory(int size, byte unchanging) : Memory { - private readonly int size; - private readonly byte unchanging; - - public UnusedMemory(int size, byte unchanging) - { - this.size = size; - this.unchanging = unchanging; - } + private readonly int size = size; + private readonly byte unchanging = unchanging; public override int Size => this.size; diff --git a/Z80/Disassembler.cs b/Z80/Disassembler.cs index 54a8481..75a8a40 100644 --- a/Z80/Disassembler.cs +++ b/Z80/Disassembler.cs @@ -6,16 +6,14 @@ namespace EightBit { using System; - public class Disassembler + public class Disassembler(Bus bus) { private bool prefixCB = false; private bool prefixDD = false; private bool prefixED = false; private bool prefixFD = false; - public Disassembler(Bus bus) => this.Bus = bus; - - public Bus Bus { get; } + public Bus Bus { get; } = bus; public static string AsFlag(byte value, StatusBits flag, string represents) => (value & (byte)flag) != 0 ? represents : "-"; @@ -31,10 +29,7 @@ namespace EightBit public static string State(Z80 cpu) { - if (cpu == null) - { - throw new ArgumentNullException(nameof(cpu)); - } + ArgumentNullException.ThrowIfNull(cpu); var pc = cpu.PC; var sp = cpu.SP; @@ -75,11 +70,7 @@ namespace EightBit public string Disassemble(Z80 cpu) { - if (cpu == null) - { - throw new ArgumentNullException(nameof(cpu)); - } - + ArgumentNullException.ThrowIfNull(cpu); this.prefixCB = this.prefixDD = this.prefixED = this.prefixFD = false; return this.Disassemble(cpu, cpu.PC.Word); } diff --git a/Z80/RefreshRegister.cs b/Z80/RefreshRegister.cs index 107db2f..3015e82 100644 --- a/Z80/RefreshRegister.cs +++ b/Z80/RefreshRegister.cs @@ -4,16 +4,10 @@ namespace EightBit { - public struct RefreshRegister : System.IEquatable + public struct RefreshRegister(byte value) : System.IEquatable { - private readonly byte high; - private byte variable; - - public RefreshRegister(byte value) - { - this.high = (byte)(value & (byte)Bits.Bit7); - this.variable = (byte)(value & (byte)Mask.Seven); - } + private readonly byte high = (byte)(value & (byte)Bits.Bit7); + private byte variable = (byte)(value & (byte)Mask.Seven); public static implicit operator byte(RefreshRegister input) => ToByte(input); @@ -33,14 +27,22 @@ namespace EightBit return value; } - public static RefreshRegister FromByte(byte input) => new RefreshRegister(input); + public static RefreshRegister FromByte(byte input) => new(input); - public byte ToByte() => ToByte(this); + public readonly byte ToByte() => ToByte(this); - public override bool Equals(object obj) => obj is RefreshRegister ? this.Equals((RefreshRegister)obj) : false; + public override readonly bool Equals(object? obj) + { + if (obj is null) + { + return false; + } - public override int GetHashCode() => this.high + this.variable; + return this.Equals((RefreshRegister)obj); + } + public readonly bool Equals(RefreshRegister other) => other.high == this.high && other.variable == this.variable; + + public override readonly int GetHashCode() => this.high + this.variable; - public bool Equals(RefreshRegister other) => other.high == this.high && other.variable == this.variable; } } diff --git a/Z80/StatusBits.cs b/Z80/StatusBits.cs index 5f652e8..a24262d 100644 --- a/Z80/StatusBits.cs +++ b/Z80/StatusBits.cs @@ -24,12 +24,16 @@ namespace EightBit // Undocumented X flag XF = Bits.Bit3, +#pragma warning disable CA1069 // Enums values should not be duplicated + // Parity PF = Bits.Bit2, // Overflow VF = Bits.Bit2, +#pragma warning restore CA1069 // Enums values should not be duplicated + // Negative? NF = Bits.Bit1, diff --git a/Z80/Z80.cs b/Z80/Z80.cs index 4ed7fda..7cc7366 100644 --- a/Z80/Z80.cs +++ b/Z80/Z80.cs @@ -6,11 +6,11 @@ namespace EightBit { using System; - public class Z80 : IntelProcessor + public class Z80(Bus bus, InputOutput ports) : IntelProcessor(bus) { - private readonly InputOutput ports; + private readonly InputOutput ports = ports; - private readonly Register16[] accumulatorFlags = { new Register16(), new Register16() }; + private readonly Register16[] accumulatorFlags = [new Register16(), new Register16()]; private readonly Register16[,] registers = { { @@ -21,9 +21,9 @@ namespace EightBit }, }; - private readonly Register16 intermediate = new Register16(); + private readonly Register16 intermediate = new(); - private RefreshRegister refresh = new RefreshRegister(0x7f); + private RefreshRegister refresh = new(0x7f); private bool prefixCB = false; private bool prefixDD = false; @@ -44,68 +44,65 @@ namespace EightBit private sbyte displacement = 0; private bool displaced = false; - public Z80(Bus bus, InputOutput ports) - : base(bus) => this.ports = ports; + public event EventHandler? ExecutingInstruction; - public event EventHandler ExecutingInstruction; + public event EventHandler? ExecutedInstruction; - public event EventHandler ExecutedInstruction; + public event EventHandler? RaisingNMI; - public event EventHandler RaisingNMI; + public event EventHandler? RaisedNMI; - public event EventHandler RaisedNMI; + public event EventHandler? LoweringNMI; - public event EventHandler LoweringNMI; + public event EventHandler? LoweredNMI; - public event EventHandler LoweredNMI; + public event EventHandler? RaisingM1; - public event EventHandler RaisingM1; + public event EventHandler? RaisedM1; - public event EventHandler RaisedM1; + public event EventHandler? LoweringM1; - public event EventHandler LoweringM1; + public event EventHandler? LoweredM1; - public event EventHandler LoweredM1; + public event EventHandler? RaisingRFSH; - public event EventHandler RaisingRFSH; + public event EventHandler? RaisedRFSH; - public event EventHandler RaisedRFSH; + public event EventHandler? LoweringRFSH; - public event EventHandler LoweringRFSH; + public event EventHandler? LoweredRFSH; - public event EventHandler LoweredRFSH; + public event EventHandler? RaisingMREQ; - public event EventHandler RaisingMREQ; + public event EventHandler? RaisedMREQ; - public event EventHandler RaisedMREQ; + public event EventHandler? LoweringMREQ; - public event EventHandler LoweringMREQ; + public event EventHandler? LoweredMREQ; - public event EventHandler LoweredMREQ; + public event EventHandler? RaisingIORQ; - public event EventHandler RaisingIORQ; + public event EventHandler? RaisedIORQ; - public event EventHandler RaisedIORQ; + public event EventHandler? LoweringIORQ; - public event EventHandler LoweringIORQ; + public event EventHandler? LoweredIORQ; - public event EventHandler LoweredIORQ; + public event EventHandler? RaisingRD; - public event EventHandler RaisingRD; + public event EventHandler? RaisedRD; - public event EventHandler RaisedRD; + public event EventHandler? LoweringRD; - public event EventHandler LoweringRD; + public event EventHandler? LoweredRD; - public event EventHandler LoweredRD; + public event EventHandler? RaisingWR; - public event EventHandler RaisingWR; + public event EventHandler? RaisedWR; - public event EventHandler RaisedWR; + public event EventHandler? LoweringWR; - public event EventHandler LoweringWR; - - public event EventHandler LoweredWR; + public event EventHandler? LoweredWR; public byte IV { get; set; } = 0xff; @@ -390,7 +387,7 @@ namespace EightBit // received from the memory is ignored and an NOP instruction is forced internally to the // CPU.The HALT acknowledge signal is active during this time indicating that the processor // is in the HALT state. - var discarded = this.ReadInitialOpCode(); + _ = this.ReadInitialOpCode(); this.Execute(0); // NOP handled = true; } @@ -864,26 +861,13 @@ namespace EightBit break; case 6: // Set interrupt mode - switch (y) + this.IM = y switch { - case 0: - case 1: - case 4: - case 5: - this.IM = 0; - break; - case 2: - case 6: - this.IM = 1; - break; - case 3: - case 7: - this.IM = 2; - break; - default: - throw new NotSupportedException("Invalid operation mode"); - } - + 0 or 1 or 4 or 5 => 0, + 2 or 6 => 1, + 3 or 7 => 2, + _ => throw new NotSupportedException("Invalid operation mode"), + }; break; case 7: // Assorted ops switch (y) @@ -1566,7 +1550,7 @@ namespace EightBit this.IFF2 = this.IFF1; this.IFF1 = false; this.LowerM1(); - var discarded = this.Bus.Data; + _ = this.Bus.Data; this.RaiseM1(); this.Restart(0x66); }