Skip to content

Commit

Permalink
#5 Handle interrupts in a better way that handles the added cycles
Browse files Browse the repository at this point in the history
  • Loading branch information
hagronnestad committed Sep 11, 2019
1 parent bde0894 commit c76cd9e
Showing 1 changed file with 47 additions and 18 deletions.
65 changes: 47 additions & 18 deletions MicroProcessor/Cpu6502/Cpu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ public class Cpu {
/// </summary>
private int _cyclesRemainingCurrentInstruction = 0;

private bool interruptWaiting = false;
private bool nonMaskableInterruptWaiting = false;

public List<OpCodeDefinition> OpCodes { get; private set; }
public Dictionary<byte, OpCodeDefinition> OpCodeCache { get; set; }

Expand Down Expand Up @@ -69,7 +72,6 @@ public class Cpu {
Reserved = true
};


public OpCodeDefinition OpCode { get; set; }
public ushort OpCodeAddress;

Expand Down Expand Up @@ -144,7 +146,16 @@ public void InitPC(ushort pc) {
/// </summary>
public void Cycle() {
if (_cyclesRemainingCurrentInstruction == 0) {
Step();

if (nonMaskableInterruptWaiting) {
DoNonMaskableInterrupt();

} else if (interruptWaiting) {
DoInterrupt();

} else {
Step();
}

} else {
_cyclesRemainingCurrentInstruction--;
Expand All @@ -156,8 +167,6 @@ public void Cycle() {
/// </summary>
/// <param name="ignoreCycles"></param>
public void Step(bool ignoreCycles = false) {
TotalInstructions += 1;

OpCode = OpCodeCache[Memory[PC]];
OpCodeAddress = PC;
PC++;
Expand All @@ -170,6 +179,7 @@ public void Step(bool ignoreCycles = false) {
OpCode.GetAddress();
}
OpCode.Run();
TotalInstructions += 1;

// Count total cycles
// This doesn't account for extra cycles caused by memory operations crossing pages
Expand All @@ -188,8 +198,8 @@ public void Reset() {

// SP should be 0xFD, I used to initialize it directly, but `-= 3` on a `byte` becomes 0xFD after roll over
// I'm not sure if this is correct on multiple resets yet
SP -= 3;
//SP = 0xFD;
//SP -= 3;
SP = 0xFD;

SR.IrqDisable = true;

Expand All @@ -200,39 +210,58 @@ public void Reset() {
TotalCycles += 8;
}

public void Interrupt() { // IRQ
// From https://youtu.be/8XmxKPJDGU0?t=3362
/// <summary>
/// Triggers a non maskable interrupt (NMI) before executing the next instruction.
/// </summary>
public void NonMaskableInterrupt() {
nonMaskableInterruptWaiting = true;
}

/// <summary>
/// Triggers an interrupt (IRQ) before executing the next instruction.
/// </summary>
public void Interrupt() {
if (SR.IrqDisable) return;
interruptWaiting = true;
}

public void DoNonMaskableInterrupt() {
// From https://youtu.be/8XmxKPJDGU0?t=3362

PushStack((byte)(PC >> 8));
PushStack((byte)(PC & 0x00FF));

PushStack((byte)((SR.Register | (byte)ProcessorStatusFlags.Reserved) & (byte)~ProcessorStatusFlags.BreakCommand));

SR.IrqDisable = true;

var irqVectorAddress = 0xFFFE;
PC = (ushort)((Memory[irqVectorAddress + 1] << 8) | Memory[irqVectorAddress + 0]);
var nmiVectorAddress = 0xFFFA;
PC = (ushort)((Memory[nmiVectorAddress + 1] << 8) | Memory[nmiVectorAddress + 0]);

// IRQ takes 7 cycles
TotalCycles += 7;
// NMI takes 8 cycles
TotalCycles += 8;
_cyclesRemainingCurrentInstruction += 8;

nonMaskableInterruptWaiting = false;
}

public void NonMaskableInterrupt() { // NMI
private void DoInterrupt() {
// From https://youtu.be/8XmxKPJDGU0?t=3362

PushStack((byte)(PC >> 8));
PushStack((byte)(PC & 0x00FF));

PushStack((byte)((SR.Register | (byte)ProcessorStatusFlags.Reserved) & (byte)~ProcessorStatusFlags.BreakCommand));

SR.IrqDisable = true;

var nmiVectorAddress = 0xFFFA;
PC = (ushort)((Memory[nmiVectorAddress + 1] << 8) | Memory[nmiVectorAddress + 0]);
var irqVectorAddress = 0xFFFE;
PC = (ushort)((Memory[irqVectorAddress + 1] << 8) | Memory[irqVectorAddress + 0]);

// NMI takes 8 cycles
TotalCycles += 8;
// IRQ takes 7 cycles
TotalCycles += 7;
_cyclesRemainingCurrentInstruction += 7;

interruptWaiting = false;
}

/// <summary>
Expand Down

0 comments on commit c76cd9e

Please sign in to comment.