Apply all analysis suggestions

This commit is contained in:
Adrian Conlon
2024-10-12 09:14:29 +01:00
parent 3d9b0aac56
commit 9aa25fed7e
17 changed files with 304 additions and 323 deletions

View File

@@ -7,69 +7,69 @@ namespace EightBit
{ {
public override Register16 PeekWord(ushort address) public override Register16 PeekWord(ushort address)
{ {
Intermediate.High = Bus.Peek(address); this.Intermediate.High = this.Bus.Peek(address);
Intermediate.Low = Bus.Peek(++address); this.Intermediate.Low = this.Bus.Peek(++address);
return Intermediate; return this.Intermediate;
} }
public override void PokeWord(ushort address, Register16 value) public override void PokeWord(ushort address, Register16 value)
{ {
ArgumentNullException.ThrowIfNull(value); ArgumentNullException.ThrowIfNull(value);
Bus.Poke(address, value.High); this.Bus.Poke(address, value.High);
Bus.Poke(++address, value.Low); this.Bus.Poke(++address, value.Low);
} }
protected override Register16 FetchWord() protected override Register16 FetchWord()
{ {
Intermediate.High = FetchByte(); this.Intermediate.High = this.FetchByte();
Intermediate.Low = FetchByte(); this.Intermediate.Low = this.FetchByte();
return Intermediate; return this.Intermediate;
} }
protected override Register16 GetWord() protected override Register16 GetWord()
{ {
Intermediate.High = MemoryRead(); this.Intermediate.High = this.MemoryRead();
++Bus.Address.Word; ++this.Bus.Address.Word;
Intermediate.Low = MemoryRead(); this.Intermediate.Low = this.MemoryRead();
return Intermediate; return this.Intermediate;
} }
protected override Register16 GetWordPaged() protected override Register16 GetWordPaged()
{ {
Intermediate.High = MemoryRead(); this.Intermediate.High = this.MemoryRead();
++Bus.Address.Low; ++this.Bus.Address.Low;
Intermediate.Low = MemoryRead(); this.Intermediate.Low = this.MemoryRead();
return Intermediate; return this.Intermediate;
} }
protected override Register16 PopWord() protected override Register16 PopWord()
{ {
Intermediate.High = Pop(); this.Intermediate.High = this.Pop();
Intermediate.Low = Pop(); this.Intermediate.Low = this.Pop();
return Intermediate; return this.Intermediate;
} }
protected override void PushWord(Register16 value) protected override void PushWord(Register16 value)
{ {
ArgumentNullException.ThrowIfNull(value); ArgumentNullException.ThrowIfNull(value);
Push(value.Low); this.Push(value.Low);
Push(value.High); this.Push(value.High);
} }
protected override void SetWord(Register16 value) protected override void SetWord(Register16 value)
{ {
ArgumentNullException.ThrowIfNull(value); ArgumentNullException.ThrowIfNull(value);
MemoryWrite(value.High); this.MemoryWrite(value.High);
++Bus.Address.Word; ++this.Bus.Address.Word;
MemoryWrite(value.Low); this.MemoryWrite(value.Low);
} }
protected override void SetWordPaged(Register16 value) protected override void SetWordPaged(Register16 value)
{ {
ArgumentNullException.ThrowIfNull(value); ArgumentNullException.ThrowIfNull(value);
MemoryWrite(value.High); this.MemoryWrite(value.High);
++Bus.Address.Low; ++this.Bus.Address.Low;
MemoryWrite(value.Low); this.MemoryWrite(value.Low);
} }
} }
} }

View File

