Files
MCEmuCore/MCEmuCore.GBMonolith/CpuRegisters.cs
2020-05-15 21:03:35 -06:00

313 lines
8.3 KiB
C#

using System;
using System.Collections.Generic;
namespace MCEmuCore.GBMonolith
{
class CpuRegisters
{
enum Register { A, B, C, D, E, H, L };
private readonly byte[] Registers = new byte[7];
public readonly FlagRegister Flags = new FlagRegister();
public ushort SP, PC;
#region Register Accessors
public byte A
{
get
{
return Registers[(int)Register.A];
}
set
{
Registers[(int)Register.A] = value;
}
}
public byte B
{
get
{
return Registers[(int)Register.B];
}
set
{
Registers[(int)Register.B] = value;
}
}
public byte D
{
get
{
return Registers[(int)Register.D];
}
set
{
Registers[(int)Register.D] = value;
}
}
public byte H
{
get
{
return Registers[(int)Register.H];
}
set
{
Registers[(int)Register.H] = value;
}
}
public byte F
{
get
{
return Flags.Value;
}
set
{
Flags.Value = value;
}
}
public byte C
{
get
{
return Registers[(int)Register.C];
}
set
{
Registers[(int)Register.C] = value;
}
}
public byte E
{
get
{
return Registers[(int)Register.E];
}
set
{
Registers[(int)Register.E] = value;
}
}
public byte L
{
get
{
return Registers[(int)Register.L];
}
set
{
Registers[(int)Register.L] = value;
}
}
#endregion
#region Wide Register Accessors
public ushort AF
{
get
{
ushort retVal = Flags.Value;
retVal += (ushort)((Registers[(int)Register.A]) << 8);
return retVal;
}
set
{
Flags.Value = (byte)(value & 0x00FF);
Registers[(int)Register.A] = (byte)((value & 0xFF00) >> 8);
}
}
public ushort BC
{
get
{
ushort retVal = Registers[(int)Register.C];
retVal += (ushort)((Registers[(int)Register.B]) << 8);
return retVal;
}
set
{
Registers[(int)Register.C] = (byte)(value & 0x00FF);
Registers[(int)Register.B] = (byte)((value & 0xFF00) >> 8);
}
}
public ushort DE
{
get
{
ushort retVal = Registers[(int)Register.E];
retVal += (ushort)((Registers[(int)Register.D]) << 8);
return retVal;
}
set
{
Registers[(int)Register.E] = (byte)(value & 0x00FF);
Registers[(int)Register.D] = (byte)((value & 0xFF00) >> 8);
}
}
public ushort HL
{
get
{
ushort retVal = Registers[(int)Register.L];
retVal += (ushort)((Registers[(int)Register.H]) << 8);
return retVal;
}
set
{
Registers[(int)Register.L] = (byte)(value & 0x00FF);
Registers[(int)Register.H] = (byte)((value & 0xFF00) >> 8);
}
}
#endregion
#region Constructors
public CpuRegisters()
{
AF = 0x01B0;
BC = 0x0013;
DE = 0x00D8;
HL = 0x014D;
}
public CpuRegisters(ushort initValue) : base()
{
AF = initValue;
BC = initValue;
DE = initValue;
HL = initValue;
}
public CpuRegisters(byte A, byte F, ushort SP, ushort PC)
{
this.A = A;
this.F = F;
this.SP = SP;
this.PC = PC;
}
public CpuRegisters(byte A, byte F, byte B, byte C, byte D, byte E, byte H, byte L, ushort SP, ushort PC) : this(A, F, SP, PC)
{
this.B = B;
this.C = C;
this.D = D;
this.E = E;
this.H = H;
this.L = L;
}
public CpuRegisters(byte A, byte F, ushort BC, ushort DE, ushort HL, ushort SP, ushort PC) : this(A, F, SP, PC)
{
this.BC = BC;
this.DE = DE;
this.HL = HL;
}
#endregion
public Dictionary<string, ushort> DumpRegisters()
{
return new Dictionary<string, ushort>
{
{ "A", A },
{ "F", F },
{ "B", B },
{ "C", C },
{ "D", D },
{ "E", E },
{ "H", H },
{ "L", L },
{ "AF", AF },
{ "BC", BC },
{ "DE", DE },
{ "HL", HL },
{ "PC", PC },
{ "SP", SP }
};
}
#region Print Functions
public void PrintSingleStatus()
{
Console.WriteLine("Register status:");
Console.WriteLine($"A:\t{A}\tF:\t{F}");
Console.WriteLine($"B:\t{B}\tC:\t{C}");
Console.WriteLine($"D:\t{D}\tE:\t{E}");
Console.WriteLine($"H:\t{H}\tL:\t{L}\r\n");
}
public void PrintWideStatus()
{
Console.WriteLine("Wide Register status:");
Console.WriteLine($"AF:\t{AF}");
Console.WriteLine($"BC:\t{BC}");
Console.WriteLine($"DE:\t{DE}");
Console.WriteLine($"HL:\t{HL}");
}
public void PrintFlags()
{
Console.WriteLine("Flag status:");
Console.WriteLine($"Zero:\t\t{Flags.Zero}");
Console.WriteLine($"Subtract:\t{Flags.Subtract}");
Console.WriteLine($"Half Carry:\t{Flags.HalfCarry}");
Console.WriteLine($"Carry:\t\t{Flags.Carry}");
Console.WriteLine($"Raw Register:\t{Convert.ToString(Flags.Value, 2)}");
}
#endregion
public class FlagRegister
{
private byte register;
public byte Value {
get => register;
set {
register = (byte)(value & 0b1111_0000);
}
}
#region Boolean Flag Properties
public bool Zero
{
get { return (Value & 0b1000_0000) != 0; }
set
{
if (value)
register |= 0b1000_0000;
else
register &= 0b0111_0000;
}
}
public bool Subtract
{
get { return (Value & 0b0100_0000) != 0; }
set
{
if (value)
register |= 0b0100_0000;
else
register &= 0b1011_0000;
}
}
public bool HalfCarry
{
get { return (Value & 0b0010_0000) != 0; }
set
{
if (value)
register |= 0b0010_0000;
else
register &= 0b1101_0000;
}
}
public bool Carry
{
get { return (Value & 0b0001_0000) != 0; }
set
{
if (value)
register |= 0b0001_0000;
else
register &= 0b1110_0000;
}
}
#endregion
public bool IsValid
{
get { return (Value & 0b0000_1111) == 0; }
}
}
}
}