Not sure if this was a really good idea, but integrated StyleCop rules into the builds. Corrected all except documentation problems.
Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
parent
30aa1b70bf
commit
224000c4c7
|
@ -12,6 +12,9 @@ EndProject
|
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestEightBit", "UnitTestEightBit\UnitTestEightBit.csproj", "{AA8282A3-212A-42DE-B778-BBAEB7E6D986}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(Performance) = preSolution
|
||||
HasPerformanceSessions = true
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
namespace EightBit
|
||||
// <copyright file="AccessLevel.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
namespace EightBit
|
||||
{
|
||||
public enum AccessLevel
|
||||
{
|
||||
Unknown, ReadOnly, WriteOnly, ReadWrite
|
||||
Unknown,
|
||||
ReadOnly,
|
||||
WriteOnly,
|
||||
ReadWrite,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
namespace EightBit
|
||||
// <copyright file="BigEndianProcessor.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
namespace EightBit
|
||||
{
|
||||
public abstract class BigEndianProcessor : Processor
|
||||
{
|
||||
|
@ -9,63 +12,63 @@
|
|||
|
||||
public override ushort PeekWord(ushort address)
|
||||
{
|
||||
var high = Bus.Peek(address);
|
||||
var low = Bus.Peek(++address);
|
||||
return MakeWord(low, high);
|
||||
var high = this.Bus.Peek(address);
|
||||
var low = this.Bus.Peek(++address);
|
||||
return Chip.MakeWord(low, high);
|
||||
}
|
||||
|
||||
public override void PokeWord(ushort address, ushort value)
|
||||
{
|
||||
Bus.Poke(address, LowByte(value));
|
||||
Bus.Poke(++address, HighByte(value));
|
||||
this.Bus.Poke(address, Chip.LowByte(value));
|
||||
this.Bus.Poke(++address, Chip.HighByte(value));
|
||||
}
|
||||
|
||||
protected override ushort FetchWord()
|
||||
{
|
||||
var high = FetchByte();
|
||||
var low = FetchByte();
|
||||
return MakeWord(low, high);
|
||||
var high = this.FetchByte();
|
||||
var low = this.FetchByte();
|
||||
return Chip.MakeWord(low, high);
|
||||
}
|
||||
|
||||
protected override ushort GetWord()
|
||||
{
|
||||
var high = BusRead();
|
||||
++Bus.Address;
|
||||
var low = BusRead();
|
||||
return MakeWord(low, high);
|
||||
var high = this.BusRead();
|
||||
++this.Bus.Address;
|
||||
var low = this.BusRead();
|
||||
return Chip.MakeWord(low, high);
|
||||
}
|
||||
|
||||
protected override ushort GetWordPaged(byte page, byte offset)
|
||||
{
|
||||
var high = BusRead(offset, page);
|
||||
var low = BusRead((byte)(offset + 1), page);
|
||||
return MakeWord(low, high);
|
||||
var high = this.BusRead(offset, page);
|
||||
var low = this.BusRead((byte)(offset + 1), page);
|
||||
return Chip.MakeWord(low, high);
|
||||
}
|
||||
|
||||
protected override ushort PopWord()
|
||||
{
|
||||
var high = Pop();
|
||||
var low = Pop();
|
||||
return MakeWord(low, high);
|
||||
var high = this.Pop();
|
||||
var low = this.Pop();
|
||||
return Chip.MakeWord(low, high);
|
||||
}
|
||||
|
||||
protected override void PushWord(ushort value)
|
||||
{
|
||||
Push(LowByte(value));
|
||||
Push(HighByte(value));
|
||||
this.Push(Chip.LowByte(value));
|
||||
this.Push(Chip.HighByte(value));
|
||||
}
|
||||
|
||||
protected override void SetWord(ushort value)
|
||||
{
|
||||
BusWrite(HighByte(value));
|
||||
++Bus.Address;
|
||||
BusWrite(LowByte(value));
|
||||
this.BusWrite(Chip.HighByte(value));
|
||||
++this.Bus.Address;
|
||||
this.BusWrite(Chip.LowByte(value));
|
||||
}
|
||||
|
||||
protected override void SetWordPaged(byte page, byte offset, ushort value)
|
||||
{
|
||||
BusWrite(offset, page, HighByte(value));
|
||||
BusWrite((byte)(offset + 1), page, LowByte(value));
|
||||
this.BusWrite(offset, page, Chip.HighByte(value));
|
||||
this.BusWrite((byte)(offset + 1), page, Chip.LowByte(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
namespace EightBit
|
||||
// <copyright file="Bits.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
|
||||
|
@ -21,6 +25,6 @@
|
|||
Bit13 = Bit12 << 1,
|
||||
Bit14 = Bit13 << 1,
|
||||
Bit15 = Bit14 << 1,
|
||||
Bit16 = Bit15 << 1
|
||||
Bit16 = Bit15 << 1,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,96 +1,115 @@
|
|||
namespace EightBit
|
||||
// <copyright file="Bus.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
|
||||
abstract public class Bus : IMapper
|
||||
public abstract class Bus : IMapper
|
||||
{
|
||||
private byte data;
|
||||
private ushort address;
|
||||
|
||||
public event EventHandler<EventArgs> WritingByte;
|
||||
|
||||
public event EventHandler<EventArgs> WrittenByte;
|
||||
|
||||
public event EventHandler<EventArgs> ReadingByte;
|
||||
|
||||
public event EventHandler<EventArgs> ReadByte;
|
||||
|
||||
public byte Data { get => data; set => data = value; }
|
||||
public ushort Address { get => address; set => address = value; }
|
||||
public byte Data { get => this.data; set => this.data = value; }
|
||||
|
||||
public ushort Address { get => this.address; set => this.address = value; }
|
||||
|
||||
public abstract MemoryMapping Mapping(ushort absolute);
|
||||
|
||||
public byte Peek() => Reference();
|
||||
public byte Peek(ushort absolute) => Reference(absolute);
|
||||
public byte Peek(byte low, byte high) => Reference(low, high);
|
||||
public byte Peek() => this.Reference();
|
||||
|
||||
public void Poke(byte value) => Reference() = value;
|
||||
public byte Poke(ushort absolute, byte value) => Reference(absolute) = value;
|
||||
public byte Poke(byte low, byte high, byte value) => Reference(low, high) = value;
|
||||
public byte Peek(ushort absolute) => this.Reference(absolute);
|
||||
|
||||
public byte Peek(byte low, byte high) => this.Reference(low, high);
|
||||
|
||||
public void Poke(byte value) => this.Reference() = value;
|
||||
|
||||
public byte Poke(ushort absolute, byte value) => this.Reference(absolute) = value;
|
||||
|
||||
public byte Poke(byte low, byte high, byte value) => this.Reference(low, high) = value;
|
||||
|
||||
public byte Read()
|
||||
{
|
||||
OnReadingByte();
|
||||
var returned = Data = Reference();
|
||||
OnReadByte();
|
||||
this.OnReadingByte();
|
||||
var returned = this.Data = this.Reference();
|
||||
this.OnReadByte();
|
||||
return returned;
|
||||
}
|
||||
|
||||
public byte Read(ushort absolute)
|
||||
{
|
||||
Address = absolute;
|
||||
return Read();
|
||||
this.Address = absolute;
|
||||
return this.Read();
|
||||
}
|
||||
|
||||
public byte Read(byte low, byte high) => Read(Chip.MakeWord(low, high));
|
||||
public byte Read(byte low, byte high) => this.Read(Chip.MakeWord(low, high));
|
||||
|
||||
public void Write()
|
||||
{
|
||||
OnWritingByte();
|
||||
Reference() = Data;
|
||||
OnWrittenByte();
|
||||
this.OnWritingByte();
|
||||
this.Reference() = this.Data;
|
||||
this.OnWrittenByte();
|
||||
}
|
||||
|
||||
public void Write(byte value)
|
||||
{
|
||||
Data = value;
|
||||
Write();
|
||||
this.Data = value;
|
||||
this.Write();
|
||||
}
|
||||
|
||||
public void Write(ushort absolute, byte value)
|
||||
{
|
||||
Address = absolute;
|
||||
Write(value);
|
||||
this.Address = absolute;
|
||||
this.Write(value);
|
||||
}
|
||||
|
||||
public void Write(byte low, byte high, byte value) => Write(Chip.MakeWord(low, high), value);
|
||||
public void Write(byte low, byte high, byte value) => this.Write(Chip.MakeWord(low, high), value);
|
||||
|
||||
public virtual void RaisePOWER() {}
|
||||
public virtual void LowerPOWER() {}
|
||||
public virtual void RaisePOWER()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void LowerPOWER()
|
||||
{
|
||||
}
|
||||
|
||||
public abstract void Initialize();
|
||||
|
||||
protected virtual void OnWritingByte() => WritingByte?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnWrittenByte() => WrittenByte?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnWritingByte() => this.WritingByte?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnReadingByte() => ReadingByte?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnReadByte() => ReadByte?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnWrittenByte() => this.WrittenByte?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnReadingByte() => this.ReadingByte?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnReadByte() => this.ReadByte?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected ref byte Reference(ushort absolute)
|
||||
{
|
||||
var mapped = Mapping(absolute);
|
||||
var mapped = this.Mapping(absolute);
|
||||
var offset = (ushort)((absolute - mapped.Begin) & mapped.Mask);
|
||||
if (mapped.Access == AccessLevel.ReadOnly)
|
||||
{
|
||||
Data = mapped.Memory.Peek(offset);
|
||||
return ref data;
|
||||
this.Data = mapped.Memory.Peek(offset);
|
||||
return ref this.data;
|
||||
}
|
||||
|
||||
return ref mapped.Memory.Reference(offset);
|
||||
}
|
||||
|
||||
protected ref byte Reference() => ref Reference(Address);
|
||||
protected ref byte Reference() => ref this.Reference(this.Address);
|
||||
|
||||
protected ref byte Reference(byte low, byte high) => ref Reference(Chip.MakeWord(low, high));
|
||||
protected ref byte Reference(byte low, byte high) => ref this.Reference(Chip.MakeWord(low, high));
|
||||
|
||||
//[[nodiscard]] static std::map<uint16_t, std::vector<uint8_t>> parseHexFile(std::string path);
|
||||
//void loadHexFile(std::string path);
|
||||
////[[nodiscard]] static std::map<uint16_t, std::vector<uint8_t>> parseHexFile(std::string path);
|
||||
////void loadHexFile(std::string path);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,35 +1,55 @@
|
|||
namespace EightBit
|
||||
// <copyright file="Chip.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
public class Chip : Device
|
||||
{
|
||||
protected Chip() { }
|
||||
protected Chip()
|
||||
{
|
||||
}
|
||||
|
||||
public static byte SetFlag(byte input, byte flag) => (byte)(input | flag);
|
||||
|
||||
public static byte SetFlag(byte input, byte flag, int condition) => SetFlag(input, flag, condition != 0);
|
||||
|
||||
public static byte SetFlag(byte input, byte flag, bool condition) => condition ? SetFlag(input, flag) : ClearFlag(input, flag);
|
||||
|
||||
public static byte ClearFlag(byte input, byte flag) => (byte)(input & (byte)~flag);
|
||||
|
||||
public static byte ClearFlag(byte input, byte flag, int condition) => ClearFlag(input, flag, condition != 0);
|
||||
|
||||
public static byte ClearFlag(byte input, byte flag, bool condition) => SetFlag(input, flag, !condition);
|
||||
|
||||
public static byte HighByte(int value) => (byte)(value >> 8);
|
||||
|
||||
public static byte HighByte(ushort value) => HighByte((int)value);
|
||||
|
||||
public static byte LowByte(int value) => (byte)(value & (int)Mask.Mask8);
|
||||
|
||||
public static byte LowByte(ushort value) => LowByte((int)value);
|
||||
|
||||
public static ushort PromoteByte(byte value) => (ushort)(value << 8);
|
||||
|
||||
public static byte DemoteByte(ushort value) => HighByte(value);
|
||||
|
||||
public static ushort HigherPart(ushort value) => (ushort)(value & 0xff00);
|
||||
|
||||
public static byte LowerPart(ushort value) => LowByte(value);
|
||||
|
||||
static public ushort MakeWord(byte low, byte high) => (ushort)(PromoteByte(high) | low);
|
||||
public static ushort MakeWord(byte low, byte high) => (ushort)(PromoteByte(high) | low);
|
||||
|
||||
public static int HighNibble(byte value) => value >> 4;
|
||||
|
||||
public static int LowNibble(byte value) => value & 0xf;
|
||||
|
||||
public static int HigherNibble(byte value) => value & 0xf0;
|
||||
|
||||
public static int LowerNibble(byte value) => LowNibble(value);
|
||||
|
||||
public static int PromoteNibble(byte value) => LowByte(value << 4);
|
||||
|
||||
public static int DemoteNibble(byte value) => HighNibble(value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
namespace EightBit
|
||||
// <copyright file="ClockedChip.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
|
||||
|
@ -6,26 +10,30 @@
|
|||
{
|
||||
private int cycles;
|
||||
|
||||
protected ClockedChip() { }
|
||||
|
||||
public int Cycles { get => cycles; protected set => cycles = value; }
|
||||
protected ClockedChip()
|
||||
{
|
||||
}
|
||||
|
||||
public event EventHandler<EventArgs> Ticked;
|
||||
|
||||
|
||||
public int Cycles { get => this.cycles; protected set => this.cycles = value; }
|
||||
|
||||
public void Tick(int extra)
|
||||
{
|
||||
for (int i = 0; i < extra; ++i)
|
||||
Tick();
|
||||
{
|
||||
this.Tick();
|
||||
}
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
++Cycles;
|
||||
OnTicked();
|
||||
++this.Cycles;
|
||||
this.OnTicked();
|
||||
}
|
||||
|
||||
protected virtual void OnTicked() => Ticked?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnTicked() => this.Ticked?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected void ResetCycles() => Cycles = 0;
|
||||
protected void ResetCycles() => this.Cycles = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
namespace EightBit
|
||||
// <copyright file="Device.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
|
||||
|
@ -6,35 +10,42 @@
|
|||
{
|
||||
private PinLevel powerLine;
|
||||
|
||||
protected Device() { }
|
||||
protected Device()
|
||||
{
|
||||
}
|
||||
|
||||
public event EventHandler<EventArgs> RaisingPOWER;
|
||||
|
||||
public event EventHandler<EventArgs> RaisedPOWER;
|
||||
|
||||
public event EventHandler<EventArgs> LoweringPOWER;
|
||||
|
||||
public event EventHandler<EventArgs> LoweredPOWER;
|
||||
|
||||
public ref PinLevel POWER() => ref powerLine;
|
||||
public bool Powered => this.POWER().Raised();
|
||||
|
||||
public bool Powered => POWER().Raised();
|
||||
public ref PinLevel POWER() => ref this.powerLine;
|
||||
|
||||
public virtual void RaisePOWER()
|
||||
{
|
||||
OnRaisingPOWER();
|
||||
POWER().Raise();
|
||||
OnRaisedPOWER();
|
||||
this.OnRaisingPOWER();
|
||||
this.POWER().Raise();
|
||||
this.OnRaisedPOWER();
|
||||
}
|
||||
|
||||
public virtual void LowerPOWER()
|
||||
{
|
||||
OnLoweringPOWER();
|
||||
POWER().Lower();
|
||||
OnLoweredPOWER();
|
||||
this.OnLoweringPOWER();
|
||||
this.POWER().Lower();
|
||||
this.OnLoweredPOWER();
|
||||
}
|
||||
|
||||
protected virtual void OnRaisingPOWER() => RaisingPOWER?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnRaisedPOWER() => RaisedPOWER?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnRaisingPOWER() => this.RaisingPOWER?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweringPOWER() => LoweringPOWER?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnLoweredPOWER() => LoweredPOWER?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnRaisedPOWER() => this.RaisedPOWER?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweringPOWER() => this.LoweringPOWER?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweredPOWER() => this.LoweredPOWER?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisIgnoreGeneratedCode>false</CodeAnalysisIgnoreGeneratedCode>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
|
@ -55,13 +56,12 @@
|
|||
<Compile Include="Chip.cs" />
|
||||
<Compile Include="ClockedChip.cs" />
|
||||
<Compile Include="Device.cs" />
|
||||
<Compile Include="GlobalSuppressions.cs" />
|
||||
<Compile Include="IntelOpCodeDecoded.cs" />
|
||||
<Compile Include="Memory.cs" />
|
||||
<Compile Include="InputOutput.cs" />
|
||||
<Compile Include="IntelProcessor.cs" />
|
||||
<Compile Include="LittleEndianProcessor.cs" />
|
||||
<Compile Include="Mapper.cs" />
|
||||
<Compile Include="IMapper.cs" />
|
||||
<Compile Include="Mask.cs" />
|
||||
<Compile Include="MemoryMapping.cs" />
|
||||
<Compile Include="PinLevel.cs" />
|
||||
|
@ -73,5 +73,13 @@
|
|||
<Compile Include="Rom.cs" />
|
||||
<Compile Include="UnusedMemory.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<AdditionalFiles Include="stylecop.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Analyzer Include="..\packages\StyleCop.Analyzers.Unstable.1.1.1.61\analyzers\dotnet\cs\StyleCop.Analyzers.CodeFixes.dll" />
|
||||
<Analyzer Include="..\packages\StyleCop.Analyzers.Unstable.1.1.1.61\analyzers\dotnet\cs\StyleCop.Analyzers.dll" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
Binary file not shown.
|
@ -0,0 +1,11 @@
|
|||
// <copyright file="IMapper.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
public interface IMapper
|
||||
{
|
||||
MemoryMapping Mapping(ushort address);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,8 @@
|
|||
namespace EightBit
|
||||
// <copyright file="InputOutput.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
|
||||
|
@ -12,37 +16,42 @@
|
|||
}
|
||||
|
||||
public event EventHandler<PortEventArgs> ReadingPort;
|
||||
|
||||
public event EventHandler<PortEventArgs> ReadPort;
|
||||
|
||||
public event EventHandler<PortEventArgs> WritingPort;
|
||||
|
||||
public event EventHandler<PortEventArgs> WrittenPort;
|
||||
|
||||
byte Read(byte port) => ReadInputPort(port);
|
||||
void Write(byte port, byte value) => WriteOutputPort(port, value);
|
||||
public byte Read(byte port) => this.ReadInputPort(port);
|
||||
|
||||
byte ReadInputPort(byte port)
|
||||
public void Write(byte port, byte value) => this.WriteOutputPort(port, value);
|
||||
|
||||
public byte ReadInputPort(byte port)
|
||||
{
|
||||
OnReadingPort(port);
|
||||
var value = input[port];
|
||||
OnReadPort(port);
|
||||
this.OnReadingPort(port);
|
||||
var value = this.input[port];
|
||||
this.OnReadPort(port);
|
||||
return value;
|
||||
}
|
||||
|
||||
void WriteInputPort(byte port, byte value) => input[port] = value;
|
||||
public void WriteInputPort(byte port, byte value) => this.input[port] = value;
|
||||
|
||||
byte ReadOutputPort(byte port) => output[port];
|
||||
public byte ReadOutputPort(byte port) => this.output[port];
|
||||
|
||||
void WriteOutputPort(byte port, byte value)
|
||||
public void WriteOutputPort(byte port, byte value)
|
||||
{
|
||||
OnWritingPort(port);
|
||||
output[port] = value;
|
||||
OnWrittenPort(port);
|
||||
this.OnWritingPort(port);
|
||||
this.output[port] = value;
|
||||
this.OnWrittenPort(port);
|
||||
}
|
||||
|
||||
private void OnReadingPort(byte port) => ReadingPort?.Invoke(this, new PortEventArgs(port));
|
||||
private void OnReadPort(byte port) => ReadPort?.Invoke(this, new PortEventArgs(port));
|
||||
private void OnReadingPort(byte port) => this.ReadingPort?.Invoke(this, new PortEventArgs(port));
|
||||
|
||||
private void OnWritingPort(byte port) => WritingPort?.Invoke(this, new PortEventArgs(port));
|
||||
private void OnWrittenPort(byte port) => WrittenPort?.Invoke(this, new PortEventArgs(port));
|
||||
private void OnReadPort(byte port) => this.ReadPort?.Invoke(this, new PortEventArgs(port));
|
||||
|
||||
private void OnWritingPort(byte port) => this.WritingPort?.Invoke(this, new PortEventArgs(port));
|
||||
|
||||
private void OnWrittenPort(byte port) => this.WrittenPort?.Invoke(this, new PortEventArgs(port));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +1,28 @@
|
|||
namespace EightBit
|
||||
{
|
||||
class IntelOpCodeDecoded
|
||||
{
|
||||
public int x;
|
||||
public int y;
|
||||
public int z;
|
||||
public int p;
|
||||
public int q;
|
||||
// <copyright file="IntelOpCodeDecoded.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
public IntelOpCodeDecoded() { }
|
||||
namespace EightBit
|
||||
{
|
||||
public class IntelOpCodeDecoded
|
||||
{
|
||||
private int x;
|
||||
private int y;
|
||||
private int z;
|
||||
private int p;
|
||||
private int q;
|
||||
|
||||
public IntelOpCodeDecoded()
|
||||
{
|
||||
}
|
||||
|
||||
public IntelOpCodeDecoded(byte opcode)
|
||||
{
|
||||
x = (opcode & 0b11000000) >> 6; // 0 - 3
|
||||
y = (opcode & 0b00111000) >> 3; // 0 - 7
|
||||
z = (opcode & 0b00000111); // 0 - 7
|
||||
p = (y & 0b110) >> 1; // 0 - 3
|
||||
q = (y & 1); // 0 - 1
|
||||
this.x = (opcode & 0b11000000) >> 6; // 0 - 3
|
||||
this.y = (opcode & 0b00111000) >> 3; // 0 - 7
|
||||
this.z = opcode & 0b00000111; // 0 - 7
|
||||
this.p = (this.y & 0b110) >> 1; // 0 - 3
|
||||
this.q = this.y & 1; // 0 - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
namespace EightBit
|
||||
// <copyright file="IntelProcessor.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
|
||||
|
@ -13,151 +17,180 @@
|
|||
protected IntelProcessor(Bus bus)
|
||||
: base(bus)
|
||||
{
|
||||
sp = (ushort)Mask.Mask16;
|
||||
memptr = (ushort)Mask.Mask16;
|
||||
this.sp = (ushort)Mask.Mask16;
|
||||
this.memptr = (ushort)Mask.Mask16;
|
||||
|
||||
for (int i = 0; i < 0x100; ++i)
|
||||
decodedOpCodes[i] = new IntelOpCodeDecoded((byte)i);
|
||||
{
|
||||
this.decodedOpCodes[i] = new IntelOpCodeDecoded((byte)i);
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler<EventArgs> RaisingHALT;
|
||||
|
||||
public event EventHandler<EventArgs> RaisedHALT;
|
||||
|
||||
public event EventHandler<EventArgs> LoweringHALT;
|
||||
|
||||
public event EventHandler<EventArgs> LoweredHALT;
|
||||
|
||||
public ref PinLevel HALT() => ref haltLine;
|
||||
public ushort SP { get => this.sp; set => this.sp = value; }
|
||||
|
||||
protected bool Halted => HALT().Lowered();
|
||||
|
||||
public ushort SP { get => sp; set => sp = value; }
|
||||
public ushort MEMPTR { get => memptr; set => memptr = value; }
|
||||
public ushort MEMPTR { get => this.memptr; set => this.memptr = value; }
|
||||
|
||||
public abstract ushort AF { get; set; }
|
||||
public byte A { get => HighByte(AF); set => AF = (ushort)(LowerPart(AF) | PromoteByte(value)); }
|
||||
public byte F { get => LowByte(AF); set => AF = (ushort)(HigherPart(AF) | value); }
|
||||
|
||||
public byte A { get => Chip.HighByte(this.AF); set => this.AF = (ushort)(Chip.LowerPart(this.AF) | Chip.PromoteByte(value)); }
|
||||
|
||||
public byte F { get => Chip.LowByte(this.AF); set => this.AF = (ushort)(Chip.HigherPart(this.AF) | value); }
|
||||
|
||||
public abstract ushort BC { get; set; }
|
||||
public byte B { get => HighByte(AF); set => BC = (ushort)(LowerPart(BC) | PromoteByte(value)); }
|
||||
public byte C { get => LowByte(AF); set => BC = (ushort)(HigherPart(BC) | value); }
|
||||
|
||||
public byte B { get => Chip.HighByte(this.BC); set => this.BC = (ushort)(Chip.LowerPart(this.BC) | Chip.PromoteByte(value)); }
|
||||
|
||||
public byte C { get => Chip.LowByte(this.BC); set => this.BC = (ushort)(Chip.HigherPart(this.BC) | value); }
|
||||
|
||||
public abstract ushort DE { get; set; }
|
||||
public byte D { get => HighByte(DE); set => DE = (ushort)(LowerPart(DE) | PromoteByte(value)); }
|
||||
public byte E { get => LowByte(DE); set => DE = (ushort)(HigherPart(DE) | value); }
|
||||
|
||||
public byte D { get => Chip.HighByte(this.DE); set => this.DE = (ushort)(Chip.LowerPart(this.DE) | Chip.PromoteByte(value)); }
|
||||
|
||||
public byte E { get => Chip.LowByte(this.DE); set => this.DE = (ushort)(Chip.HigherPart(this.DE) | value); }
|
||||
|
||||
public abstract ushort HL { get; set; }
|
||||
public byte H { get => HighByte(HL); set => HL = (ushort)(LowerPart(HL) | PromoteByte(value)); }
|
||||
public byte L { get => LowByte(HL); set { HL = (ushort)(HigherPart(HL) | value); } }
|
||||
|
||||
public byte H { get => Chip.HighByte(this.HL); set => this.HL = (ushort)(Chip.LowerPart(this.HL) | Chip.PromoteByte(value)); }
|
||||
|
||||
public byte L { get => Chip.LowByte(this.HL); set => this.HL = (ushort)(Chip.HigherPart(this.HL) | value); }
|
||||
|
||||
protected bool Halted => this.HALT().Lowered();
|
||||
|
||||
public ref PinLevel HALT() => ref this.haltLine;
|
||||
|
||||
public override void RaisePOWER()
|
||||
{
|
||||
base.RaisePOWER();
|
||||
RaiseHALT();
|
||||
SP = AF = BC = DE = HL = (ushort)Mask.Mask16;
|
||||
this.RaiseHALT();
|
||||
this.SP = this.AF = this.BC = this.DE = this.HL = (ushort)Mask.Mask16;
|
||||
}
|
||||
|
||||
public virtual void RaiseHALT()
|
||||
{
|
||||
OnRaisingHALT();
|
||||
HALT().Raise();
|
||||
OnRaisedHALT();
|
||||
this.OnRaisingHALT();
|
||||
this.HALT().Raise();
|
||||
this.OnRaisedHALT();
|
||||
}
|
||||
|
||||
public virtual void LowerHALT()
|
||||
{
|
||||
OnLoweringHALT();
|
||||
HALT().Lower();
|
||||
OnLoweredHALT();
|
||||
this.OnLoweringHALT();
|
||||
this.HALT().Lower();
|
||||
this.OnLoweredHALT();
|
||||
}
|
||||
|
||||
protected virtual void OnRaisingHALT() => RaisingHALT?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnRaisedHALT() => RaisedHALT?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnRaisingHALT() => this.RaisingHALT?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweringHALT() => LoweringHALT?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnLoweredHALT() => LoweredHALT?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnRaisedHALT() => this.RaisedHALT?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweringHALT() => this.LoweringHALT?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweredHALT() => this.LoweredHALT?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected override void HandleRESET()
|
||||
{
|
||||
base.HandleRESET();
|
||||
PC = 0;
|
||||
this.PC = 0;
|
||||
}
|
||||
|
||||
protected sealed override void Push(byte value) => Bus.Write(--SP, value);
|
||||
protected sealed override byte Pop() => Bus.Read(SP++);
|
||||
protected sealed override void Push(byte value) => this.Bus.Write(--this.SP, value);
|
||||
|
||||
protected sealed override byte Pop() => this.Bus.Read(this.SP++);
|
||||
|
||||
protected sealed override ushort GetWord()
|
||||
{
|
||||
var returned = base.GetWord();
|
||||
MEMPTR = Bus.Address;
|
||||
return returned;
|
||||
this.MEMPTR = this.Bus.Address;
|
||||
return returned;
|
||||
}
|
||||
|
||||
protected sealed override void SetWord(ushort value)
|
||||
{
|
||||
base.SetWord(value);
|
||||
MEMPTR = Bus.Address;
|
||||
this.MEMPTR = this.Bus.Address;
|
||||
}
|
||||
|
||||
//
|
||||
////
|
||||
|
||||
protected void Restart(byte address)
|
||||
{
|
||||
MEMPTR = address;
|
||||
Call(MEMPTR);
|
||||
this.MEMPTR = address;
|
||||
this.Call(this.MEMPTR);
|
||||
}
|
||||
|
||||
protected bool CallConditional(bool condition)
|
||||
{
|
||||
MEMPTR = FetchWord();
|
||||
this.MEMPTR = this.FetchWord();
|
||||
if (condition)
|
||||
Call(MEMPTR);
|
||||
{
|
||||
this.Call(this.MEMPTR);
|
||||
}
|
||||
|
||||
return condition;
|
||||
}
|
||||
|
||||
protected bool JumpConditional(bool condition)
|
||||
{
|
||||
MEMPTR = FetchWord();
|
||||
this.MEMPTR = this.FetchWord();
|
||||
if (condition)
|
||||
Jump(MEMPTR);
|
||||
{
|
||||
this.Jump(this.MEMPTR);
|
||||
}
|
||||
|
||||
return condition;
|
||||
}
|
||||
|
||||
protected bool ReturnConditional(bool condition)
|
||||
{
|
||||
if (condition)
|
||||
Return();
|
||||
{
|
||||
this.Return();
|
||||
}
|
||||
|
||||
return condition;
|
||||
}
|
||||
|
||||
protected void JumpRelative(sbyte offset)
|
||||
{
|
||||
MEMPTR = (ushort)(PC + offset);
|
||||
Jump(MEMPTR);
|
||||
this.MEMPTR = (ushort)(this.PC + offset);
|
||||
this.Jump(this.MEMPTR);
|
||||
}
|
||||
|
||||
protected bool JumpRelativeConditional(bool condition)
|
||||
{
|
||||
var offset = (sbyte)FetchByte();
|
||||
var offset = (sbyte)this.FetchByte();
|
||||
if (condition)
|
||||
JumpRelative(offset);
|
||||
{
|
||||
this.JumpRelative(offset);
|
||||
}
|
||||
|
||||
return condition;
|
||||
}
|
||||
|
||||
protected override sealed void Return()
|
||||
{
|
||||
base.Return();
|
||||
MEMPTR = PC;
|
||||
this.MEMPTR = this.PC;
|
||||
}
|
||||
|
||||
protected void Halt()
|
||||
{
|
||||
--PC;
|
||||
LowerHALT();
|
||||
--this.PC;
|
||||
this.LowerHALT();
|
||||
}
|
||||
|
||||
protected void Proceed()
|
||||
{
|
||||
++PC;
|
||||
RaiseHALT();
|
||||
++this.PC;
|
||||
this.RaiseHALT();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
namespace EightBit
|
||||
// <copyright file="LittleEndianProcessor.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
public abstract class LittleEndianProcessor : Processor
|
||||
{
|
||||
|
@ -9,63 +13,63 @@
|
|||
|
||||
public override ushort PeekWord(ushort address)
|
||||
{
|
||||
var low = Bus.Peek(address);
|
||||
var high = Bus.Peek(++address);
|
||||
return MakeWord(low, high);
|
||||
var low = this.Bus.Peek(address);
|
||||
var high = this.Bus.Peek(++address);
|
||||
return Chip.MakeWord(low, high);
|
||||
}
|
||||
|
||||
public override void PokeWord(ushort address, ushort value)
|
||||
{
|
||||
Bus.Poke(address, LowByte(value));
|
||||
Bus.Poke(++address, HighByte(value));
|
||||
this.Bus.Poke(address, Chip.LowByte(value));
|
||||
this.Bus.Poke(++address, Chip.HighByte(value));
|
||||
}
|
||||
|
||||
protected override ushort FetchWord()
|
||||
{
|
||||
var low = FetchByte();
|
||||
var high = FetchByte();
|
||||
return MakeWord(low, high);
|
||||
var low = this.FetchByte();
|
||||
var high = this.FetchByte();
|
||||
return Chip.MakeWord(low, high);
|
||||
}
|
||||
|
||||
protected override ushort GetWord()
|
||||
{
|
||||
var low = BusRead();
|
||||
++Bus.Address;
|
||||
var high = BusRead();
|
||||
return MakeWord(low, high);
|
||||
var low = this.BusRead();
|
||||
++this.Bus.Address;
|
||||
var high = this.BusRead();
|
||||
return Chip.MakeWord(low, high);
|
||||
}
|
||||
|
||||
protected override ushort GetWordPaged(byte page, byte offset)
|
||||
{
|
||||
var low = BusRead(offset, page);
|
||||
var high = BusRead((byte)(offset + 1), page);
|
||||
return MakeWord(low, high);
|
||||
var low = this.BusRead(offset, page);
|
||||
var high = this.BusRead((byte)(offset + 1), page);
|
||||
return Chip.MakeWord(low, high);
|
||||
}
|
||||
|
||||
protected override ushort PopWord()
|
||||
{
|
||||
var low = Pop();
|
||||
var high = Pop();
|
||||
return MakeWord(low, high);
|
||||
var low = this.Pop();
|
||||
var high = this.Pop();
|
||||
return Chip.MakeWord(low, high);
|
||||
}
|
||||
|
||||
protected override void PushWord(ushort value)
|
||||
{
|
||||
Push(HighByte(value));
|
||||
Push(LowByte(value));
|
||||
this.Push(Chip.HighByte(value));
|
||||
this.Push(Chip.LowByte(value));
|
||||
}
|
||||
|
||||
protected override void SetWord(ushort value)
|
||||
{
|
||||
BusWrite(LowByte(value));
|
||||
++Bus.Address;
|
||||
BusWrite(HighByte(value));
|
||||
this.BusWrite(Chip.LowByte(value));
|
||||
++this.Bus.Address;
|
||||
this.BusWrite(Chip.HighByte(value));
|
||||
}
|
||||
|
||||
protected override void SetWordPaged(byte page, byte offset, ushort value)
|
||||
{
|
||||
BusWrite(offset, page, LowByte(value));
|
||||
BusWrite((byte)(offset + 1), page, HighByte(value));
|
||||
this.BusWrite(offset, page, Chip.LowByte(value));
|
||||
this.BusWrite((byte)(offset + 1), page, Chip.HighByte(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
namespace EightBit
|
||||
{
|
||||
public interface IMapper
|
||||
{
|
||||
MemoryMapping Mapping(ushort address);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,11 @@
|
|||
using System;
|
||||
// <copyright file="Mask.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
|
||||
public enum Mask
|
||||
{
|
||||
None = 0,
|
||||
|
@ -20,6 +24,6 @@ namespace EightBit
|
|||
Mask13 = Bits.Bit13 - 1,
|
||||
Mask14 = Bits.Bit14 - 1,
|
||||
Mask15 = Bits.Bit15 - 1,
|
||||
Mask16 = Bits.Bit16 - 1
|
||||
Mask16 = Bits.Bit16 - 1,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
namespace EightBit
|
||||
// <copyright file="Memory.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
|
@ -18,7 +22,9 @@
|
|||
}
|
||||
|
||||
public abstract int Load(FileStream file, int writeOffset = 0, int readOffset = 0, int limit = -1);
|
||||
|
||||
public abstract int Load(string path, int writeOffset = 0, int readOffset = 0, int limit = -1);
|
||||
|
||||
public abstract int Load(byte[] from, int writeOffset = 0, int readOffset = 0, int limit = -1);
|
||||
|
||||
protected abstract void Poke(ushort address, byte value);
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
namespace EightBit
|
||||
// <copyright file="MemoryMapping.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
public class MemoryMapping
|
||||
{
|
||||
|
@ -15,9 +19,12 @@
|
|||
this.access = access;
|
||||
}
|
||||
|
||||
public Memory Memory { get => memory; set => memory = value; }
|
||||
public ushort Begin { get => begin; set => begin = value; }
|
||||
public ushort Mask { get => mask; set => mask = value; }
|
||||
public AccessLevel Access { get => access; set => access = value; }
|
||||
public Memory Memory { get => this.memory; set => this.memory = value; }
|
||||
|
||||
public ushort Begin { get => this.begin; set => this.begin = value; }
|
||||
|
||||
public ushort Mask { get => this.mask; set => this.mask = value; }
|
||||
|
||||
public AccessLevel Access { get => this.access; set => this.access = value; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
namespace EightBit
|
||||
// <copyright file="PinLevel.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
public enum PinLevel
|
||||
{
|
||||
Low, High
|
||||
Low,
|
||||
High,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
namespace EightBit
|
||||
// <copyright file="PinLevelExtensions.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
public static class PinLevelExtensions
|
||||
{
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
using System;
|
||||
// <copyright file="PortEventArgs.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
|
||||
public sealed class PortEventArgs : EventArgs
|
||||
{
|
||||
private byte port;
|
||||
|
||||
public PortEventArgs(byte value) => port = value;
|
||||
public PortEventArgs(byte value) => this.port = value;
|
||||
|
||||
public byte Port => port;
|
||||
public byte Port => this.port;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
namespace EightBit
|
||||
// <copyright file="Processor.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
|
||||
|
@ -13,161 +17,176 @@
|
|||
|
||||
protected Processor(Bus memory)
|
||||
{
|
||||
bus = memory;
|
||||
this.bus = memory;
|
||||
}
|
||||
|
||||
public event EventHandler<EventArgs> RaisingRESET;
|
||||
|
||||
public event EventHandler<EventArgs> RaisedRESET;
|
||||
|
||||
public event EventHandler<EventArgs> LoweringRESET;
|
||||
|
||||
public event EventHandler<EventArgs> LoweredRESET;
|
||||
|
||||
public event EventHandler<EventArgs> RaisingINT;
|
||||
|
||||
public event EventHandler<EventArgs> RaisedINT;
|
||||
|
||||
public event EventHandler<EventArgs> LoweringINT;
|
||||
|
||||
public event EventHandler<EventArgs> LoweredINT;
|
||||
|
||||
public ushort PC { get => pc; set => pc = value; }
|
||||
protected byte OpCode { get => opcode; set => opcode = value; }
|
||||
public Bus Bus { get => bus; }
|
||||
public ushort PC { get => this.pc; set => this.pc = value; }
|
||||
|
||||
public ref PinLevel RESET() => ref resetLine;
|
||||
public ref PinLevel INT() => ref intLine;
|
||||
public Bus Bus { get => this.bus; }
|
||||
|
||||
protected byte OpCode { get => this.opcode; set => this.opcode = value; }
|
||||
|
||||
public ref PinLevel RESET() => ref this.resetLine;
|
||||
|
||||
public ref PinLevel INT() => ref this.intLine;
|
||||
|
||||
public abstract int Step();
|
||||
|
||||
public abstract int Execute();
|
||||
|
||||
public int Run(int limit)
|
||||
{
|
||||
int current = 0;
|
||||
while (Powered && (current < limit))
|
||||
current += Step();
|
||||
while (this.Powered && (current < limit))
|
||||
{
|
||||
current += this.Step();
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
public int Execute(byte value)
|
||||
{
|
||||
OpCode = value;
|
||||
return Execute();
|
||||
this.OpCode = value;
|
||||
return this.Execute();
|
||||
}
|
||||
|
||||
public abstract ushort PeekWord(ushort address);
|
||||
|
||||
public abstract void PokeWord(ushort address, ushort value);
|
||||
|
||||
public ushort PeekWord(byte low, byte high) => PeekWord((ushort)(PromoteByte(high) | low));
|
||||
public ushort PeekWord(byte low, byte high) => this.PeekWord((ushort)(Chip.PromoteByte(high) | low));
|
||||
|
||||
public virtual void RaiseRESET()
|
||||
{
|
||||
OnRaisingRESET();
|
||||
RESET().Raise();
|
||||
OnRaisedRESET();
|
||||
this.OnRaisingRESET();
|
||||
this.RESET().Raise();
|
||||
this.OnRaisedRESET();
|
||||
}
|
||||
|
||||
public virtual void LowerRESET()
|
||||
{
|
||||
OnLoweringRESET();
|
||||
RESET().Lower();
|
||||
OnLoweredRESET();
|
||||
this.OnLoweringRESET();
|
||||
this.RESET().Lower();
|
||||
this.OnLoweredRESET();
|
||||
}
|
||||
|
||||
public virtual void RaiseINT()
|
||||
{
|
||||
OnRaisingINT();
|
||||
INT().Raise();
|
||||
OnRaisedINT();
|
||||
this.OnRaisingINT();
|
||||
this.INT().Raise();
|
||||
this.OnRaisedINT();
|
||||
}
|
||||
|
||||
public virtual void LowerINT()
|
||||
{
|
||||
OnLoweringINT();
|
||||
INT().Lower();
|
||||
OnLoweredINT();
|
||||
this.OnLoweringINT();
|
||||
this.INT().Lower();
|
||||
this.OnLoweredINT();
|
||||
}
|
||||
|
||||
protected virtual void OnRaisingRESET() => RaisingRESET?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnRaisedRESET() => RaisedRESET?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnRaisingRESET() => this.RaisingRESET?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweringRESET() => LoweringRESET?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnLoweredRESET() => LoweredRESET?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnRaisedRESET() => this.RaisedRESET?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnRaisingINT() => RaisingINT?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnRaisedINT() => RaisedINT?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnLoweringRESET() => this.LoweringRESET?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweringINT() => LoweringINT?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnLoweredINT() => LoweredINT?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnLoweredRESET() => this.LoweredRESET?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void HandleRESET() => RaiseRESET();
|
||||
protected virtual void HandleINT() => RaiseINT();
|
||||
protected virtual void OnRaisingINT() => this.RaisingINT?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
#region BusWrite
|
||||
protected virtual void OnRaisedINT() => this.RaisedINT?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected void BusWrite(byte low, byte high, byte data) => BusWrite(MakeWord(low, high), data);
|
||||
protected virtual void OnLoweringINT() => this.LoweringINT?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweredINT() => this.LoweredINT?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void HandleRESET() => this.RaiseRESET();
|
||||
|
||||
protected virtual void HandleINT() => this.RaiseINT();
|
||||
|
||||
protected void BusWrite(byte low, byte high, byte data) => this.BusWrite(Chip.MakeWord(low, high), data);
|
||||
|
||||
protected void BusWrite(ushort address, byte data)
|
||||
{
|
||||
Bus.Address = address;
|
||||
BusWrite(data);
|
||||
this.Bus.Address = address;
|
||||
this.BusWrite(data);
|
||||
}
|
||||
|
||||
protected void BusWrite(byte data)
|
||||
{
|
||||
Bus.Data = data;
|
||||
BusWrite();
|
||||
this.Bus.Data = data;
|
||||
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.
|
||||
|
||||
#endregion
|
||||
|
||||
#region BusRead
|
||||
|
||||
protected byte BusRead(byte low, byte high) => BusRead(MakeWord(low, high));
|
||||
protected byte BusRead(byte low, byte high) => this.BusRead(Chip.MakeWord(low, high));
|
||||
|
||||
protected byte BusRead(ushort address)
|
||||
{
|
||||
Bus.Address = address;
|
||||
return BusRead();
|
||||
this.Bus.Address = address;
|
||||
return 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.
|
||||
|
||||
#endregion
|
||||
|
||||
protected byte FetchByte() => BusRead(PC++);
|
||||
protected byte FetchByte() => this.BusRead(this.PC++);
|
||||
|
||||
protected abstract ushort GetWord();
|
||||
protected abstract void SetWord(ushort value);
|
||||
|
||||
protected abstract ushort GetWordPaged(byte page, byte offset);
|
||||
protected abstract void SetWordPaged(byte page, byte offset, ushort value);
|
||||
protected abstract void SetWord(ushort value);
|
||||
|
||||
protected abstract ushort FetchWord();
|
||||
protected abstract ushort GetWordPaged(byte page, byte offset);
|
||||
|
||||
protected abstract void Push(byte value);
|
||||
protected abstract byte Pop();
|
||||
protected abstract void SetWordPaged(byte page, byte offset, ushort value);
|
||||
|
||||
protected abstract void PushWord(ushort value);
|
||||
protected abstract ushort PopWord();
|
||||
protected abstract ushort FetchWord();
|
||||
|
||||
protected abstract void Push(byte value);
|
||||
|
||||
protected abstract byte Pop();
|
||||
|
||||
protected abstract void PushWord(ushort value);
|
||||
|
||||
protected abstract ushort PopWord();
|
||||
|
||||
protected ushort GetWord(ushort address)
|
||||
{
|
||||
Bus.Address = address;
|
||||
return GetWord();
|
||||
this.Bus.Address = address;
|
||||
return this.GetWord();
|
||||
}
|
||||
|
||||
protected void SetWord(ushort address, ushort value)
|
||||
{
|
||||
Bus.Address = address;
|
||||
SetWord(value);
|
||||
this.Bus.Address = address;
|
||||
this.SetWord(value);
|
||||
}
|
||||
|
||||
protected void Jump(ushort destination) => PC = destination;
|
||||
protected void Jump(ushort destination) => this.PC = destination;
|
||||
|
||||
protected void Call(ushort destination)
|
||||
{
|
||||
PushWord(PC);
|
||||
Jump(destination);
|
||||
this.PushWord(this.PC);
|
||||
this.Jump(destination);
|
||||
}
|
||||
|
||||
protected virtual void Return() => Jump(PopWord());
|
||||
protected virtual void Return() => this.Jump(this.PopWord());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
// <copyright file="AssemblyInfo.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
|
@ -8,9 +11,9 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTitle("EightBit")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyCompany("Adrian Conlon")]
|
||||
[assembly: AssemblyProduct("EightBit")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2019")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2019")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
namespace EightBit
|
||||
// <copyright file="Ram.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
public class Ram : Rom
|
||||
{
|
||||
|
@ -7,14 +11,8 @@
|
|||
{
|
||||
}
|
||||
|
||||
public override sealed ref byte Reference(ushort address)
|
||||
{
|
||||
return ref Bytes()[address];
|
||||
}
|
||||
public override sealed 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
namespace EightBit
|
||||
// <copyright file="Rom.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
|
@ -7,23 +11,28 @@
|
|||
{
|
||||
private byte[] bytes;
|
||||
|
||||
public Rom(int size) => bytes = new byte[size];
|
||||
public Rom(int size) => this.bytes = new byte[size];
|
||||
|
||||
public Rom() : this(0) { }
|
||||
public Rom()
|
||||
: this(0)
|
||||
{
|
||||
}
|
||||
|
||||
public override int Size => bytes.Length;
|
||||
public override int Size => this.bytes.Length;
|
||||
|
||||
protected ref byte[] Bytes() => ref bytes;
|
||||
|
||||
static public int Load(FileStream file, ref byte[] output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1)
|
||||
public static int Load(FileStream file, ref byte[] output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1)
|
||||
{
|
||||
var size = (int)file.Length;
|
||||
|
||||
if ((maximumSize > 0) && ((size - readOffset) > maximumSize))
|
||||
{
|
||||
throw new InvalidOperationException("File is too large");
|
||||
}
|
||||
|
||||
if ((limit < 0) || (limit > size))
|
||||
{
|
||||
limit = (int)size;
|
||||
}
|
||||
|
||||
var extent = limit + writeOffset;
|
||||
if (output.Length < extent)
|
||||
|
@ -52,36 +61,40 @@
|
|||
|
||||
public override int Load(FileStream file, int writeOffset = 0, int readOffset = 0, int limit = -1)
|
||||
{
|
||||
var maximumSize = Size - writeOffset;
|
||||
return Load(file, ref Bytes(), writeOffset, readOffset, limit, maximumSize);
|
||||
var maximumSize = this.Size - writeOffset;
|
||||
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)
|
||||
{
|
||||
var maximumSize = Size - writeOffset;
|
||||
return Load(path, ref Bytes(), writeOffset, readOffset, limit, maximumSize);
|
||||
var maximumSize = this.Size - writeOffset;
|
||||
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)
|
||||
{
|
||||
if (limit < 0)
|
||||
limit = Size - readOffset;
|
||||
|
||||
var extent = limit + writeOffset;
|
||||
if (Size < extent)
|
||||
{
|
||||
var updated = new byte[extent];
|
||||
Array.Copy(Bytes(), updated, Size);
|
||||
Bytes() = updated;
|
||||
limit = this.Size - readOffset;
|
||||
}
|
||||
|
||||
Array.Copy(from, readOffset, Bytes(), writeOffset, limit);
|
||||
var extent = limit + writeOffset;
|
||||
if (this.Size < extent)
|
||||
{
|
||||
var updated = new byte[extent];
|
||||
Array.Copy(this.Bytes(), updated, this.Size);
|
||||
this.Bytes() = updated;
|
||||
}
|
||||
|
||||
Array.Copy(from, readOffset, this.Bytes(), writeOffset, limit);
|
||||
|
||||
return limit;
|
||||
}
|
||||
|
||||
public override byte Peek(ushort address) => Bytes()[address];
|
||||
public override byte Peek(ushort address) => this.Bytes()[address];
|
||||
|
||||
protected override void Poke(ushort address, byte value) => Bytes()[address] = value;
|
||||
protected ref byte[] Bytes() => ref this.bytes;
|
||||
|
||||
protected override void Poke(ushort address, byte value) => this.Bytes()[address] = value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,219 @@
|
|||
<StyleCopSettings Version="105">
|
||||
<Analyzers>
|
||||
<Analyzer AnalyzerId="StyleCop.CSharp.DocumentationRules">
|
||||
<Rules>
|
||||
<Rule Name="ElementsMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PartialElementsMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="EnumerationItemsMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationMustContainValidXml">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustHaveSummary">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PartialElementDocumentationMustHaveSummary">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustHaveSummaryText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PartialElementDocumentationMustHaveSummaryText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustNotHaveDefaultSummary">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParametersMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParameterDocumentationMustMatchElementParameters">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParameterDocumentationMustDeclareParameterName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParameterDocumentationMustHaveText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementReturnValueMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementReturnValueDocumentationMustHaveText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="VoidReturnValueMustNotBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParametersMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParametersMustBeDocumentedPartialClass">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParameterDocumentationMustMatchTypeParameters">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParameterDocumentationMustDeclareParameterName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParameterDocumentationMustHaveText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PropertySummaryDocumentationMustMatchAccessors">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PropertySummaryDocumentationMustOmitSetAccessorWithRestrictedAccess">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustNotBeCopiedAndPasted">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="SingleLineCommentsMustNotUseDocumentationStyleSlashes">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationTextMustNotBeEmpty">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationTextMustContainWhitespace">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationMustMeetCharacterPercentage">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ConstructorSummaryDocumentationMustBeginWithStandardText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DestructorSummaryDocumentationMustBeginWithStandardText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationHeadersMustNotContainBlankLines">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="IncludedDocumentationXPathDoesNotExist">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="IncludeNodeDoesNotContainValidFileAndPath">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="InheritDocMustBeUsedWithInheritingClass">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustBeSpelledCorrectly">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileMustHaveHeader">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustShowCopyright">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustHaveCopyrightText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustContainFileName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderFileNameDocumentationMustMatchFileName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustHaveValidCompanyText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderFileNameDocumentationMustMatchTypeName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
</Rules>
|
||||
<AnalyzerSettings />
|
||||
</Analyzer>
|
||||
</Analyzers>
|
||||
</StyleCopSettings>
|
|
@ -1,4 +1,8 @@
|
|||
namespace EightBit
|
||||
// <copyright file="UnusedMemory.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using System.IO;
|
||||
|
||||
|
@ -7,19 +11,22 @@
|
|||
private readonly int size;
|
||||
private readonly byte unchanging;
|
||||
|
||||
UnusedMemory(int size, byte unchanging)
|
||||
public UnusedMemory(int size, byte unchanging)
|
||||
{
|
||||
this.size = size;
|
||||
this.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 System.NotImplementedException();
|
||||
|
||||
public override int Load(string path, int writeOffset = 0, int readOffset = 0, int limit = -1) => throw new System.NotImplementedException();
|
||||
|
||||
public override int Load(byte[] from, int writeOffset = 0, int readOffset = 0, int limit = -1) => throw new System.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 System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="StyleCop.Analyzers" version="1.1.1-beta.61" targetFramework="net472" developmentDependency="true" />
|
||||
<package id="StyleCop.Analyzers.Unstable" version="1.1.1.61" targetFramework="net472" developmentDependency="true" />
|
||||
</packages>
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
// ACTION REQUIRED: This file was automatically added to your project, but it
|
||||
// will not take effect until additional steps are taken to enable it. See the
|
||||
// following page for additional information:
|
||||
//
|
||||
// https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md
|
||||
|
||||
"$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
|
||||
"settings": {
|
||||
"documentationRules": {
|
||||
"documentInterfaces": false,
|
||||
"documentExposedElements": false,
|
||||
"documentInternalElements": false,
|
||||
"documentPrivateElements": false,
|
||||
"documentPrivateFields": false,
|
||||
"companyName": "Adrian Conlon"
|
||||
}
|
||||
}
|
||||
}
|
1156
M6502/Disassembly.cs
1156
M6502/Disassembly.cs
File diff suppressed because it is too large
Load Diff
1118
M6502/M6502.cs
1118
M6502/M6502.cs
File diff suppressed because it is too large
Load Diff
|
@ -12,6 +12,7 @@
|
|||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
<StyleCopTreatErrorsAsWarnings>True</StyleCopTreatErrorsAsWarnings>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -58,5 +59,13 @@
|
|||
<Name>EightBit</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<AdditionalFiles Include="stylecop.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Analyzer Include="..\packages\StyleCop.Analyzers.Unstable.1.1.1.61\analyzers\dotnet\cs\StyleCop.Analyzers.CodeFixes.dll" />
|
||||
<Analyzer Include="..\packages\StyleCop.Analyzers.Unstable.1.1.1.61\analyzers\dotnet\cs\StyleCop.Analyzers.dll" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -1,7 +1,12 @@
|
|||
namespace EightBit
|
||||
// <copyright file="PageCrossingBehavior.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
public enum PageCrossingBehavior
|
||||
{
|
||||
AlwaysReadTwice, MaybeReadTwice
|
||||
AlwaysReadTwice,
|
||||
MaybeReadTwice,
|
||||
}
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
// <copyright file="AssemblyInfo.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
|
|
|
@ -0,0 +1,222 @@
|
|||
<StyleCopSettings Version="105">
|
||||
<GlobalSettings>
|
||||
<StringProperty Name="Culture">en-GB</StringProperty>
|
||||
</GlobalSettings>
|
||||
<Analyzers>
|
||||
<Analyzer AnalyzerId="StyleCop.CSharp.DocumentationRules">
|
||||
<Rules>
|
||||
<Rule Name="ElementsMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PartialElementsMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="EnumerationItemsMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationMustContainValidXml">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustHaveSummary">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PartialElementDocumentationMustHaveSummary">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustHaveSummaryText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PartialElementDocumentationMustHaveSummaryText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustNotHaveDefaultSummary">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParametersMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParameterDocumentationMustMatchElementParameters">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParameterDocumentationMustDeclareParameterName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementParameterDocumentationMustHaveText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementReturnValueMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementReturnValueDocumentationMustHaveText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="VoidReturnValueMustNotBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParametersMustBeDocumented">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParametersMustBeDocumentedPartialClass">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParameterDocumentationMustMatchTypeParameters">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParameterDocumentationMustDeclareParameterName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="GenericTypeParameterDocumentationMustHaveText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PropertySummaryDocumentationMustMatchAccessors">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="PropertySummaryDocumentationMustOmitSetAccessorWithRestrictedAccess">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustNotBeCopiedAndPasted">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="SingleLineCommentsMustNotUseDocumentationStyleSlashes">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationTextMustNotBeEmpty">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationTextMustContainWhitespace">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationMustMeetCharacterPercentage">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ConstructorSummaryDocumentationMustBeginWithStandardText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DestructorSummaryDocumentationMustBeginWithStandardText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationHeadersMustNotContainBlankLines">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="IncludedDocumentationXPathDoesNotExist">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="IncludeNodeDoesNotContainValidFileAndPath">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="InheritDocMustBeUsedWithInheritingClass">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="ElementDocumentationMustBeSpelledCorrectly">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileMustHaveHeader">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustShowCopyright">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustHaveCopyrightText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustContainFileName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderFileNameDocumentationMustMatchFileName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderMustHaveValidCompanyText">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderFileNameDocumentationMustMatchTypeName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
</Rules>
|
||||
<AnalyzerSettings />
|
||||
</Analyzer>
|
||||
</Analyzers>
|
||||
</StyleCopSettings>
|
|
@ -1,4 +1,8 @@
|
|||
namespace EightBit
|
||||
// <copyright file="StatusBits.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
namespace EightBit
|
||||
// <copyright file="Symbols.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -12,45 +16,51 @@
|
|||
private readonly Dictionary<string, ushort> addresses;
|
||||
private readonly Dictionary<string, Dictionary<string, Dictionary<string, string>>> parsed;
|
||||
|
||||
public Symbols() : this("") { }
|
||||
public Symbols()
|
||||
: this(string.Empty)
|
||||
{
|
||||
}
|
||||
|
||||
public Symbols(string path)
|
||||
{
|
||||
labels = new Dictionary<ushort, string>();
|
||||
constants = new Dictionary<ushort, string>();
|
||||
scopes = new Dictionary<string, ushort>();
|
||||
addresses = new Dictionary<string, ushort>();
|
||||
parsed = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();
|
||||
this.labels = new Dictionary<ushort, string>();
|
||||
this.constants = new Dictionary<ushort, string>();
|
||||
this.scopes = new Dictionary<string, ushort>();
|
||||
this.addresses = new Dictionary<string, ushort>();
|
||||
this.parsed = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();
|
||||
|
||||
if (path.Length > 0)
|
||||
{
|
||||
Parse(path);
|
||||
AssignSymbols();
|
||||
AssignScopes();
|
||||
this.Parse(path);
|
||||
this.AssignSymbols();
|
||||
this.AssignScopes();
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<ushort, string> Labels => labels;
|
||||
public Dictionary<ushort, string> Constants => constants;
|
||||
public Dictionary<string, ushort> Scopes => scopes;
|
||||
public Dictionary<string, ushort> Addresses => addresses;
|
||||
public Dictionary<ushort, string> Labels => this.labels;
|
||||
|
||||
public Dictionary<ushort, string> Constants => this.constants;
|
||||
|
||||
public Dictionary<string, ushort> Scopes => this.scopes;
|
||||
|
||||
public Dictionary<string, ushort> Addresses => this.addresses;
|
||||
|
||||
private void AssignScopes()
|
||||
{
|
||||
var parsedScopes = parsed["scope"];
|
||||
var parsedScopes = this.parsed["scope"];
|
||||
foreach (var parsedScopeElement in parsedScopes)
|
||||
{
|
||||
var parsedScope = parsedScopeElement.Value;
|
||||
var name = parsedScope["name"];
|
||||
var trimmedName = name.Substring(1, name.Length - 2);
|
||||
var size = parsedScope["size"];
|
||||
scopes[trimmedName] = ushort.Parse(size);
|
||||
this.scopes[trimmedName] = ushort.Parse(size);
|
||||
}
|
||||
}
|
||||
|
||||
private void AssignSymbols()
|
||||
{
|
||||
var symbols = parsed["sym"];
|
||||
var symbols = this.parsed["sym"];
|
||||
foreach (var symbolElement in symbols)
|
||||
{
|
||||
var symbol = symbolElement.Value;
|
||||
|
@ -61,12 +71,12 @@
|
|||
var symbolType = symbol["type"];
|
||||
if (symbolType == "lab")
|
||||
{
|
||||
labels[number] = trimmedName;
|
||||
addresses[trimmedName] = number;
|
||||
this.labels[number] = trimmedName;
|
||||
this.addresses[trimmedName] = number;
|
||||
}
|
||||
else if (symbolType == "equ")
|
||||
{
|
||||
constants[number] = trimmedName;
|
||||
this.constants[number] = trimmedName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,16 +98,21 @@
|
|||
{
|
||||
var definition = dataElement.Split('=');
|
||||
if (definition.Length == 2)
|
||||
{
|
||||
data[definition[0]] = definition[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (data.ContainsKey("id"))
|
||||
{
|
||||
if (!parsed.ContainsKey(type))
|
||||
parsed[type] = new Dictionary<string, Dictionary<string, string>>();
|
||||
if (!this.parsed.ContainsKey(type))
|
||||
{
|
||||
this.parsed[type] = new Dictionary<string, Dictionary<string, string>>();
|
||||
}
|
||||
|
||||
var id = data["id"];
|
||||
data.Remove("id");
|
||||
parsed[type][id] = data;
|
||||
this.parsed[type][id] = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="StyleCop.Analyzers" version="1.1.1-beta.61" targetFramework="net472" developmentDependency="true" />
|
||||
<package id="StyleCop.Analyzers.Unstable" version="1.1.1.61" targetFramework="net472" developmentDependency="true" />
|
||||
</packages>
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
// ACTION REQUIRED: This file was automatically added to your project, but it
|
||||
// will not take effect until additional steps are taken to enable it. See the
|
||||
// following page for additional information:
|
||||
//
|
||||
// https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md
|
||||
|
||||
"$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
|
||||
"settings": {
|
||||
"documentationRules": {
|
||||
"documentInterfaces": false,
|
||||
"documentExposedElements": false,
|
||||
"documentInternalElements": false,
|
||||
"documentPrivateElements": false,
|
||||
"documentPrivateFields": false,
|
||||
"companyName": "Adrian Conlon"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,11 @@
|
|||
namespace Test
|
||||
// <copyright file="Board.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace Test
|
||||
{
|
||||
using EightBit;
|
||||
using System.Text;
|
||||
using EightBit;
|
||||
|
||||
internal class Board : Bus
|
||||
{
|
||||
|
@ -24,52 +28,59 @@
|
|||
this.oldPC = (ushort)Mask.Mask16;
|
||||
}
|
||||
|
||||
public M6502 CPU { get { return this.cpu; } }
|
||||
public M6502 CPU { get => this.cpu; }
|
||||
|
||||
public override void RaisePOWER()
|
||||
{
|
||||
base.RaisePOWER();
|
||||
CPU.RaisePOWER();
|
||||
CPU.RaiseRESET();
|
||||
CPU.RaiseINT();
|
||||
CPU.RaiseNMI();
|
||||
CPU.RaiseSO();
|
||||
CPU.RaiseRDY();
|
||||
this.CPU.RaisePOWER();
|
||||
this.CPU.RaiseRESET();
|
||||
this.CPU.RaiseINT();
|
||||
this.CPU.RaiseNMI();
|
||||
this.CPU.RaiseSO();
|
||||
this.CPU.RaiseRDY();
|
||||
}
|
||||
|
||||
public override void LowerPOWER()
|
||||
{
|
||||
CPU.LowerPOWER();
|
||||
this.CPU.LowerPOWER();
|
||||
base.LowerPOWER();
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
var programFilename = configuration.Program;
|
||||
var programPath = configuration.RomDirectory + "/" + configuration.Program;
|
||||
var loadAddress = configuration.LoadAddress;
|
||||
ram.Load(programPath, loadAddress);
|
||||
var programFilename = this.configuration.Program;
|
||||
var programPath = this.configuration.RomDirectory + "/" + this.configuration.Program;
|
||||
var loadAddress = this.configuration.LoadAddress;
|
||||
this.ram.Load(programPath, loadAddress);
|
||||
|
||||
if (configuration.DebugMode)
|
||||
CPU.ExecutingInstruction += CPU_ExecutingInstruction;
|
||||
if (this.configuration.DebugMode)
|
||||
{
|
||||
this.CPU.ExecutingInstruction += this.CPU_ExecutingInstruction;
|
||||
}
|
||||
|
||||
CPU.ExecutedInstruction += CPU_ExecutedInstruction;
|
||||
this.CPU.ExecutedInstruction += this.CPU_ExecutedInstruction;
|
||||
|
||||
Poke(0x00, 0x4c);
|
||||
cpu.PokeWord(0x01, configuration.StartAddress);
|
||||
this.Poke(0x00, 0x4c);
|
||||
this.cpu.PokeWord(0x01, this.configuration.StartAddress);
|
||||
}
|
||||
|
||||
public override MemoryMapping Mapping(ushort absolute)
|
||||
{
|
||||
return new MemoryMapping(this.ram, 0x0000, (ushort)Mask.Mask16, AccessLevel.ReadWrite);
|
||||
}
|
||||
|
||||
private void CPU_ExecutedInstruction(object sender, System.EventArgs e)
|
||||
{
|
||||
var pc = CPU.PC;
|
||||
if (oldPC != pc)
|
||||
var pc = this.CPU.PC;
|
||||
if (this.oldPC != pc)
|
||||
{
|
||||
oldPC = pc;
|
||||
this.oldPC = pc;
|
||||
}
|
||||
else
|
||||
{
|
||||
LowerPOWER();
|
||||
var test = Peek(0x0200);
|
||||
this.LowerPOWER();
|
||||
var test = this.Peek(0x0200);
|
||||
System.Console.Out.WriteLine();
|
||||
System.Console.Out.Write("** Test=");
|
||||
System.Console.Out.WriteLine(Disassembly.Dump_ByteValue(test));
|
||||
|
@ -78,8 +89,8 @@
|
|||
|
||||
private void CPU_ExecutingInstruction(object sender, System.EventArgs e)
|
||||
{
|
||||
var address = CPU.PC;
|
||||
var cell = Peek(address);
|
||||
var address = this.CPU.PC;
|
||||
var cell = this.Peek(address);
|
||||
|
||||
var output = new StringBuilder();
|
||||
|
||||
|
@ -88,33 +99,28 @@
|
|||
output.Append(":");
|
||||
|
||||
output.Append("P=");
|
||||
output.Append(Disassembly.Dump_Flags(CPU.P));
|
||||
output.Append(Disassembly.Dump_Flags(this.CPU.P));
|
||||
output.Append(", ");
|
||||
|
||||
output.Append("A=");
|
||||
output.Append(Disassembly.Dump_ByteValue(CPU.A));
|
||||
output.Append(Disassembly.Dump_ByteValue(this.CPU.A));
|
||||
output.Append(", ");
|
||||
|
||||
output.Append("X=");
|
||||
output.Append(Disassembly.Dump_ByteValue(CPU.X));
|
||||
output.Append(Disassembly.Dump_ByteValue(this.CPU.X));
|
||||
output.Append(", ");
|
||||
|
||||
output.Append("Y=");
|
||||
output.Append(Disassembly.Dump_ByteValue(CPU.Y));
|
||||
output.Append(Disassembly.Dump_ByteValue(this.CPU.Y));
|
||||
output.Append(", ");
|
||||
|
||||
output.Append("S=");
|
||||
output.Append(Disassembly.Dump_ByteValue(CPU.S));
|
||||
output.Append(Disassembly.Dump_ByteValue(this.CPU.S));
|
||||
output.Append("\t");
|
||||
|
||||
output.Append(disassembler.Disassemble(address));
|
||||
output.Append(this.disassembler.Disassemble(address));
|
||||
|
||||
System.Console.Out.WriteLine(output.ToString());
|
||||
}
|
||||
|
||||
public override MemoryMapping Mapping(ushort absolute)
|
||||
{
|
||||
return new MemoryMapping(ram, 0x0000, (ushort)Mask.Mask16, AccessLevel.ReadWrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,35 @@
|
|||
namespace Test
|
||||
// <copyright file="Configuration.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace Test
|
||||
{
|
||||
using EightBit;
|
||||
|
||||
internal class Configuration
|
||||
{
|
||||
private bool debugMode = false;
|
||||
private readonly ushort loadAddress = 0x400;
|
||||
private readonly ushort startAddress = 0x400;
|
||||
private readonly string romDirectory = "roms";
|
||||
private readonly string program = "6502_functional_test.bin";
|
||||
private bool debugMode = false;
|
||||
|
||||
public Configuration() {}
|
||||
|
||||
public bool DebugMode {
|
||||
get { return debugMode; }
|
||||
set { debugMode = value; }
|
||||
public Configuration()
|
||||
{
|
||||
}
|
||||
|
||||
public ushort LoadAddress { get { return loadAddress; } }
|
||||
public ushort StartAddress { get { return startAddress; } }
|
||||
public bool DebugMode
|
||||
{
|
||||
get => this.debugMode;
|
||||
set => this.debugMode = value;
|
||||
}
|
||||
|
||||
public string RomDirectory { get { return romDirectory; } }
|
||||
public string Program { get { return program; } }
|
||||
public ushort LoadAddress { get => this.loadAddress; }
|
||||
|
||||
public ushort StartAddress { get => this.startAddress; }
|
||||
|
||||
public string RomDirectory { get => this.romDirectory; }
|
||||
|
||||
public string Program { get => this.program; }
|
||||
}
|
||||
}
|
|
@ -1,12 +1,16 @@
|
|||
namespace Test
|
||||
// <copyright file="Program.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace Test
|
||||
{
|
||||
class Program
|
||||
public class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var configuration = new Configuration();
|
||||
|
||||
//configuration.DebugMode = true;
|
||||
////configuration.DebugMode = true;
|
||||
|
||||
var harness = new TestHarness(configuration);
|
||||
harness.Run();
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
// <copyright file="AssemblyInfo.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
namespace Test
|
||||
// <copyright file="TestHarness.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace Test
|
||||
{
|
||||
internal class TestHarness
|
||||
{
|
||||
|
@ -6,18 +10,20 @@
|
|||
|
||||
public TestHarness(Configuration configuration)
|
||||
{
|
||||
board = new Board(configuration);
|
||||
this.board = new Board(configuration);
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
board.Initialize();
|
||||
board.RaisePOWER();
|
||||
this.board.Initialize();
|
||||
this.board.RaisePOWER();
|
||||
|
||||
var cpu = board.CPU;
|
||||
var cpu = this.board.CPU;
|
||||
|
||||
while (cpu.Powered)
|
||||
{
|
||||
cpu.Step();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,8 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
<AdditionalFiles Include="stylecop.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\EightBit\EightBit.csproj">
|
||||
|
@ -65,5 +67,9 @@
|
|||
<Name>M6502</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Analyzer Include="..\packages\StyleCop.Analyzers.Unstable.1.1.1.61\analyzers\dotnet\cs\StyleCop.Analyzers.CodeFixes.dll" />
|
||||
<Analyzer Include="..\packages\StyleCop.Analyzers.Unstable.1.1.1.61\analyzers\dotnet\cs\StyleCop.Analyzers.dll" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="StyleCop.Analyzers" version="1.1.1-beta.61" targetFramework="net472" developmentDependency="true" />
|
||||
<package id="StyleCop.Analyzers.Unstable" version="1.1.1.61" targetFramework="net472" developmentDependency="true" />
|
||||
</packages>
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
// ACTION REQUIRED: This file was automatically added to your project, but it
|
||||
// will not take effect until additional steps are taken to enable it. See the
|
||||
// following page for additional information:
|
||||
//
|
||||
// https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md
|
||||
|
||||
"$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
|
||||
"settings": {
|
||||
"documentationRules": {
|
||||
"documentInterfaces": false,
|
||||
"documentExposedElements": false,
|
||||
"documentInternalElements": false,
|
||||
"documentPrivateElements": false,
|
||||
"documentPrivateFields": false,
|
||||
"companyName": "Adrian Conlon"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +1,15 @@
|
|||
namespace UnitTestEightBit
|
||||
// <copyright file="ChipUnitTest.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace UnitTestEightBit
|
||||
{
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using EightBit;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
public class ChipUnitTest
|
||||
{
|
||||
#region LowByte
|
||||
|
||||
[TestMethod]
|
||||
public void TestLowByte()
|
||||
{
|
||||
|
@ -16,10 +18,6 @@
|
|||
Assert.AreEqual(0xf, low);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region HighByte
|
||||
|
||||
[TestMethod]
|
||||
public void TestHighByte()
|
||||
{
|
||||
|
@ -28,10 +26,6 @@
|
|||
Assert.AreEqual(0xf0, high);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ClearFlag
|
||||
|
||||
[TestMethod]
|
||||
public void TestClearFlag()
|
||||
{
|
||||
|
@ -72,10 +66,6 @@
|
|||
Assert.AreEqual(0x7f, flags);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SetFlag
|
||||
|
||||
[TestMethod]
|
||||
public void TestSetFlag()
|
||||
{
|
||||
|
@ -116,10 +106,6 @@
|
|||
Assert.AreEqual(0xff, flags);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region LowerPart
|
||||
|
||||
[TestMethod]
|
||||
public void TestLowerPart()
|
||||
{
|
||||
|
@ -128,10 +114,6 @@
|
|||
Assert.AreEqual(0xf, lower);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region HigherPart
|
||||
|
||||
[TestMethod]
|
||||
public void TestHigherPart()
|
||||
{
|
||||
|
@ -140,10 +122,6 @@
|
|||
Assert.AreEqual(0xf000, higher);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DemoteByte
|
||||
|
||||
[TestMethod]
|
||||
public void TestDemoteByte()
|
||||
{
|
||||
|
@ -152,10 +130,6 @@
|
|||
Assert.AreEqual(0xf0, demoted);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PromoteByte
|
||||
|
||||
[TestMethod]
|
||||
public void TestPromoteByte()
|
||||
{
|
||||
|
@ -164,10 +138,6 @@
|
|||
Assert.AreEqual(0xf000, promoted);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region LowNibble
|
||||
|
||||
[TestMethod]
|
||||
public void TestLowNibble()
|
||||
{
|
||||
|
@ -176,10 +146,6 @@
|
|||
Assert.AreEqual(0xb, nibble);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region HighNibble
|
||||
|
||||
[TestMethod]
|
||||
public void TestHighNibble()
|
||||
{
|
||||
|
@ -188,10 +154,6 @@
|
|||
Assert.AreEqual(0xa, nibble);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DemoteNibble
|
||||
|
||||
[TestMethod]
|
||||
public void TestDemoteNibble()
|
||||
{
|
||||
|
@ -200,10 +162,6 @@
|
|||
Assert.AreEqual(0xa, nibble);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PromoteNibble
|
||||
|
||||
[TestMethod]
|
||||
public void TestPromoteNibble()
|
||||
{
|
||||
|
@ -212,10 +170,6 @@
|
|||
Assert.AreEqual(0xb0, nibble);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region HigherNibble
|
||||
|
||||
[TestMethod]
|
||||
public void TestHigherNibble()
|
||||
{
|
||||
|
@ -224,10 +178,6 @@
|
|||
Assert.AreEqual(0xa0, nibble);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region LowerNibble
|
||||
|
||||
[TestMethod]
|
||||
public void TestLowerNibble()
|
||||
{
|
||||
|
@ -236,18 +186,11 @@
|
|||
Assert.AreEqual(0xb, nibble);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MakeWord
|
||||
|
||||
[TestMethod]
|
||||
public void TestMakeWord()
|
||||
{
|
||||
ushort word = Chip.MakeWord(0xcd, 0xab);
|
||||
Assert.AreEqual(0xabcd, word);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
// <copyright file="AssemblyInfo.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("UnitTestEightBit")]
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<AdditionalFiles Include="stylecop.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\EightBit\EightBit.csproj">
|
||||
|
@ -63,6 +64,10 @@
|
|||
<Name>EightBit</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Analyzer Include="..\packages\StyleCop.Analyzers.Unstable.1.1.1.61\analyzers\dotnet\cs\StyleCop.Analyzers.CodeFixes.dll" />
|
||||
<Analyzer Include="..\packages\StyleCop.Analyzers.Unstable.1.1.1.61\analyzers\dotnet\cs\StyleCop.Analyzers.dll" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
|
|
|
@ -2,4 +2,6 @@
|
|||
<packages>
|
||||
<package id="MSTest.TestAdapter" version="1.3.2" targetFramework="net472" />
|
||||
<package id="MSTest.TestFramework" version="1.3.2" targetFramework="net472" />
|
||||
<package id="StyleCop.Analyzers" version="1.1.1-beta.61" targetFramework="net472" developmentDependency="true" />
|
||||
<package id="StyleCop.Analyzers.Unstable" version="1.1.1.61" targetFramework="net472" developmentDependency="true" />
|
||||
</packages>
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
// ACTION REQUIRED: This file was automatically added to your project, but it
|
||||
// will not take effect until additional steps are taken to enable it. See the
|
||||
// following page for additional information:
|
||||
//
|
||||
// https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md
|
||||
|
||||
"$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
|
||||
"settings": {
|
||||
"documentationRules": {
|
||||
"documentInterfaces": false,
|
||||
"documentExposedElements": false,
|
||||
"documentInternalElements": false,
|
||||
"documentPrivateElements": false,
|
||||
"documentPrivateFields": false,
|
||||
"companyName": "Adrian Conlon"
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue