mirror of
https://github.com/MoleskiCoder/EightBitNet.git
synced 2026-04-20 21:16:29 +00:00
Drop Register16 support (replaced with explicit ushort), add some unit tests (Chip class only at present)
Now runs some instructions before going wrong... Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
@@ -7,67 +7,65 @@
|
||||
{
|
||||
}
|
||||
|
||||
public override Register16 PeekWord(Register16 address)
|
||||
public override ushort PeekWord(ushort address)
|
||||
{
|
||||
var high = Bus.Peek(address);
|
||||
var low = Bus.Peek(++address);
|
||||
return new Register16(low, high);
|
||||
return MakeWord(low, high);
|
||||
}
|
||||
|
||||
public override void PokeWord(Register16 address, Register16 value)
|
||||
public override void PokeWord(ushort address, ushort value)
|
||||
{
|
||||
Bus.Poke(address, value.High);
|
||||
Bus.Poke(++address, value.Low);
|
||||
Bus.Poke(address, LowByte(value));
|
||||
Bus.Poke(++address, HighByte(value));
|
||||
}
|
||||
|
||||
protected override Register16 FetchWord()
|
||||
protected override ushort FetchWord()
|
||||
{
|
||||
var high = FetchByte();
|
||||
var low = FetchByte();
|
||||
return new Register16(low, high);
|
||||
return MakeWord(low, high);
|
||||
}
|
||||
|
||||
protected override Register16 GetWord()
|
||||
protected override ushort GetWord()
|
||||
{
|
||||
var high = BusRead();
|
||||
++Bus.Address.Word;
|
||||
++Bus.Address;
|
||||
var low = BusRead();
|
||||
return new Register16(low, high);
|
||||
return MakeWord(low, high);
|
||||
}
|
||||
|
||||
protected override Register16 GetWordPaged(byte page, byte offset)
|
||||
protected override ushort GetWordPaged(byte page, byte offset)
|
||||
{
|
||||
var high = GetBytePaged(page, offset);
|
||||
++Bus.Address.Low;
|
||||
var low = BusRead();
|
||||
return new Register16(low, high);
|
||||
var low = GetBytePaged(page, (byte)(offset + 1));
|
||||
return MakeWord(low, high);
|
||||
}
|
||||
|
||||
protected override Register16 PopWord()
|
||||
protected override ushort PopWord()
|
||||
{
|
||||
var high = Pop();
|
||||
var low = Pop();
|
||||
return new Register16(low, high);
|
||||
return MakeWord(low, high);
|
||||
}
|
||||
|
||||
protected override void PushWord(Register16 value)
|
||||
protected override void PushWord(ushort value)
|
||||
{
|
||||
Push(value.Low);
|
||||
Push(value.High);
|
||||
Push(LowByte(value));
|
||||
Push(HighByte(value));
|
||||
}
|
||||
|
||||
protected override void SetWord(Register16 value)
|
||||
protected override void SetWord(ushort value)
|
||||
{
|
||||
BusWrite(value.High);
|
||||
++Bus.Address.Word;
|
||||
BusWrite(value.Low);
|
||||
BusWrite(HighByte(value));
|
||||
++Bus.Address;
|
||||
BusWrite(LowByte(value));
|
||||
}
|
||||
|
||||
protected override void SetWordPaged(byte page, byte offset, Register16 value)
|
||||
protected override void SetWordPaged(byte page, byte offset, ushort value)
|
||||
{
|
||||
SetBytePaged(page, offset, value.High);
|
||||
++Bus.Address.Low;
|
||||
BusWrite(value.Low);
|
||||
SetBytePaged(page, offset, HighByte(value));
|
||||
SetBytePaged(page, (byte)(offset + 1), LowByte(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+24
-19
@@ -5,7 +5,7 @@
|
||||
abstract public class Bus : IMapper
|
||||
{
|
||||
private byte data;
|
||||
private Register16 address = new Register16();
|
||||
private ushort address;
|
||||
|
||||
public event EventHandler<EventArgs> WritingByte;
|
||||
public event EventHandler<EventArgs> WrittenByte;
|
||||
@@ -19,22 +19,21 @@
|
||||
set { data = value; }
|
||||
}
|
||||
|
||||
public Register16 Address
|
||||
public ushort Address
|
||||
{
|
||||
get { return address; }
|
||||
set { address = value; }
|
||||
}
|
||||
|
||||
public abstract MemoryMapping Mapping(Register16 absolute);
|
||||
public abstract MemoryMapping Mapping(ushort absolute);
|
||||
|
||||
public byte Peek() => Reference();
|
||||
public byte Peek(Register16 absolute) => Reference(absolute);
|
||||
public byte Peek(ushort absolute) => Peek(Chip.LowByte(absolute), Chip.HighByte(absolute));
|
||||
public byte Peek(byte low, byte high) => Reference(new Register16(low, high));
|
||||
public byte Peek(ushort absolute) => Reference(absolute);
|
||||
public byte Peek(byte low, byte high) => Reference(low, high);
|
||||
|
||||
public void Poke(byte value) => Reference() = value;
|
||||
public void Poke(Register16 absolute, byte value) => Reference(absolute) = value;
|
||||
public byte Poke(ushort absolute, byte value) => Poke(Chip.LowByte(absolute), Chip.HighByte(absolute), value);
|
||||
public byte Poke(byte low, byte high, byte value) => Reference(new Register16(low, high)) = 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 Read()
|
||||
{
|
||||
@@ -44,12 +43,17 @@
|
||||
return returned;
|
||||
}
|
||||
|
||||
public byte Read(Register16 absolute)
|
||||
public byte Read(ushort absolute)
|
||||
{
|
||||
Address.Word = absolute.Word;
|
||||
Address = absolute;
|
||||
return Read();
|
||||
}
|
||||
|
||||
public byte Read(byte low, byte high)
|
||||
{
|
||||
return Read(Chip.MakeWord(low, high));
|
||||
}
|
||||
|
||||
public void Write()
|
||||
{
|
||||
OnWritingByte();
|
||||
@@ -63,12 +67,17 @@
|
||||
Write();
|
||||
}
|
||||
|
||||
public void Write(Register16 absolute, byte value)
|
||||
public void Write(ushort absolute, byte value)
|
||||
{
|
||||
Address.Word = absolute.Word;
|
||||
Address = absolute;
|
||||
Write(value);
|
||||
}
|
||||
|
||||
public void Write(byte low, byte high, byte value)
|
||||
{
|
||||
Write(Chip.MakeWord(low, high), value);
|
||||
}
|
||||
|
||||
public virtual void RaisePOWER() {}
|
||||
public virtual void LowerPOWER() {}
|
||||
|
||||
@@ -80,7 +89,7 @@
|
||||
protected virtual void OnReadingByte() => ReadingByte?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnReadByte() => ReadByte?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected ref byte Reference(Register16 absolute)
|
||||
protected ref byte Reference(ushort absolute)
|
||||
{
|
||||
var mapped = Mapping(absolute);
|
||||
var offset = (ushort)((absolute - mapped.Begin) & mapped.Mask);
|
||||
@@ -94,13 +103,9 @@
|
||||
|
||||
protected ref byte Reference() => ref Reference(Address);
|
||||
|
||||
protected ref byte Reference(ushort absolute) => ref Reference(Chip.LowByte(absolute), Chip.HighByte(absolute));
|
||||
|
||||
protected ref byte Reference(byte low, byte high)
|
||||
{
|
||||
Address.Low = low;
|
||||
Address.High = high;
|
||||
return ref Reference();
|
||||
return ref Reference(Chip.MakeWord(low, high));
|
||||
}
|
||||
|
||||
//[[nodiscard]] static std::map<uint16_t, std::vector<uint8_t>> parseHexFile(std::string path);
|
||||
|
||||
+12
-10
@@ -17,18 +17,20 @@
|
||||
ClearFlag(ref f, flag);
|
||||
}
|
||||
|
||||
public static void ClearFlag(ref byte f, byte flag, int condition) => ClearFlag(ref f, flag, condition == 0);
|
||||
public static void ClearFlag(ref byte f, byte flag, int condition) => ClearFlag(ref f, flag, condition != 0);
|
||||
|
||||
public static void ClearFlag(ref byte f, byte flag, bool condition) => SetFlag(ref f, flag, !condition);
|
||||
|
||||
public static int HighByte(int value) => LowByte(value >> 8);
|
||||
public static byte HighByte(ushort value) => (byte)LowByte((int)value);
|
||||
public static int LowByte(int value) => value & (int)Mask.Mask8;
|
||||
public static byte LowByte(ushort value) => (byte)LowByte((int)value);
|
||||
public static int PromoteByte(int value) => value << 8;
|
||||
public static ushort PromoteByte(byte value) => (ushort)PromoteByte((int)value);
|
||||
public static int DemoteByte(int value) => HighByte(value);
|
||||
public static byte DemoteByte(ushort value) => (byte)HighByte((int)value);
|
||||
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 int HighNibble(byte value) => value >> 4;
|
||||
public static int LowNibble(byte value) => value & 0xf;
|
||||
@@ -36,7 +38,7 @@
|
||||
public static int HigherNibble(byte value) => value & 0xf0;
|
||||
public static int LowerNibble(byte value) => LowNibble(value);
|
||||
|
||||
public static int PromoteNibble(byte value) => value << 4;
|
||||
public static int PromoteNibble(byte value) => LowByte(value << 4);
|
||||
public static int DemoteNibble(byte value) => HighNibble(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,6 @@
|
||||
<Compile Include="Processor.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Ram.cs" />
|
||||
<Compile Include="Register16.cs" />
|
||||
<Compile Include="Rom.cs" />
|
||||
<Compile Include="UnusedMemory.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
+24
-25
@@ -5,8 +5,8 @@
|
||||
public abstract class IntelProcessor : LittleEndianProcessor
|
||||
{
|
||||
private readonly IntelOpCodeDecoded[] decodedOpCodes;
|
||||
private Register16 sp;
|
||||
private Register16 memptr;
|
||||
private ushort sp;
|
||||
private ushort memptr;
|
||||
|
||||
private PinLevel haltLine;
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
: base(bus)
|
||||
{
|
||||
decodedOpCodes = new IntelOpCodeDecoded[0x100];
|
||||
sp = new Register16((ushort)Mask.Mask16);
|
||||
memptr = new Register16();
|
||||
sp = (ushort)Mask.Mask16;
|
||||
memptr = (ushort)Mask.Mask16;
|
||||
|
||||
for (int i = 0; i < 0x100; ++i)
|
||||
decodedOpCodes[i] = new IntelOpCodeDecoded((byte)i);
|
||||
@@ -30,30 +30,30 @@
|
||||
|
||||
protected bool Halted => HALT().Lowered();
|
||||
|
||||
public Register16 SP { get => sp; set => sp = value; }
|
||||
public Register16 MEMPTR { get => memptr; set => memptr = value; }
|
||||
public ushort SP { get => sp; set => sp = value; }
|
||||
public ushort MEMPTR { get => memptr; set => memptr = value; }
|
||||
|
||||
public abstract Register16 AF { get; set; }
|
||||
public byte A { get { return AF.High; } set { AF.High = value; } }
|
||||
public byte F { get { return AF.Low; } set { AF.Low = value; } }
|
||||
public abstract ushort AF { get; set; }
|
||||
public byte A { get { return HighByte(AF); } set { AF = (ushort)(LowerPart(AF) | PromoteByte(value)); } }
|
||||
public byte F { get { return LowByte(AF); } set { AF = (ushort)(HigherPart(AF) | value); } }
|
||||
|
||||
public abstract Register16 BC { get; set; }
|
||||
public byte B { get { return BC.High; } set { BC.High = value; } }
|
||||
public byte C { get { return BC.Low; } set { BC.Low = value; } }
|
||||
public abstract ushort BC { get; set; }
|
||||
public byte B { get { return HighByte(AF); } set { BC = (ushort)(LowerPart(BC) | PromoteByte(value)); } }
|
||||
public byte C { get { return LowByte(AF); } set { BC = (ushort)(HigherPart(BC) | value); } }
|
||||
|
||||
public abstract Register16 DE { get; set; }
|
||||
public byte D { get { return DE.High; } set { DE.High = value; } }
|
||||
public byte E { get { return DE.Low; } set { DE.Low = value; } }
|
||||
public abstract ushort DE { get; set; }
|
||||
public byte D { get { return HighByte(AF); } set { DE = (ushort)(LowerPart(DE) | PromoteByte(value)); } }
|
||||
public byte E { get { return LowByte(AF); } set { DE = (ushort)(HigherPart(DE) | value); } }
|
||||
|
||||
public abstract Register16 HL { get; set; }
|
||||
public byte H { get { return HL.High; } set { HL.High = value; } }
|
||||
public byte L { get { return HL.Low; } set { HL.Low = value; } }
|
||||
public abstract ushort HL { get; set; }
|
||||
public byte H { get { return HighByte(AF); } set { HL = (ushort)(LowerPart(AF) | PromoteByte(value)); } }
|
||||
public byte L { get { return LowByte(AF); } set { HL = (ushort)(HigherPart(AF) | value); } }
|
||||
|
||||
public override void RaisePOWER()
|
||||
{
|
||||
base.RaisePOWER();
|
||||
RaiseHALT();
|
||||
SP = AF = BC = DE = HL = new Register16((ushort)Mask.Mask16);
|
||||
SP = AF = BC = DE = HL = (ushort)Mask.Mask16;
|
||||
}
|
||||
|
||||
public virtual void RaiseHALT()
|
||||
@@ -79,20 +79,20 @@
|
||||
protected override void HandleRESET()
|
||||
{
|
||||
base.HandleRESET();
|
||||
PC.Word = 0;
|
||||
PC = 0;
|
||||
}
|
||||
|
||||
protected sealed override void Push(byte value) => Bus.Write(--SP, value);
|
||||
protected sealed override byte Pop() => Bus.Read(SP++);
|
||||
|
||||
protected sealed override Register16 GetWord()
|
||||
protected sealed override ushort GetWord()
|
||||
{
|
||||
var returned = base.GetWord();
|
||||
MEMPTR = Bus.Address;
|
||||
return returned;
|
||||
}
|
||||
|
||||
protected sealed override void SetWord(Register16 value)
|
||||
protected sealed override void SetWord(ushort value)
|
||||
{
|
||||
base.SetWord(value);
|
||||
MEMPTR = Bus.Address;
|
||||
@@ -102,8 +102,7 @@
|
||||
|
||||
protected void Restart(byte address)
|
||||
{
|
||||
MEMPTR.Low = address;
|
||||
MEMPTR.High = 0;
|
||||
MEMPTR = address;
|
||||
Call(MEMPTR);
|
||||
}
|
||||
|
||||
@@ -132,7 +131,7 @@
|
||||
|
||||
protected void JumpRelative(sbyte offset)
|
||||
{
|
||||
MEMPTR.Word = (ushort)(PC.Word + offset);
|
||||
MEMPTR = (ushort)(PC + offset);
|
||||
Jump(MEMPTR);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
|
||||
namespace EightBit
|
||||
namespace EightBit
|
||||
{
|
||||
public abstract class LittleEndianProcessor : Processor
|
||||
{
|
||||
@@ -9,75 +7,65 @@ namespace EightBit
|
||||
{
|
||||
}
|
||||
|
||||
public override Register16 PeekWord(Register16 address)
|
||||
public override ushort PeekWord(ushort address)
|
||||
{
|
||||
var low = Bus.Peek(address);
|
||||
var high = Bus.Peek(++address);
|
||||
return new Register16(low, high);
|
||||
return MakeWord(low, high);
|
||||
}
|
||||
|
||||
public override void PokeWord(Register16 address, Register16 value)
|
||||
public override void PokeWord(ushort address, ushort value)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
Bus.Poke(address, value.Low);
|
||||
Bus.Poke(++address, value.High);
|
||||
Bus.Poke(address, LowByte(value));
|
||||
Bus.Poke(++address, HighByte(value));
|
||||
}
|
||||
|
||||
protected override Register16 FetchWord()
|
||||
protected override ushort FetchWord()
|
||||
{
|
||||
var low = FetchByte();
|
||||
var high = FetchByte();
|
||||
return new Register16(low, high);
|
||||
return MakeWord(low, high);
|
||||
}
|
||||
|
||||
protected override Register16 GetWord()
|
||||
protected override ushort GetWord()
|
||||
{
|
||||
var low = BusRead();
|
||||
++Bus.Address.Word;
|
||||
++Bus.Address;
|
||||
var high = BusRead();
|
||||
return new Register16(low, high);
|
||||
return MakeWord(low, high);
|
||||
}
|
||||
|
||||
protected override Register16 GetWordPaged(byte page, byte offset)
|
||||
protected override ushort GetWordPaged(byte page, byte offset)
|
||||
{
|
||||
var low = GetBytePaged(page, offset);
|
||||
++Bus.Address.Low;
|
||||
var high = BusRead();
|
||||
return new Register16(low, high);
|
||||
var high = GetBytePaged(page, (byte)(offset + 1));
|
||||
return MakeWord(low, high);
|
||||
}
|
||||
|
||||
protected override Register16 PopWord()
|
||||
protected override ushort PopWord()
|
||||
{
|
||||
var low = Pop();
|
||||
var high = Pop();
|
||||
return new Register16(low, high);
|
||||
return MakeWord(low, high);
|
||||
}
|
||||
|
||||
protected override void PushWord(Register16 value)
|
||||
protected override void PushWord(ushort value)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
Push(value.High);
|
||||
Push(value.Low);
|
||||
Push(HighByte(value));
|
||||
Push(LowByte(value));
|
||||
}
|
||||
|
||||
protected override void SetWord(Register16 value)
|
||||
protected override void SetWord(ushort value)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
BusWrite(value.Low);
|
||||
++Bus.Address.Word;
|
||||
BusWrite(value.High);
|
||||
BusWrite(LowByte(value));
|
||||
++Bus.Address;
|
||||
BusWrite(HighByte(value));
|
||||
}
|
||||
|
||||
protected override void SetWordPaged(byte page, byte offset, Register16 value)
|
||||
protected override void SetWordPaged(byte page, byte offset, ushort value)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
SetBytePaged(page, offset, value.Low);
|
||||
++Bus.Address.Low;
|
||||
BusWrite(value.High);
|
||||
SetBytePaged(page, offset, LowByte(value));
|
||||
SetBytePaged(page, (byte)(offset + 1), HighByte(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -2,6 +2,6 @@
|
||||
{
|
||||
public interface IMapper
|
||||
{
|
||||
MemoryMapping Mapping(Register16 address);
|
||||
MemoryMapping Mapping(ushort address);
|
||||
}
|
||||
}
|
||||
|
||||
+44
-33
@@ -6,7 +6,7 @@
|
||||
{
|
||||
private Bus bus;
|
||||
private byte opcode;
|
||||
private Register16 pc;
|
||||
private ushort pc;
|
||||
|
||||
private PinLevel resetLine;
|
||||
private PinLevel intLine;
|
||||
@@ -14,7 +14,7 @@
|
||||
protected Processor(Bus memory)
|
||||
{
|
||||
bus = memory;
|
||||
pc = new Register16();
|
||||
pc = 0;
|
||||
}
|
||||
|
||||
public event EventHandler<EventArgs> RaisingRESET;
|
||||
@@ -27,7 +27,7 @@
|
||||
public event EventHandler<EventArgs> LoweringINT;
|
||||
public event EventHandler<EventArgs> LoweredINT;
|
||||
|
||||
public Register16 PC { get => pc; set => pc = value; }
|
||||
public ushort PC { get => pc; set => pc = value; }
|
||||
protected byte OpCode { get => opcode; set => opcode = value; }
|
||||
public Bus Bus { get => bus; set => bus = value; }
|
||||
|
||||
@@ -51,11 +51,10 @@
|
||||
return Execute();
|
||||
}
|
||||
|
||||
public abstract Register16 PeekWord(Register16 address);
|
||||
public abstract void PokeWord(Register16 address, Register16 value);
|
||||
public abstract ushort PeekWord(ushort address);
|
||||
public abstract void PokeWord(ushort address, ushort value);
|
||||
|
||||
public Register16 PeekWord(byte low, byte high) => PeekWord(new Register16(low, high));
|
||||
public Register16 PeekWord(ushort address) => PeekWord(LowByte(address), HighByte(address));
|
||||
public ushort PeekWord(byte low, byte high) => PeekWord((ushort)(PromoteByte(high) | low));
|
||||
|
||||
public virtual void RaiseRESET()
|
||||
{
|
||||
@@ -100,14 +99,16 @@
|
||||
protected virtual void HandleRESET() => RaiseRESET();
|
||||
protected virtual void HandleINT() => RaiseINT();
|
||||
|
||||
protected void BusWrite(byte low, byte data) => BusWrite(low, 0, data);
|
||||
|
||||
protected void BusWrite(Register16 address, byte data) => BusWrite(address.Low, address.High, data);
|
||||
#region BusWrite
|
||||
|
||||
protected void BusWrite(byte low, byte high, byte data)
|
||||
{
|
||||
Bus.Address.Low = low;
|
||||
Bus.Address.High = high;
|
||||
BusWrite(MakeWord(low, high), data);
|
||||
}
|
||||
|
||||
protected void BusWrite(ushort address, byte data)
|
||||
{
|
||||
Bus.Address = address;
|
||||
BusWrite(data);
|
||||
}
|
||||
|
||||
@@ -117,59 +118,69 @@
|
||||
BusWrite();
|
||||
}
|
||||
|
||||
protected virtual void BusWrite() => Bus.Write();
|
||||
protected virtual void BusWrite() => Bus.Write(); // N.B. Should be the only real call into the "Bus.Write" code.
|
||||
|
||||
protected byte BusRead(byte low) => BusRead(low, 0);
|
||||
#endregion
|
||||
|
||||
protected byte BusRead(Register16 address) => BusRead(address.Low, address.High);
|
||||
#region BusRead
|
||||
|
||||
protected byte BusRead(byte low, byte high)
|
||||
{
|
||||
Bus.Address.Low = low;
|
||||
Bus.Address.High = high;
|
||||
return BusRead(MakeWord(low, high));
|
||||
}
|
||||
|
||||
protected byte BusRead(ushort address)
|
||||
{
|
||||
Bus.Address = address;
|
||||
return BusRead();
|
||||
}
|
||||
|
||||
protected virtual byte BusRead() => Bus.Read();
|
||||
protected virtual byte BusRead() => Bus.Read(); // N.B. Should be the only real call into the "Bus.Read" code.
|
||||
|
||||
protected byte GetBytePaged(byte page, byte offset) => BusRead(new Register16(offset, page));
|
||||
#endregion
|
||||
|
||||
protected void SetBytePaged(byte page, byte offset, byte value) => BusWrite(new Register16(offset, page), value);
|
||||
#region Paged reader/writer wrappers
|
||||
|
||||
protected byte GetBytePaged(byte page, byte offset) => BusRead(offset, page);
|
||||
|
||||
protected void SetBytePaged(byte page, byte offset, byte value) => BusWrite(offset, page, value);
|
||||
|
||||
#endregion
|
||||
|
||||
protected byte FetchByte() => BusRead(PC++);
|
||||
|
||||
protected abstract Register16 GetWord();
|
||||
protected abstract void SetWord(Register16 value);
|
||||
protected abstract ushort GetWord();
|
||||
protected abstract void SetWord(ushort value);
|
||||
|
||||
protected abstract Register16 GetWordPaged(byte page, byte offset);
|
||||
protected abstract void SetWordPaged(byte page, byte offset, Register16 value);
|
||||
protected abstract ushort GetWordPaged(byte page, byte offset);
|
||||
protected abstract void SetWordPaged(byte page, byte offset, ushort value);
|
||||
|
||||
protected abstract Register16 FetchWord();
|
||||
protected abstract ushort FetchWord();
|
||||
|
||||
protected abstract void Push(byte value);
|
||||
protected abstract byte Pop();
|
||||
|
||||
protected abstract void PushWord(Register16 value);
|
||||
protected abstract Register16 PopWord();
|
||||
protected abstract void PushWord(ushort value);
|
||||
protected abstract ushort PopWord();
|
||||
|
||||
protected Register16 GetWord(Register16 address)
|
||||
protected ushort GetWord(ushort address)
|
||||
{
|
||||
Bus.Address.Word = address.Word;
|
||||
Bus.Address = address;
|
||||
return GetWord();
|
||||
}
|
||||
|
||||
protected void SetWord(Register16 address, Register16 value)
|
||||
protected void SetWord(ushort address, ushort value)
|
||||
{
|
||||
Bus.Address.Word = address.Word;
|
||||
Bus.Address = address;
|
||||
SetWord(value);
|
||||
}
|
||||
|
||||
protected void Jump(Register16 destination)
|
||||
protected void Jump(ushort destination)
|
||||
{
|
||||
PC = destination;
|
||||
}
|
||||
|
||||
protected void Call(Register16 destination)
|
||||
protected void Call(ushort destination)
|
||||
{
|
||||
PushWord(PC);
|
||||
Jump(destination);
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
namespace EightBit
|
||||
{
|
||||
public sealed class Register16
|
||||
{
|
||||
private byte low;
|
||||
private byte high;
|
||||
|
||||
public Register16() { }
|
||||
|
||||
public Register16(ushort value) => Word = value;
|
||||
|
||||
public Register16(byte lowValue, byte highValue)
|
||||
{
|
||||
Low = lowValue;
|
||||
High = highValue;
|
||||
}
|
||||
|
||||
public byte Low { get => low; set => low = value; }
|
||||
public byte High { get => high; set => high = value; }
|
||||
|
||||
public ushort Word
|
||||
{
|
||||
get
|
||||
{
|
||||
return (ushort)(Chip.PromoteByte(high) | low);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
high = Chip.DemoteByte(value);
|
||||
low = Chip.LowByte(value);
|
||||
}
|
||||
}
|
||||
|
||||
public static implicit operator ushort(Register16 value) { return ToUInt16(value); }
|
||||
|
||||
public static Register16 operator ++(Register16 left) => Increment(left);
|
||||
public static Register16 operator --(Register16 left) => Decrement(left);
|
||||
|
||||
public static bool operator ==(Register16 left, Register16 right) => Equals(left, right);
|
||||
public static bool operator !=(Register16 left, Register16 right) => !(left == right);
|
||||
|
||||
public static Register16 operator +(Register16 left, Register16 right) => Add(left, right);
|
||||
public static Register16 operator -(Register16 left, Register16 right) => Subtract(left, right);
|
||||
|
||||
public static ushort ToUInt16(Register16 value) { return value.Word; }
|
||||
public ushort ToUInt16() { return ToUInt16(this); }
|
||||
|
||||
public static Register16 Increment(Register16 left)
|
||||
{
|
||||
++left.Word;
|
||||
return left;
|
||||
}
|
||||
|
||||
public static Register16 Decrement(Register16 left)
|
||||
{
|
||||
--left.Word;
|
||||
return left;
|
||||
}
|
||||
|
||||
public static Register16 Add(Register16 left, Register16 right)
|
||||
{
|
||||
left.Word += right.Word;
|
||||
return left;
|
||||
}
|
||||
|
||||
public static Register16 Subtract(Register16 left, Register16 right)
|
||||
{
|
||||
left.Word -= right.Word;
|
||||
return left;
|
||||
}
|
||||
|
||||
public override int GetHashCode() => Word;
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var register = obj as Register16;
|
||||
return Equals(register);
|
||||
}
|
||||
|
||||
public bool Equals(Register16 register)
|
||||
{
|
||||
return register != null && low == register.low && high == register.high;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user