Skip to content
2 changes: 1 addition & 1 deletion CPU_emu/CPU_emu.CMD_Methods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public void Cmd_B4()

#region stack push pull

// Push Accumulator on Stack
// Push Accumulator on Stack PHA
public void Cmd_48()
{
PushByteToStack(A,ref _CpuCycle);
Expand Down
119 changes: 44 additions & 75 deletions CPU_emu/Class_CPU.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using CPU_emulator;
using CPU_emu;
using CPU_emulator;
using System;
using System.Collections.Generic;
using System.ComponentModel;
Expand Down Expand Up @@ -31,6 +32,8 @@ public partial class CPU
private const uint MAX_MEM = 1024 * 64;
private byte[] Data = new byte[MAX_MEM];

MemoryBus _memoryBus;

private byte
NegativeFlagBit = 0b10000000,
OverflowFlagBit = 0b01000000,
Expand All @@ -42,6 +45,8 @@ private byte
public bool SteppingMode { get => _SteppingMode; set => _SteppingMode = value; }
public bool ExitRequested { get => _ExitRequested; set => _ExitRequested = value; }
public ulong InterruptPeriod { get => _InterruptPeriod; set => _InterruptPeriod = value; }

public ulong CpuCycle { get => _CpuCycle; }
public byte[] Memory
{
get
Expand Down Expand Up @@ -70,6 +75,7 @@ public byte[] Memory

public CPU()
{
_memoryBus = new MemoryBus(ref Data);
SetVectors();
}

Expand All @@ -91,7 +97,7 @@ public void Reset()
SetRegister("A", 0);
SetRegister("X", 0);
SetRegister("Y", 0);
InterruptPeriod = 1000;

ExitRequested = false;

// set all status flags to false
Expand All @@ -105,51 +111,7 @@ public void Reset()

}

private void LoadInlineTestProg()
{
Data[PC] = 0xB5;
Data[PC + 1] = 0x0b;
Data[PC + 2] = 0x48;
Data[PC + 3] = 0xA9;
Data[PC + 4] = 0xac;
Data[PC + 5] = 0x48;
Data[PC + 6] = 0xA9;
Data[PC + 7] = 0x00;
Data[PC + 8] = 0x48;
Data[PC + 9] = 0xA9;
Data[PC + 10] = 0xae;
Data[PC + 11] = 0x48;

Data[PC + 12] = 0x48;
Data[PC + 13] = 0x48;
Data[PC + 14] = 0x48;
Data[PC + 15] = 0x48;

Data[PC + 16] = 0x48;
Data[PC + 17] = 0x48;
Data[PC + 18] = 0x48;
Data[PC + 19] = 0x48;

Data[PC + 20] = 0x48;
Data[PC + 21] = 0x48;
Data[PC + 22] = 0x48;
Data[PC + 23] = 0x48;
Data[PC + 24] = 0x48;
Data[PC + 25] = 0x48;
Data[PC + 26] = 0x48;
Data[PC + 27] = 0x48;

Data[PC + 28] = 0x48;
Data[PC + 29] = 0x68;
Data[PC + 30] = 0x68;
Data[PC + 31] = 0x68;
Data[PC + 32] = 0x68;
Data[PC + 33] = 0x68;
Data[PC + 34] = 0x68;
Data[PC + 35] = 0x68;

OnMemoryUpdate?.Invoke(this, new CPUEventArgs(this));
}


public void Start()
{
Expand All @@ -163,37 +125,16 @@ public void Start()

private void CpuRunner_DoWork(object sender, DoWorkEventArgs e)
{
//_CpuCycle = InterruptPeriod;


Type thisType = this.GetType();


while (CpuIsRunning)
{
byte instruction = FetchByte();

// Build method name from 'Cmd' + opcode
string cmd = "Cmd_" + instruction.ToString("X2").ToUpper();

MethodInfo theMethod2Call = thisType.GetMethod(cmd);
// Check if method Cmd_<opcode> exists
if (theMethod2Call != null)
{
// check for method attribute
OpcodeAttribute? attribute = theMethod2Call.GetCustomAttribute<OpcodeAttribute>();

theMethod2Call.Invoke(this, new object[] { });
CallInstruction(thisType, instruction);

if (attribute != null)
{
IncrementCpuCycle((ulong)attribute.Cycles);
}
}
else
{
MessageBox.Show(string.Format("Method {0} not found!", cmd),"Error!",MessageBoxButtons.OK,MessageBoxIcon.Error);
}

if (_SteppingMode)
{
break;
Expand All @@ -208,13 +149,38 @@ private void CpuRunner_DoWork(object sender, DoWorkEventArgs e)
break;
}


if (SlowDown && !_SteppingMode)
{
System.Threading.Thread.Sleep(SlowDownTime);
}



}
}

private void CallInstruction(Type thisType, byte instruction)
{
// Build method name from 'Cmd' + opcode
string cmd = "Cmd_" + instruction.ToString("X2").ToUpper();

MethodInfo theMethod2Call = thisType.GetMethod(cmd);
// Check if method Cmd_<opcode> exists
if (theMethod2Call != null)
{
// check for method attribute
OpcodeAttribute? attribute = theMethod2Call.GetCustomAttribute<OpcodeAttribute>();

theMethod2Call.Invoke(this, new object[] { });

if (attribute != null)
{
IncrementCpuCycle((ulong)attribute.Cycles);
}
}
else
{
MessageBox.Show(string.Format("Method {0} not found!", cmd), "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}

Expand Down Expand Up @@ -256,7 +222,8 @@ private void SetZeroAndNegativeFlags(byte register)

private byte FetchByte()
{
byte data = Data[PC];
//byte data = Data[PC];
byte data = _memoryBus.Read((ushort)PC);
IncrementPC();
IncrementCpuCycle(1);
return data;
Expand All @@ -275,13 +242,15 @@ private ushort FetchWord(ref ulong CpuCycle)

public void WriteByteToMemory(byte b,ushort address)
{
Data[address] = b;
//Data[address] = b;
_memoryBus.Write(address, b);
OnMemoryUpdate?.Invoke(this, new CPUEventArgs(this));
}

private byte ReadByteFromMemory(ushort address)
{
return Data[address];
//return Data[address];
return _memoryBus.Read(address);
}

private ushort ReadWordFromMemory(ushort address)
Expand Down
10 changes: 5 additions & 5 deletions CPU_emu/Forms/CPU_emu.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions CPU_emu/Interfaces/IMemoryBus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CPU_emu;

internal interface IMemoryBus
{
byte Read(ushort address);
void Write(ushort address, byte value);
void Load(ushort address, params byte[] data);
byte[] Dump(ushort address, int length);


}
43 changes: 43 additions & 0 deletions CPU_emu/MemoryBus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CPU_emu
{
internal class MemoryBus : IMemoryBus
{
private readonly byte[] _memory;

public MemoryBus(int memSize = 1024 * 64)
{
_memory = new byte[memSize];
}
public MemoryBus(ref byte[] memory)
{
_memory = memory;
}
public byte Read(ushort address)
{
return _memory[address];
}

public void Write(ushort address, byte value)
{
_memory[address] = value;
}

public void Load(ushort address, params byte[] data)
{
Array.Copy(data, 0, _memory, address, data.Length);
}

public byte[] Dump(ushort address, int length)
{
return _memory.Skip(address).Take(length).ToArray();
}


}
}
Loading