IDE suggestions

This commit is contained in:
Adrian Conlon 2024-05-19 09:07:20 +01:00
parent 6cbffa1051
commit e0235f396e
19 changed files with 151 additions and 192 deletions

View File

@ -3,14 +3,9 @@
// </copyright>
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)
{

View File

@ -10,13 +10,13 @@ namespace EightBit
{
private byte data;
public event EventHandler<EventArgs> WritingByte;
public event EventHandler<EventArgs>? WritingByte;
public event EventHandler<EventArgs> WrittenByte;
public event EventHandler<EventArgs>? WrittenByte;
public event EventHandler<EventArgs> ReadingByte;
public event EventHandler<EventArgs>? ReadingByte;
public event EventHandler<EventArgs> ReadByte;
public event EventHandler<EventArgs>? 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);
}
}
}

View File

@ -12,7 +12,7 @@ namespace EightBit
{
}
public event EventHandler<EventArgs> Ticked;
public event EventHandler<EventArgs>? Ticked;
public int Cycles { get; protected set; }

View File

@ -14,13 +14,13 @@ namespace EightBit
{
}
public event EventHandler<EventArgs> RaisingPOWER;
public event EventHandler<EventArgs>? RaisingPOWER;
public event EventHandler<EventArgs> RaisedPOWER;
public event EventHandler<EventArgs>? RaisedPOWER;
public event EventHandler<EventArgs> LoweringPOWER;
public event EventHandler<EventArgs>? LoweringPOWER;
public event EventHandler<EventArgs> LoweredPOWER;
public event EventHandler<EventArgs>? LoweredPOWER;
public bool Powered => this.POWER.Raised();

View File

@ -15,13 +15,13 @@ namespace EightBit
{
}
public event EventHandler<PortEventArgs> ReadingPort;
public event EventHandler<PortEventArgs>? ReadingPort;
public event EventHandler<PortEventArgs> ReadPort;
public event EventHandler<PortEventArgs>? ReadPort;
public event EventHandler<PortEventArgs> WritingPort;
public event EventHandler<PortEventArgs>? WritingPort;
public event EventHandler<PortEventArgs> WrittenPort;
public event EventHandler<PortEventArgs>? WrittenPort;
public byte Read(byte port) => this.ReadInputPort(port);

View File

@ -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<ushort, byte[]> Parse(string line)
private Tuple<ushort, byte[]>? 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");

View File

@ -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<EventArgs> RaisingHALT;
public event EventHandler<EventArgs>? RaisingHALT;
public event EventHandler<EventArgs> RaisedHALT;
public event EventHandler<EventArgs>? RaisedHALT;
public event EventHandler<EventArgs> LoweringHALT;
public event EventHandler<EventArgs>? LoweringHALT;
public event EventHandler<EventArgs> LoweredHALT;
public event EventHandler<EventArgs>? LoweredHALT;
public Register16 SP { get; } = new Register16((ushort)Mask.Sixteen);

View File

@ -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)
{

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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<EventArgs>? RaisingRESET;
public event EventHandler<EventArgs> RaisingRESET;
public event EventHandler<EventArgs>? RaisedRESET;
public event EventHandler<EventArgs> RaisedRESET;
public event EventHandler<EventArgs>? LoweringRESET;
public event EventHandler<EventArgs> LoweringRESET;
public event EventHandler<EventArgs>? LoweredRESET;
public event EventHandler<EventArgs> LoweredRESET;
public event EventHandler<EventArgs>? RaisingINT;
public event EventHandler<EventArgs> RaisingINT;
public event EventHandler<EventArgs>? RaisedINT;
public event EventHandler<EventArgs> RaisedINT;
public event EventHandler<EventArgs>? LoweringINT;
public event EventHandler<EventArgs> LoweringINT;
public event EventHandler<EventArgs> LoweredINT;
public event EventHandler<EventArgs>? 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();

View File

@ -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)
{

View File

@ -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;
}
}
}