@@ -18,89 +18,90 @@ namespace EightBit
public event EventHandler<EventArgs>? ReadByte; public event EventHandler<EventArgs>? ReadByte;
public ref byte Data => ref _data; public ref byte Data => ref this._data;
public Register16 Address { get; } = new(); public Register16 Address { get; } = new();
public abstract MemoryMapping Mapping(ushort absolute); public abstract MemoryMapping Mapping(ushort absolute);
public byte Peek() => Reference(); public byte Peek() => this.Reference();
public byte Peek(ushort absolute) => Reference(absolute); public byte Peek(ushort absolute) => this.Reference(absolute);
public byte Peek(Register16 absolute) public byte Peek(Register16 absolute)
{ {
ArgumentNullException.ThrowIfNull(absolute); ArgumentNullException.ThrowIfNull(absolute);
return Peek(absolute.Word); return this.Peek(absolute.Word);
} }
public void Poke(byte value) => Reference() = value; public void Poke(byte value) => this.Reference() = value;
public void Poke(ushort absolute, byte value) => Reference(absolute) = value; public void Poke(ushort absolute, byte value) => this.Reference(absolute) = value;
public void Poke(Register16 absolute, byte value) public void Poke(Register16 absolute, byte value)
{ {
ArgumentNullException.ThrowIfNull(absolute); ArgumentNullException.ThrowIfNull(absolute);
Poke(absolute.Word, value); this.Poke(absolute.Word, value);
} }
public byte Read() public byte Read()
{ {
OnReadingByte(); this.OnReadingByte();
var returned = Data = Reference(); var returned = this.Data = this.Reference();
OnReadByte(); this.OnReadByte();
return returned; return returned;
} }
public byte Read(ushort absolute) public byte Read(ushort absolute)
{ {
Address.Word = absolute; this.Address.Word = absolute;
return Read(); return this.Read();
} }
public byte Read(Register16 absolute) public byte Read(Register16 absolute)
{ {
ArgumentNullException.ThrowIfNull(absolute); ArgumentNullException.ThrowIfNull(absolute);
return Read(absolute.Low, absolute.High); return this.Read(absolute.Low, absolute.High);
} }
public byte Read(byte low, byte high) public byte Read(byte low, byte high)
{ {
Address.Assign(low, high); this.Address.Assign(low, high);
return Read(); return this.Read();
} }
public void Write() public void Write()
{ {
OnWritingByte(); this.OnWritingByte();
Reference() = Data; this.Reference() = this.Data;
OnWrittenByte(); this.OnWrittenByte();
} }
public void Write(byte value) public void Write(byte value)
{ {
Data = value; this.Data = value;
Write(); this.Write();
} }
public void Write(ushort absolute, byte value) public void Write(ushort absolute, byte value)
{ {
Address.Word = absolute; this.Address.Word = absolute;
Write(value); this.Write(value);
} }
public void Write(Register16 absolute, byte value) public void Write(Register16 absolute, byte value)
{ {
ArgumentNullException.ThrowIfNull(absolute); ArgumentNullException.ThrowIfNull(absolute);
Write(absolute.Low, absolute.High, value); this.Write(absolute.Low, absolute.High, value);
} }
public void Write(byte low, byte high, byte value) public void Write(byte low, byte high, byte value)
{ {
Address.Assign(low, high); this.Address.Assign(low, high);
Write(value); this.Write(value);
} }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
public virtual void RaisePOWER() public virtual void RaisePOWER()
{ {
} }
@@ -121,12 +122,12 @@ namespace EightBit
protected ref byte Reference(ushort absolute) protected ref byte Reference(ushort absolute)
{ {
var mapped = Mapping(absolute); var mapped = this.Mapping(absolute);
var offset = (ushort)mapped.Offset(absolute); var offset = (ushort)mapped.Offset(absolute);
if (mapped.Access == AccessLevel.ReadOnly) if (mapped.Access == AccessLevel.ReadOnly)
{ {
Data = mapped.Memory.Peek(offset); this.Data = mapped.Memory.Peek(offset);
return ref _data; return ref this._data;
} }
return ref mapped.Memory.Reference(offset); return ref mapped.Memory.Reference(offset);
@@ -135,19 +136,19 @@ namespace EightBit
protected ref byte Reference(Register16 absolute) protected ref byte Reference(Register16 absolute)
{ {
ArgumentNullException.ThrowIfNull(absolute); ArgumentNullException.ThrowIfNull(absolute);
return ref Reference(absolute.Word); return ref this.Reference(absolute.Word);
} }
protected ref byte Reference() => ref Reference(Address); protected ref byte Reference() => ref this.Reference(this.Address);
protected void LoadHexFile(string path) protected void LoadHexFile(string path)
{ {
var file = new IntelHexFile(path); var file = new IntelHexFile(path);
foreach (var (address, content) in file.Parse()) foreach (var (address, content) in file.Parse())
{ {
var mapped = Mapping(address); var mapped = this.Mapping(address);
var offset = address - mapped.Begin; var offset = address - mapped.Begin;
mapped.Memory.Load(content, offset); _ = mapped.Memory.Load(content, offset);
} }
} }
} }

View File

@@ -52,24 +52,10 @@ namespace EightBit
public static int DemoteNibble(byte value) => HighNibble(value); public static int DemoteNibble(byte value) => HighNibble(value);
public static int CountBits(uint value) public static int CountBits(uint value) => System.Numerics.BitOperations.PopCount(value);
{
return System.Numerics.BitOperations.PopCount(value);
}
public static bool EvenParity(uint value) public static bool EvenParity(uint value) => CountBits(value) % 2 == 0;
{
return CountBits(value) % 2 == 0;
}
public static int FindFirstSet(uint value) public static int FindFirstSet(uint value) => value == 0 ? 0 : System.Numerics.BitOperations.TrailingZeroCount(value) + 1;
{
if (value == 0)
{
return 0;
}
return System.Numerics.BitOperations.TrailingZeroCount(value) + 1;
}
} }
} }

View File

@@ -20,18 +20,18 @@ namespace EightBit
{ {
for (var i = 0; i < extra; ++i) for (var i = 0; i < extra; ++i)
{ {
Tick(); this.Tick();
} }
} }
public void Tick() public void Tick()
{ {
++Cycles; ++this.Cycles;
OnTicked(); this.OnTicked();
} }
protected virtual void OnTicked() => Ticked?.Invoke(this, EventArgs.Empty); protected virtual void OnTicked() => Ticked?.Invoke(this, EventArgs.Empty);
protected void ResetCycles() => Cycles = 0; protected void ResetCycles() => this.Cycles = 0;
} }
} }

View File

@@ -18,27 +18,28 @@ namespace EightBit
public event EventHandler<EventArgs>? LoweredPOWER; public event EventHandler<EventArgs>? LoweredPOWER;
public bool Powered => POWER.Raised(); public bool Powered => this.POWER.Raised();
public ref PinLevel POWER => ref _powerLine; public ref PinLevel POWER => ref this._powerLine;
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
public virtual void RaisePOWER() public virtual void RaisePOWER()
{ {
if (POWER.Lowered()) if (this.POWER.Lowered())
{ {
OnRaisingPOWER(); this.OnRaisingPOWER();
POWER.Raise(); this.POWER.Raise();
OnRaisedPOWER(); this.OnRaisedPOWER();
} }
} }
public virtual void LowerPOWER() public virtual void LowerPOWER()
{ {
if (POWER.Raised()) if (this.POWER.Raised())
{ {
OnLoweringPOWER(); this.OnLoweringPOWER();
POWER.Lower(); this.POWER.Lower();
OnLoweredPOWER(); this.OnLoweredPOWER();
} }
} }

View File

