add project files

This commit is contained in:
2019-02-07 15:56:39 -07:00
parent 746c09d826
commit 9cc69a67ea
25 changed files with 5962 additions and 0 deletions

View File

@@ -0,0 +1,93 @@
using System;
using System.Collections.Generic;
namespace MCEmuCore.GBMonolith
{
public struct OpCode
{
public readonly byte Instruction;
public byte? Arg1;
public byte? Arg2;
}
class Cpu
{
const byte ZERO_FLAG = 0b10000000;
const byte SUB_FLAG = 0b01000000;
const byte HALF_CARRY = 0b00100000;
const byte FULL_CARRY = 0b00010000;
private readonly CpuRegisters registers;
#region OpCodes
private readonly Dictionary<byte, Func<OpCode, bool>> OpCodeTable;
#endregion
public Cpu()
{
registers = new CpuRegisters();
OpCodeTable = new Dictionary<byte, Func<OpCode, bool>>()
{
{0x00, (op) => {
registers.PC += 1;
return true;
} },
{0x01, (op) =>
{
// LD BC,d16
if (op.Arg1.HasValue && op.Arg2.HasValue)
{
ushort operand = (ushort)(op.Arg2 + (op.Arg1 << 8));
registers.BC = operand;
registers.PC += 3;
return true;
}
else
{
throw new InvalidOperationException(op, "Missing arguments for LD BC");
}
} },
{0x02, (op) =>
{
// LD (BC), A
throw new NotImplementedException("LD (BC), A");
} },
{0x03, (op) =>
{
registers.BC += 1;
registers.PC += 1;
return true;
} },
{0x04, (op) =>
{
// INC B
byte reg = (byte)(registers.B + 1);
registers.B = reg;
registers.Flags.Subtract = false;
registers.Flags.Zero = reg == 0;
registers.Flags.HalfCarry = reg == 16;
registers.PC += 1;
return true;
} }
};
}
}
[Serializable]
public class InvalidOperationException : Exception
{
public OpCode OpCode { get; set; }
public InvalidOperationException() { }
public InvalidOperationException(OpCode opCode, string message) : base(message)
{
OpCode = opCode;
}
public InvalidOperationException(string message) : base(message) { }
public InvalidOperationException(string message, Exception inner) : base(message, inner) { }
protected InvalidOperationException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
}

View File

@@ -0,0 +1,308 @@
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<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
{
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; }
}
}
}
}

View File

@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,60 @@
using System;
namespace MCEmuCore.GBMonolith
{
class Program
{
static void Main(string[] args)
{
TestRegisters();
}
static void TestRegisters()
{
CpuRegisters cpuRegisters = new CpuRegisters(true);
Console.WriteLine("Initializing registers:");
Console.WriteLine("A:\t1\tF:\t16");
Console.WriteLine("B:\t2\tC:\t100");
Console.WriteLine("D:\t3\tE:\t150");
Console.WriteLine("H:\t4\tL:\t200\r\n");
cpuRegisters.A += 1;
cpuRegisters.B += 2;
cpuRegisters.D += 3;
cpuRegisters.H += 4;
cpuRegisters.F += 16;
cpuRegisters.C += 100;
cpuRegisters.E += 150;
cpuRegisters.L += 200;
cpuRegisters.PrintSingleStatus();
Console.WriteLine("Expected Wide Register status:");
Console.WriteLine("BC:\t612");
Console.WriteLine("DE:\t918");
Console.WriteLine("HL:\t1224\r\n");
Console.Write("Actual ");
cpuRegisters.PrintWideStatus();
Console.WriteLine("\r\nSetting wide values:");
Console.WriteLine("BC:\t26214");
Console.WriteLine("DE:\t22016");
Console.WriteLine("HL:\t153\r\n");
cpuRegisters.BC = 26214;
cpuRegisters.DE = 22016;
cpuRegisters.HL = 153;
cpuRegisters.PrintWideStatus();
Console.WriteLine("\r\nExpected Register status:");
Console.WriteLine("A:\t1\tF:\t16");
Console.WriteLine("B:\t102\tC:\t102");
Console.WriteLine("D:\t86\tE:\t0");
Console.WriteLine("H:\t0\tL:\t153\r\n");
Console.Write("Actual ");
cpuRegisters.PrintSingleStatus();
Console.WriteLine("Testing Flags:");
cpuRegisters.PrintFlags();
cpuRegisters.Flags.Zero = true;
cpuRegisters.Flags.Subtract = true;
cpuRegisters.Flags.HalfCarry = true;
cpuRegisters.Flags.Carry = false;
cpuRegisters.PrintFlags();
Console.ReadLine();
}
}
}