forked from sin365/AxibugEmuOnline
82 lines
2.2 KiB
C#
82 lines
2.2 KiB
C#
using System;
|
|
|
|
namespace AxibugEmuOnline.Client.UNES
|
|
{
|
|
sealed partial class CPU
|
|
{
|
|
public enum InterruptType
|
|
{
|
|
NMI,
|
|
IRQ,
|
|
RESET
|
|
}
|
|
|
|
private readonly uint[] _interruptHandlerOffsets = { 0xFFFA, 0xFFFE, 0xFFFC };
|
|
private readonly bool[] _interrupts = new bool[2];
|
|
|
|
public void Initialize()
|
|
{
|
|
A = 0;
|
|
X = 0;
|
|
Y = 0;
|
|
SP = 0xFD;
|
|
P = 0x24;
|
|
|
|
PC = ReadWord(_interruptHandlerOffsets[(int) InterruptType.RESET]);
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
SP -= 3;
|
|
F.InterruptsDisabled = true;
|
|
}
|
|
|
|
public void TickFromPPU()
|
|
{
|
|
if (Cycle-- > 0) return;
|
|
ExecuteSingleInstruction();
|
|
}
|
|
|
|
public void ExecuteSingleInstruction()
|
|
{
|
|
for (var i = 0; i < _interrupts.Length; i++)
|
|
{
|
|
if (_interrupts[i])
|
|
{
|
|
PushWord(PC);
|
|
Push(P);
|
|
PC = ReadWord(_interruptHandlerOffsets[i]);
|
|
F.InterruptsDisabled = true;
|
|
_interrupts[i] = false;
|
|
return;
|
|
}
|
|
}
|
|
|
|
_currentInstruction = NextByte();
|
|
|
|
Cycle += _opCodeDefs[_currentInstruction].Cycles;
|
|
|
|
ResetInstructionAddressingMode();
|
|
// if (_numExecuted > 10000 && PC - 1 == 0xFF61)
|
|
// if(_emulator.Controller.debug || 0x6E00 <= PC && PC <= 0x6EEF)
|
|
// Console.WriteLine($"{(PC - 1).ToString("X4")} {_currentInstruction.ToString("X2")} {opcodeNames[_currentInstruction]}\t\t\tA:{A.ToString("X2")} X:{X.ToString("X2")} Y:{Y.ToString("X2")} P:{P.ToString("X2")} SP:{SP.ToString("X2")}");
|
|
|
|
var op = _opCodes[_currentInstruction];
|
|
if (op == null)
|
|
{
|
|
throw new ArgumentException(_currentInstruction.ToString("X2"));
|
|
}
|
|
|
|
op();
|
|
}
|
|
|
|
public void TriggerInterrupt(InterruptType type)
|
|
{
|
|
if (!F.InterruptsDisabled || type == InterruptType.NMI)
|
|
{
|
|
_interrupts[(int)type] = true;
|
|
}
|
|
}
|
|
}
|
|
}
|