@@ -19,27 +19,27 @@ namespace EightBit
public event EventHandler<PortEventArgs>? WrittenPort; public event EventHandler<PortEventArgs>? WrittenPort;
public byte Read(byte port) => ReadInputPort(port); public byte Read(byte port) => this.ReadInputPort(port);
public void Write(byte port, byte value) => WriteOutputPort(port, value); public void Write(byte port, byte value) => this.WriteOutputPort(port, value);
public byte ReadInputPort(byte port) public byte ReadInputPort(byte port)
{ {
OnReadingPort(port); this.OnReadingPort(port);
var value = _input[port]; var value = this._input[port];
OnReadPort(port); this.OnReadPort(port);
return value; return value;
} }
public void WriteInputPort(byte port, byte value) => _input[port] = value; public void WriteInputPort(byte port, byte value) => this._input[port] = value;
public byte ReadOutputPort(byte port) => _output[port]; public byte ReadOutputPort(byte port) => this._output[port];
public void WriteOutputPort(byte port, byte value) public void WriteOutputPort(byte port, byte value)
{ {
OnWritingPort(port); this.OnWritingPort(port);
_output[port] = value; this._output[port] = value;
OnWrittenPort(port); this.OnWrittenPort(port);
} }
private void OnReadingPort(byte port) => ReadingPort?.Invoke(this, new PortEventArgs(port)); private void OnReadingPort(byte port) => ReadingPort?.Invoke(this, new PortEventArgs(port));

View File