View File

@ -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)

View File

@ -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;

View File

@ -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);
}

View File

@ -4,16 +4,10 @@
namespace EightBit
{
public struct RefreshRegister : System.IEquatable<RefreshRegister>
public struct RefreshRegister(byte value) : System.IEquatable<RefreshRegister>
{
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;
}
}

View File

@ -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,

View File

@ -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<EventArgs>? ExecutingInstruction;
public event EventHandler<EventArgs> ExecutingInstruction;
public event EventHandler<EventArgs>? ExecutedInstruction;
public event EventHandler<EventArgs> ExecutedInstruction;
public event EventHandler<EventArgs>? RaisingNMI;
public event EventHandler<EventArgs> RaisingNMI;
public event EventHandler<EventArgs>? RaisedNMI;
public event EventHandler<EventArgs> RaisedNMI;
public event EventHandler<EventArgs>? LoweringNMI;
public event EventHandler<EventArgs> LoweringNMI;
public event EventHandler<EventArgs>? LoweredNMI;
public event EventHandler<EventArgs> LoweredNMI;
public event EventHandler<EventArgs>? RaisingM1;
public event EventHandler<EventArgs> RaisingM1;
public event EventHandler<EventArgs>? RaisedM1;
public event EventHandler<EventArgs> RaisedM1;
public event EventHandler<EventArgs>? LoweringM1;
public event EventHandler<EventArgs> LoweringM1;
public event EventHandler<EventArgs>? LoweredM1;
public event EventHandler<EventArgs> LoweredM1;
public event EventHandler<EventArgs>? RaisingRFSH;
public event EventHandler<EventArgs> RaisingRFSH;
public event EventHandler<EventArgs>? RaisedRFSH;
public event EventHandler<EventArgs> RaisedRFSH;
public event EventHandler<EventArgs>? LoweringRFSH;
public event EventHandler<EventArgs> LoweringRFSH;
public event EventHandler<EventArgs>? LoweredRFSH;
public event EventHandler<EventArgs> LoweredRFSH;
public event EventHandler<EventArgs>? RaisingMREQ;
public event EventHandler<EventArgs> RaisingMREQ;
public event EventHandler<EventArgs>? RaisedMREQ;
public event EventHandler<EventArgs> RaisedMREQ;
public event EventHandler<EventArgs>? LoweringMREQ;
public event EventHandler<EventArgs> LoweringMREQ;
public event EventHandler<EventArgs>? LoweredMREQ;
public event EventHandler<EventArgs> LoweredMREQ;
public event EventHandler<EventArgs>? RaisingIORQ;
public event EventHandler<EventArgs> RaisingIORQ;
public event EventHandler<EventArgs>? RaisedIORQ;
public event EventHandler<EventArgs> RaisedIORQ;
public event EventHandler<EventArgs>? LoweringIORQ;
public event EventHandler<EventArgs> LoweringIORQ;
public event EventHandler<EventArgs>? LoweredIORQ;
public event EventHandler<EventArgs> LoweredIORQ;
public event EventHandler<EventArgs>? RaisingRD;
public event EventHandler<EventArgs> RaisingRD;
public event EventHandler<EventArgs>? RaisedRD;
public event EventHandler<EventArgs> RaisedRD;
public event EventHandler<EventArgs>? LoweringRD;
public event EventHandler<EventArgs> LoweringRD;
public event EventHandler<EventArgs>? LoweredRD;
public event EventHandler<EventArgs> LoweredRD;
public event EventHandler<EventArgs>? RaisingWR;
public event EventHandler<EventArgs> RaisingWR;
public event EventHandler<EventArgs>? RaisedWR;
public event EventHandler<EventArgs> RaisedWR;
public event EventHandler<EventArgs>? LoweringWR;
public event EventHandler<EventArgs> LoweringWR;
public event EventHandler<EventArgs> LoweredWR;
public event EventHandler<EventArgs>? 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);
}