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(); #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 public ushort SP { get; set; } public ushort PC { get; set; } #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 DumpRegisters() { return new Dictionary { { "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 { protected internal byte Value { get; set; } #region Boolean Flag Properties public bool Zero { get { return (Value & 0b1000_0000) != 0; } set { if (value) Value |= 0b1000_0000; else Value &= 0b0111_1111; } } public bool Subtract { get { return (Value & 0b0100_0000) != 0; } set { if (value) Value |= 0b0100_0000; else Value &= 0b1011_1111; } } public bool HalfCarry { get { return (Value & 0b0010_0000) != 0; } set { if (value) Value |= 0b0010_0000; else Value &= 0b1101_1111; } } public bool Carry { get { return (Value & 0b0001_0000) != 0; } set { if (value) Value |= 0b0001_0000; else Value &= 0b1110_1111; } } #endregion public bool IsValid { get { return (Value & 0b0000_1111) == 0; } } } } }