@@ -11,19 +11,19 @@ namespace EightBit
public IEnumerable<Tuple<ushort, byte[]>> Parse() public IEnumerable<Tuple<ushort, byte[]>> Parse()
{ {
_eof = false; this._eof = false;
using var reader = File.OpenText(_path); using var reader = File.OpenText(this._path);
while (!reader.EndOfStream && !_eof) while (!reader.EndOfStream && !this._eof)
{ {
var line = reader.ReadLine() ?? throw new InvalidOperationException("Early EOF detected"); var line = reader.ReadLine() ?? throw new InvalidOperationException("Early EOF detected");
var parsed = Parse(line); var parsed = this.Parse(line);
if (parsed != null) if (parsed is not null)
{ {
yield return parsed; yield return parsed;
} }
} }
if (!_eof) if (!this._eof)
{ {
throw new InvalidOperationException("File is missing an EOF record"); throw new InvalidOperationException("File is missing an EOF record");
} }
@@ -73,7 +73,7 @@ namespace EightBit
return new Tuple<ushort, byte[]>(address, ParseDataRecord(line, count)); return new Tuple<ushort, byte[]>(address, ParseDataRecord(line, count));
case 0x01: case 0x01:
_eof = true; this._eof = true;
return null; return null;
default: default:

View File

@@ -8,11 +8,11 @@ namespace EightBit
{ {
public IntelOpCodeDecoded(byte opCode) public IntelOpCodeDecoded(byte opCode)
{ {
X = (opCode & 0b11000000) >> 6; // 0 - 3 this.X = (opCode & 0b11000000) >> 6; // 0 - 3
Y = (opCode & 0b00111000) >> 3; // 0 - 7 this.Y = (opCode & 0b00111000) >> 3; // 0 - 7
Z = opCode & 0b00000111; // 0 - 7 this.Z = opCode & 0b00000111; // 0 - 7
P = (Y & 0b110) >> 1; // 0 - 3 this.P = (this.Y & 0b110) >> 1; // 0 - 3
Q = Y & 1; // 0 - 1 this.Q = this.Y & 0b1; // 0 - 1
} }
public int X { get; } public int X { get; }

View File

@@ -20,7 +20,7 @@ namespace EightBit
{ {
for (var i = 0; i < 0x100; ++i) for (var i = 0; i < 0x100; ++i)
{ {
_decodedOpCodes[i] = new((byte)i); this._decodedOpCodes[i] = new((byte)i);
} }
} }
@@ -38,49 +38,50 @@ namespace EightBit
public abstract Register16 AF { get; } public abstract Register16 AF { get; }
public ref byte A => ref AF.High; public ref byte A => ref this.AF.High;
public ref byte F => ref AF.Low; public ref byte F => ref this.AF.Low;
public abstract Register16 BC { get; } public abstract Register16 BC { get; }
public ref byte B => ref BC.High; public ref byte B => ref this.BC.High;
public ref byte C => ref BC.Low; public ref byte C => ref this.BC.Low;
public abstract Register16 DE { get; } public abstract Register16 DE { get; }
public ref byte D => ref DE.High; public ref byte D => ref this.DE.High;
public ref byte E => ref DE.Low; public ref byte E => ref this.DE.Low;
public abstract Register16 HL { get; } public abstract Register16 HL { get; }
public ref byte H => ref HL.High; public ref byte H => ref this.HL.High;
public ref byte L => ref HL.Low; public ref byte L => ref this.HL.Low;
public ref PinLevel HALT => ref _haltLine; public ref PinLevel HALT => ref this._haltLine;
public IntelOpCodeDecoded GetDecodedOpCode(byte opCode) => _decodedOpCodes[opCode]; public IntelOpCodeDecoded GetDecodedOpCode(byte opCode) => this._decodedOpCodes[opCode];
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
public virtual void RaiseHALT() public virtual void RaiseHALT()
{ {
if (HALT.Lowered()) if (this.HALT.Lowered())
{ {
OnRaisingHALT(); this.OnRaisingHALT();
HALT.Raise(); this.HALT.Raise();
OnRaisedHALT(); this.OnRaisedHALT();
} }
} }
public virtual void LowerHALT() public virtual void LowerHALT()
{ {
if (HALT.Raised()) if (this.HALT.Raised())
{ {
OnLoweringHALT(); this.OnLoweringHALT();
HALT.Lower(); this.HALT.Lower();
OnLoweredHALT(); this.OnLoweredHALT();
} }
} }
@@ -100,8 +101,8 @@ namespace EightBit
protected override void OnRaisedPOWER() protected override void OnRaisedPOWER()
{ {
PC.Word = SP.Word = AF.Word = BC.Word = DE.Word = HL.Word = (ushort)Mask.Sixteen; this.PC.Word = this.SP.Word = this.AF.Word = this.BC.Word = this.DE.Word = this.HL.Word = (ushort)Mask.Sixteen;
RaiseHALT(); this.RaiseHALT();
base.OnRaisedPOWER(); base.OnRaisedPOWER();
} }
@@ -109,7 +110,7 @@ namespace EightBit
protected virtual void OnRaisedHALT() protected virtual void OnRaisedHALT()
{ {
++PC.Word; // Release the PC from HALT instruction ++this.PC.Word; // Release the PC from HALT instruction
RaisedHALT?.Invoke(this, EventArgs.Empty); RaisedHALT?.Invoke(this, EventArgs.Empty);
} }
@@ -117,56 +118,56 @@ namespace EightBit
protected virtual void OnLoweredHALT() protected virtual void OnLoweredHALT()
{ {
--PC.Word; // Keep the PC on the HALT instruction (i.e. executing NOP) --this.PC.Word; // Keep the PC on the HALT instruction (i.e. executing NOP)
LoweredHALT?.Invoke(this, EventArgs.Empty); LoweredHALT?.Invoke(this, EventArgs.Empty);
} }
protected override void HandleRESET() protected override void HandleRESET()
{ {
base.HandleRESET(); base.HandleRESET();
Jump(0); this.Jump(0);
} }
protected sealed override void Push(byte value) protected sealed override void Push(byte value)
{ {
--SP.Word; --this.SP.Word;
MemoryWrite(SP, value); this.MemoryWrite(this.SP, value);
} }
protected sealed override byte Pop() protected sealed override byte Pop()
{ {
var returned = MemoryRead(SP); var returned = this.MemoryRead(this.SP);
SP.Word++; this.SP.Word++;
return returned; return returned;
} }
protected sealed override Register16 GetWord() protected sealed override Register16 GetWord()
{ {
var returned = base.GetWord(); var returned = base.GetWord();
MEMPTR.Assign(Bus.Address); this.MEMPTR.Assign(this.Bus.Address);
return returned; return returned;
} }
protected sealed override void SetWord(Register16 value) protected sealed override void SetWord(Register16 value)
{ {
base.SetWord(value); base.SetWord(value);
MEMPTR.Assign(Bus.Address); this.MEMPTR.Assign(this.Bus.Address);
} }
//// ////
protected void Restart(byte address) protected void Restart(byte address)
{ {
MEMPTR.Assign(address, 0); this.MEMPTR.Assign(address, 0);
Call(MEMPTR); this.Call(this.MEMPTR);
} }
protected bool CallConditional(bool condition) protected bool CallConditional(bool condition)
{ {
FetchWordMEMPTR(); this.FetchWordMEMPTR();
if (condition) if (condition)
{ {
Call(MEMPTR); this.Call(this.MEMPTR);
} }
return condition; return condition;
@@ -174,10 +175,10 @@ namespace EightBit
protected bool JumpConditional(bool condition) protected bool JumpConditional(bool condition)
{ {
FetchWordMEMPTR(); this.FetchWordMEMPTR();
if (condition) if (condition)
{ {
Jump(MEMPTR); this.Jump(this.MEMPTR);
} }
return condition; return condition;
@@ -187,7 +188,7 @@ namespace EightBit
{ {
if (condition) if (condition)
{ {
Return(); this.Return();
} }
return condition; return condition;
@@ -195,45 +196,45 @@ namespace EightBit
protected void FetchWordMEMPTR() protected void FetchWordMEMPTR()
{ {
FetchWord(); _ = this.FetchWord();
MEMPTR.Assign(Intermediate); this.MEMPTR.Assign(this.Intermediate);
} }
protected void JumpIndirect() protected void JumpIndirect()
{ {
FetchWordMEMPTR(); this.FetchWordMEMPTR();
Jump(MEMPTR); this.Jump(this.MEMPTR);
} }
protected void CallIndirect() protected void CallIndirect()
{ {
FetchWordMEMPTR(); this.FetchWordMEMPTR();
Call(MEMPTR); this.Call(this.MEMPTR);
} }
protected void JumpRelative(sbyte offset) protected void JumpRelative(sbyte offset)
{ {
MEMPTR.Word = (ushort)(PC.Word + offset); this.MEMPTR.Word = (ushort)(this.PC.Word + offset);
Jump(MEMPTR); this.Jump(this.MEMPTR);
} }
protected bool JumpRelativeConditional(bool condition) protected bool JumpRelativeConditional(bool condition)
{ {
Intermediate.Assign(PC); this.Intermediate.Assign(this.PC);
++PC.Word; ++this.PC.Word;
if (condition) if (condition)
{ {
var offset = (sbyte)MemoryRead(Intermediate); var offset = (sbyte)this.MemoryRead(this.Intermediate);
JumpRelative(offset); this.JumpRelative(offset);
} }
return condition; return condition;
} }
protected override sealed void Return() protected sealed override void Return()
{ {
base.Return(); base.Return();
MEMPTR.Assign(PC); this.MEMPTR.Assign(this.PC);
} }
} }
} }

View File

@@ -8,69 +8,69 @@ namespace EightBit
{ {
public override Register16 PeekWord(ushort address) public override Register16 PeekWord(ushort address)
{ {
Intermediate.Low = Bus.Peek(address); this.Intermediate.Low = this.Bus.Peek(address);
Intermediate.High = Bus.Peek(++address); this.Intermediate.High = this.Bus.Peek(++address);
return Intermediate; return this.Intermediate;
} }
public override void PokeWord(ushort address, Register16 value) public override void PokeWord(ushort address, Register16 value)
{ {
ArgumentNullException.ThrowIfNull(value); ArgumentNullException.ThrowIfNull(value);
Bus.Poke(address, value.Low); this.Bus.Poke(address, value.Low);
Bus.Poke(++address, value.High); this.Bus.Poke(++address, value.High);
} }
protected override Register16 FetchWord() protected override Register16 FetchWord()
{ {
Intermediate.Low = FetchByte(); this.Intermediate.Low = this.FetchByte();
Intermediate.High = FetchByte(); this.Intermediate.High = this.FetchByte();
return Intermediate; return this.Intermediate;
} }
protected override Register16 GetWord() protected override Register16 GetWord()
{ {
Intermediate.Low = MemoryRead(); this.Intermediate.Low = this.MemoryRead();
++Bus.Address.Word; ++this.Bus.Address.Word;
Intermediate.High = MemoryRead(); this.Intermediate.High = this.MemoryRead();
return Intermediate; return this.Intermediate;
} }
protected override Register16 GetWordPaged() protected override Register16 GetWordPaged()
{ {
Intermediate.Low = MemoryRead(); this.Intermediate.Low = this.MemoryRead();
++Bus.Address.Low; ++this.Bus.Address.Low;
Intermediate.High = MemoryRead(); this.Intermediate.High = this.MemoryRead();
return Intermediate; return this.Intermediate;
} }
protected override Register16 PopWord() protected override Register16 PopWord()
{ {
Intermediate.Low = Pop(); this.Intermediate.Low = this.Pop();
Intermediate.High = Pop(); this.Intermediate.High = this.Pop();
return Intermediate; return this.Intermediate;
} }
protected override void PushWord(Register16 value) protected override void PushWord(Register16 value)
{ {
ArgumentNullException.ThrowIfNull(value); ArgumentNullException.ThrowIfNull(value);
Push(value.High); this.Push(value.High);
Push(value.Low); this.Push(value.Low);
} }
protected override void SetWord(Register16 value) protected override void SetWord(Register16 value)
{ {
ArgumentNullException.ThrowIfNull(value); ArgumentNullException.ThrowIfNull(value);
MemoryWrite(value.Low); this.MemoryWrite(value.Low);
++Bus.Address.Word; ++this.Bus.Address.Word;
MemoryWrite(value.High); this.MemoryWrite(value.High);
} }
protected override void SetWordPaged(Register16 value) protected override void SetWordPaged(Register16 value)
{ {
ArgumentNullException.ThrowIfNull(value); ArgumentNullException.ThrowIfNull(value);
MemoryWrite(value.Low); this.MemoryWrite(value.Low);
++Bus.Address.Low; ++this.Bus.Address.Low;
MemoryWrite(value.High); this.MemoryWrite(value.High);
} }
} }
} }

View File

@@ -19,9 +19,6 @@ namespace EightBit
public AccessLevel Access { get; set; } = access; public AccessLevel Access { get; set; } = access;
public int Offset(ushort absolute) public int Offset(ushort absolute) => (absolute - this.Begin) & this.Mask;
{
return (absolute - Begin) & Mask;
}
} }
} }

View File

@@ -10,6 +10,7 @@ namespace EightBit
public static bool Lowered(this PinLevel line) => line == PinLevel.Low; public static bool Lowered(this PinLevel line) => line == PinLevel.Low;
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
public static void Raise(this ref PinLevel line) => line = PinLevel.High; public static void Raise(this ref PinLevel line) => line = PinLevel.High;
public static void Lower(this ref PinLevel line) => line = PinLevel.Low; public static void Lower(this ref PinLevel line) => line = PinLevel.Low;

View File

@@ -36,9 +36,10 @@ namespace EightBit
public event EventHandler<EventArgs>? LoweredINT; public event EventHandler<EventArgs>? LoweredINT;
public ref PinLevel RESET => ref _resetLine; public ref PinLevel RESET => ref this._resetLine;
public ref PinLevel INT => ref _intLine; [System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1720:Identifier contains type name", Justification = "Chip pin name")]
public ref PinLevel INT => ref this._intLine;
public Bus Bus { get; } = memory; public Bus Bus { get; } = memory;
@@ -58,17 +59,17 @@ namespace EightBit
public static sbyte SignExtend(int b, int x) => SignExtend(b, (byte)x); public static sbyte SignExtend(int b, int x) => SignExtend(b, (byte)x);
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1716:Identifiers should not match keywords", Justification = "Not using VB.NET")]
public virtual int Step() public virtual int Step()
{ {
ResetCycles(); this.ResetCycles();
OnExecutingInstruction(); this.OnExecutingInstruction();
if (Powered) if (this.Powered)
{ {
PoweredStep(); this.PoweredStep();
} }
this.OnExecutedInstruction();
OnExecutedInstruction(); return this.Cycles;
return Cycles;
} }
public abstract void PoweredStep(); public abstract void PoweredStep();
@@ -78,9 +79,9 @@ namespace EightBit
public int Run(int limit) public int Run(int limit)
{ {
var current = 0; var current = 0;
while (Powered && (current < limit)) while (this.Powered && (current < limit))
{ {
current += Step(); current += this.Step();
} }
return current; return current;
@@ -88,53 +89,55 @@ namespace EightBit
public void Execute(byte value) public void Execute(byte value)
{ {
OpCode = value; this.OpCode = value;
Execute(); this.Execute();
} }
public abstract Register16 PeekWord(ushort address); public abstract Register16 PeekWord(ushort address);
public abstract void PokeWord(ushort address, Register16 value); public abstract void PokeWord(ushort address, Register16 value);
public void PokeWord(ushort address, ushort value) => PokeWord(address, new Register16(value)); public void PokeWord(ushort address, ushort value) => this.PokeWord(address, new Register16(value));
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
public virtual void RaiseRESET() public virtual void RaiseRESET()
{ {
if (RESET.Lowered()) if (this.RESET.Lowered())
{ {
OnRaisingRESET(); this.OnRaisingRESET();
RESET.Raise(); this.RESET.Raise();
OnRaisedRESET(); this.OnRaisedRESET();
} }
} }
public virtual void LowerRESET() public virtual void LowerRESET()
{ {
if (RESET.Raised()) if (this.RESET.Raised())
{ {
OnLoweringRESET(); this.OnLoweringRESET();
RESET.Lower(); this.RESET.Lower();
OnLoweredRESET(); this.OnLoweredRESET();
} }
} }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
public virtual void RaiseINT() public virtual void RaiseINT()
{ {
if (INT.Lowered()) if (this.INT.Lowered())
{ {
OnRaisingINT(); this.OnRaisingINT();
INT.Raise(); this.INT.Raise();
OnRaisedINT(); this.OnRaisedINT();
} }
} }
public virtual void LowerINT() public virtual void LowerINT()
{ {
if (INT.Raised()) if (this.INT.Raised())
{ {
OnLoweringINT(); this.OnLoweringINT();
INT.Lower(); this.INT.Lower();
OnLoweredINT(); this.OnLoweredINT();
} }
} }
@@ -154,77 +157,77 @@ namespace EightBit
protected virtual void OnLoweredINT() => LoweredINT?.Invoke(this, EventArgs.Empty); protected virtual void OnLoweredINT() => LoweredINT?.Invoke(this, EventArgs.Empty);
protected virtual void HandleRESET() => RaiseRESET(); protected virtual void HandleRESET() => this.RaiseRESET();
protected virtual void HandleINT() => RaiseINT(); protected virtual void HandleINT() => this.RaiseINT();
protected void MemoryWrite(byte low, byte high) protected void MemoryWrite(byte low, byte high)
{ {
Bus.Address.Assign(low, high); this.Bus.Address.Assign(low, high);
MemoryWrite(); this.MemoryWrite();
} }
protected void MemoryWrite(byte low, byte high, byte data) protected void MemoryWrite(byte low, byte high, byte data)
{ {
Bus.Address.Assign(low, high); this.Bus.Address.Assign(low, high);
MemoryWrite(data); this.MemoryWrite(data);
} }
protected void MemoryWrite(ushort address, byte data) protected void MemoryWrite(ushort address, byte data)
{ {
Bus.Address.Word = address; this.Bus.Address.Word = address;
MemoryWrite(data); this.MemoryWrite(data);
} }
protected void MemoryWrite(Register16 address, byte data) protected void MemoryWrite(Register16 address, byte data)
{ {
ArgumentNullException.ThrowIfNull(address); ArgumentNullException.ThrowIfNull(address);
MemoryWrite(address.Low, address.High, data); this.MemoryWrite(address.Low, address.High, data);
} }
protected void MemoryWrite(Register16 address) protected void MemoryWrite(Register16 address)
{ {
ArgumentNullException.ThrowIfNull(address); ArgumentNullException.ThrowIfNull(address);
MemoryWrite(address.Low, address.High); this.MemoryWrite(address.Low, address.High);
} }
protected void MemoryWrite(byte data) protected void MemoryWrite(byte data)
{ {
Bus.Data = data; this.Bus.Data = data;
MemoryWrite(); this.MemoryWrite();
} }
protected virtual void MemoryWrite() => BusWrite(); protected virtual void MemoryWrite() => this.BusWrite();
protected virtual void BusWrite() => Bus.Write(); // N.B. Should be the only real call into the "Bus.Write" code. protected virtual void BusWrite() => this.Bus.Write(); // N.B. Should be the only real call into the "Bus.Write" code.
protected byte MemoryRead(byte low, byte high) protected byte MemoryRead(byte low, byte high)
{ {
Bus.Address.Assign(low, high); this.Bus.Address.Assign(low, high);
return MemoryRead(); return this.MemoryRead();
} }
protected byte MemoryRead(ushort address) protected byte MemoryRead(ushort address)
{ {
Bus.Address.Word = address; this.Bus.Address.Word = address;
return MemoryRead(); return this.MemoryRead();
} }
protected byte MemoryRead(Register16 address) protected byte MemoryRead(Register16 address)
{ {
ArgumentNullException.ThrowIfNull(address); ArgumentNullException.ThrowIfNull(address);
return MemoryRead(address.Low, address.High); return this.MemoryRead(address.Low, address.High);
} }
protected virtual byte MemoryRead() => BusRead(); protected virtual byte MemoryRead() => this.BusRead();
protected virtual byte BusRead() => Bus.Read(); // N.B. Should be the only real call into the "Bus.Read" code. protected virtual byte BusRead() => this.Bus.Read(); // N.B. Should be the only real call into the "Bus.Read" code.
protected virtual byte FetchByte() protected virtual byte FetchByte()
{ {
Bus.Address.Assign(PC); this.Bus.Address.Assign(this.PC);
PC.Word++; this.PC.Word++;
return MemoryRead(); return this.MemoryRead();
} }
protected abstract Register16 GetWord(); protected abstract Register16 GetWord();
@@ -236,13 +239,13 @@ namespace EightBit
protected Register16 GetWordPaged(Register16 address) protected Register16 GetWordPaged(Register16 address)
{ {
ArgumentNullException.ThrowIfNull(address); ArgumentNullException.ThrowIfNull(address);
return GetWordPaged(address.High, address.Low); return this.GetWordPaged(address.High, address.Low);
} }
protected Register16 GetWordPaged(byte page, byte offset) protected Register16 GetWordPaged(byte page, byte offset)
{ {
Bus.Address.Assign(offset, page); this.Bus.Address.Assign(offset, page);
return GetWordPaged(); return this.GetWordPaged();
} }
protected abstract void SetWordPaged(Register16 value); protected abstract void SetWordPaged(Register16 value);
@@ -250,21 +253,21 @@ namespace EightBit
protected void SetWordPaged(Register16 address, Register16 value) protected void SetWordPaged(Register16 address, Register16 value)
{ {
ArgumentNullException.ThrowIfNull(address); ArgumentNullException.ThrowIfNull(address);
SetWordPaged(address.High, address.Low, value); this.SetWordPaged(address.High, address.Low, value);
} }
protected void SetWordPaged(byte page, byte offset, Register16 value) protected void SetWordPaged(byte page, byte offset, Register16 value)
{ {
Bus.Address.Assign(offset, page); this.Bus.Address.Assign(offset, page);
SetWordPaged(value); this.SetWordPaged(value);
} }
protected abstract Register16 FetchWord(); protected abstract Register16 FetchWord();
protected void FetchWordAddress() protected void FetchWordAddress()
{ {
FetchWord(); _ = this.FetchWord();
Bus.Address.Assign(Intermediate); this.Bus.Address.Assign(this.Intermediate);
} }
protected abstract void Push(byte value); protected abstract void Push(byte value);
@@ -277,47 +280,50 @@ namespace EightBit
protected Register16 GetWord(ushort address) protected Register16 GetWord(ushort address)
{ {
Bus.Address.Word = address; this.Bus.Address.Word = address;
return GetWord(); return this.GetWord();
} }
protected Register16 GetWord(Register16 address) protected Register16 GetWord(Register16 address)
{ {
Bus.Address.Assign(address); this.Bus.Address.Assign(address);
return GetWord(); return this.GetWord();
} }
protected void SetWord(ushort address, Register16 value) protected void SetWord(ushort address, Register16 value)
{ {
Bus.Address.Word = address; this.Bus.Address.Word = address;
SetWord(value); this.SetWord(value);
} }
protected void SetWord(Register16 address, Register16 value) protected void SetWord(Register16 address, Register16 value)
{ {
Bus.Address.Assign(address); this.Bus.Address.Assign(address);
SetWord(value); this.SetWord(value);
} }
protected void Jump(ushort destination) => PC.Word = destination; protected void Jump(ushort destination) => this.PC.Word = destination;
protected void Jump(Register16 destination) protected void Jump(Register16 destination)
{ {
PC.Assign(destination); ArgumentNullException.ThrowIfNull(destination);
this.PC.Assign(destination);
} }
protected void Call(ushort destination) protected void Call(ushort destination)
{ {
Intermediate.Word = destination; this.Intermediate.Word = destination;
Call(Intermediate); this.Call(this.Intermediate);
} }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1716:Identifiers should not match keywords", Justification = "Not using VB.NET")]
protected virtual void Call(Register16 destination) protected virtual void Call(Register16 destination)
{ {
PushWord(PC); this.PushWord(this.PC);
Jump(destination); this.Jump(destination);
} }
protected virtual void Return() => Jump(PopWord()); [System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1716:Identifiers should not match keywords", Justification = "Not using VB.NET")]
protected virtual void Return() => this.Jump(this.PopWord());
} }
} }

View File

@@ -11,7 +11,7 @@ namespace EightBit
{ {
} }
public override sealed ref byte Reference(ushort address) => ref Bytes()[address]; public sealed override ref byte Reference(ushort address) => ref this.Bytes()[address];
public new void Poke(ushort address, byte value) => base.Poke(address, value); public new void Poke(ushort address, byte value) => base.Poke(address, value);
} }

View File

@@ -14,14 +14,14 @@ namespace EightBit
public Register16(byte low, byte high) public Register16(byte low, byte high)
{ {
Low = low; this.Low = low;
High = high; this.High = high;
} }
public Register16(ushort value) public Register16(ushort value)
{ {
Low = Chip.LowByte(value); this.Low = Chip.LowByte(value);
High = Chip.HighByte(value); this.High = Chip.HighByte(value);
} }
public Register16() public Register16()
@@ -47,24 +47,24 @@ namespace EightBit
public Register16(Register16 rhs) public Register16(Register16 rhs)
{ {
ArgumentNullException.ThrowIfNull(rhs); ArgumentNullException.ThrowIfNull(rhs);
Low = rhs.Low; this.Low = rhs.Low;
High = rhs.High; this.High = rhs.High;
} }
public ushort Word public ushort Word
{ {
get => Chip.MakeWord(Low, High); get => Chip.MakeWord(this.Low, this.High);
set set
{ {
Low = Chip.LowByte(value); this.Low = Chip.LowByte(value);
High = Chip.HighByte(value); this.High = Chip.HighByte(value);
} }
} }
public ref byte Low => ref _low; public ref byte Low => ref this._low;
public ref byte High => ref _high; public ref byte High => ref this._high;
public static bool operator ==(Register16 left, Register16 right) public static bool operator ==(Register16 left, Register16 right)
{ {
@@ -74,38 +74,22 @@ namespace EightBit
public static bool operator !=(Register16 left, Register16 right) => !(left == right); public static bool operator !=(Register16 left, Register16 right) => !(left == right);
public override int GetHashCode() => Word; public override int GetHashCode() => this.Word;
public override bool Equals(object? obj) public override bool Equals(object? obj) => this.Equals(obj as Register16);
{
return Equals(obj as Register16);
}
public bool Equals(Register16? rhs) public bool Equals(Register16? rhs) => ReferenceEquals(this, rhs) || (rhs is not null && rhs.Low == this.Low && rhs.High == this.High);
{
if (ReferenceEquals(this, rhs))
{
return true;
}
if (rhs is null)
{
return false;
}
return rhs.Low == Low && rhs.High == High;
}
public void Assign(byte low, byte high) public void Assign(byte low, byte high)
{ {
_low = low; this._low = low;
_high = high; this._high = high;
} }
public void Assign(Register16 from) public void Assign(Register16 from)
{ {
ArgumentNullException.ThrowIfNull(from); ArgumentNullException.ThrowIfNull(from);
Assign(from._low, from._high); this.Assign(from._low, from._high);
} }
} }
} }

View File

@@ -4,11 +4,13 @@
namespace EightBit namespace EightBit
{ {
using System.Diagnostics;
public class Rom(int size = 0) : Memory public class Rom(int size = 0) : Memory
{ {
private byte[] _bytes = new byte[size]; private byte[] _bytes = new byte[size];
public override int Size => _bytes.Length; public override int Size => this._bytes.Length;
public static int Load(Stream file, ref byte[] output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1) public static int Load(Stream file, ref byte[] output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1)
{ {
@@ -24,7 +26,7 @@ namespace EightBit
if ((limit < 0) || (limit > size)) if ((limit < 0) || (limit > size))
{ {
limit = (int)size; limit = size;
} }
var extent = limit + writeOffset; var extent = limit + writeOffset;
@@ -35,10 +37,12 @@ namespace EightBit
output = updated; output = updated;
} }
file.Seek(readOffset, SeekOrigin.Begin); var position = file.Seek(readOffset, SeekOrigin.Begin);
Debug.Assert(position == readOffset);
using (var reader = new BinaryReader(file)) using (var reader = new BinaryReader(file))
{ {
reader.Read(output, writeOffset, limit); var actual = reader.Read(output, writeOffset, limit);
Debug.Assert(actual <= limit);
} }
return size; return size;
@@ -52,14 +56,14 @@ namespace EightBit
public override int Load(FileStream file, int writeOffset = 0, int readOffset = 0, int limit = -1) public override int Load(FileStream file, int writeOffset = 0, int readOffset = 0, int limit = -1)
{ {
var maximumSize = Size - writeOffset; var maximumSize = this.Size - writeOffset;
return Load(file, ref Bytes(), writeOffset, readOffset, limit, maximumSize); return Load(file, ref this.Bytes(), writeOffset, readOffset, limit, maximumSize);
} }
public override int Load(string path, int writeOffset = 0, int readOffset = 0, int limit = -1) public override int Load(string path, int writeOffset = 0, int readOffset = 0, int limit = -1)
{ {
var maximumSize = Size - writeOffset; var maximumSize = this.Size - writeOffset;
return Load(path, ref Bytes(), writeOffset, readOffset, limit, maximumSize); return Load(path, ref this.Bytes(), writeOffset, readOffset, limit, maximumSize);
} }
public override int Load(byte[] from, int writeOffset = 0, int readOffset = 0, int limit = -1) public override int Load(byte[] from, int writeOffset = 0, int readOffset = 0, int limit = -1)
@@ -68,26 +72,26 @@ namespace EightBit
if (limit < 0) if (limit < 0)
{ {
limit = Math.Min(from.Length, Size - readOffset); limit = Math.Min(from.Length, this.Size - readOffset);
} }
var extent = limit + writeOffset; var extent = limit + writeOffset;
if (Size < extent) if (this.Size < extent)
{ {
var updated = new byte[extent]; var updated = new byte[extent];
Array.Copy(Bytes(), updated, Size); Array.Copy(this.Bytes(), updated, this.Size);
Bytes() = updated; this.Bytes() = updated;
} }
Array.Copy(from, readOffset, Bytes(), writeOffset, limit); Array.Copy(from, readOffset, this.Bytes(), writeOffset, limit);
return limit; return limit;
} }
public override byte Peek(ushort address) => Bytes()[address]; public override byte Peek(ushort address) => this.Bytes()[address];
protected ref byte[] Bytes() => ref _bytes; protected ref byte[] Bytes() => ref this._bytes;
protected override void Poke(ushort address, byte value) => Bytes()[address] = value; protected override void Poke(ushort address, byte value) => this.Bytes()[address] = value;
} }
} }

View File

@@ -9,7 +9,7 @@ namespace EightBit
private readonly int _size = size; private readonly int _size = size;
private readonly byte _unchanging = unchanging; private readonly byte _unchanging = unchanging;
public override int Size => _size; public override int Size => this._size;
public override int Load(FileStream file, int writeOffset = 0, int readOffset = 0, int limit = -1) => throw new NotImplementedException(); public override int Load(FileStream file, int writeOffset = 0, int readOffset = 0, int limit = -1) => throw new NotImplementedException();
@@ -17,7 +17,7 @@ namespace EightBit
public override int Load(byte[] from, int writeOffset = 0, int readOffset = 0, int limit = -1) => throw new NotImplementedException(); public override int Load(byte[] from, int writeOffset = 0, int readOffset = 0, int limit = -1) => throw new NotImplementedException();
public override byte Peek(ushort address) => _unchanging; public override byte Peek(ushort address) => this._unchanging;
protected override void Poke(ushort address, byte value) => throw new NotImplementedException(); protected override void Poke(ushort address, byte value) => throw new NotImplementedException();
} }