BizHawk/BizHawk.Emulation.Cores/CPUs/Z80A/Interrupts.cs

142 lines
3.6 KiB
C#
Raw Normal View History

2017-10-13 00:20:13 +00:00
using System;
2017-10-13 21:58:36 +00:00
namespace BizHawk.Emulation.Cores.Components.Z80A
2017-10-13 00:20:13 +00:00
{
public partial class Z80A
{
private bool iff1;
public bool IFF1 { get { return iff1; } set { iff1 = value; } }
private bool iff2;
public bool IFF2 { get { return iff2; } set { iff2 = value; } }
private bool nonMaskableInterrupt;
public bool NonMaskableInterrupt
{
get { return nonMaskableInterrupt; }
set { if (value && !nonMaskableInterrupt) NonMaskableInterruptPending = true; nonMaskableInterrupt = value; }
}
private bool nonMaskableInterruptPending;
public bool NonMaskableInterruptPending { get { return nonMaskableInterruptPending; } set { nonMaskableInterruptPending = value; } }
private int interruptMode;
public int InterruptMode
{
get { return interruptMode; }
set { if (value < 0 || value > 2) throw new ArgumentOutOfRangeException(); interruptMode = value; }
}
public Action IRQCallback = delegate () { };
public Action NMICallback = delegate () { };
// this will be a few cycles off for now
// it should suffice for now until Alyosha returns from hiatus
public Action IRQACKCallback = delegate () { };
2017-10-13 00:20:13 +00:00
private void NMI_()
{
cur_instr = new ushort[]
{DEC16, SPl, SPh,
2018-06-04 12:57:12 +00:00
TR, ALU, PCl,
WAIT,
2018-06-04 12:57:12 +00:00
WR_DEC, SPl, SPh, PCh,
TR16, PCl, PCh, NMI_V, ZERO,
WAIT,
2018-06-04 12:57:12 +00:00
WR, SPl, SPh, ALU,
IDLE,
WAIT,
OP_F,
2017-10-13 00:20:13 +00:00
OP };
2018-06-04 12:57:12 +00:00
BUSRQ = new ushort[] { 0, SPh, 0, 0, SPh, 0, 0, PCh, 0, 0, 0 };
MEMRQ = new ushort[] { 0, SPh, 0, 0, SPh, 0, 0, PCh, 0, 0, 0 };
}
2017-10-13 00:20:13 +00:00
// Mode 0 interrupts only take effect if a CALL or RST is on the data bus
// Otherwise operation just continues as normal
// For now assume a NOP is on the data bus, in which case no stack operations occur
//NOTE: TODO: When a CALL is present on the data bus, adjust WZ accordingly
private void INTERRUPT_0(ushort src)
{
cur_instr = new ushort[]
{IDLE,
WAIT,
2018-06-04 12:57:12 +00:00
RD_INC, ALU, PCl, PCh,
IDLE,
WAIT,
OP_F,
2017-10-13 00:20:13 +00:00
OP };
2018-06-04 12:57:12 +00:00
BUSRQ = new ushort[] { PCh, 0, 0, PCh, 0, 0, 0 };
MEMRQ = new ushort[] { PCh, 0, 0, PCh, 0, 0, 0 };
IRQACKCallback();
}
2017-10-13 00:20:13 +00:00
// Just jump to $0038
private void INTERRUPT_1()
{
cur_instr = new ushort[]
2018-06-04 12:57:12 +00:00
{IDLE,
2018-06-04 15:15:26 +00:00
TR, ALU, PCl,
2017-10-13 00:20:13 +00:00
DEC16, SPl, SPh,
IDLE,
2018-06-04 12:57:12 +00:00
WAIT,
WR_DEC, SPl, SPh, PCh,
TR16, PCl, PCh, IRQ_V, ZERO,
WAIT,
WR, SPl, SPh, ALU,
2017-10-13 00:20:13 +00:00
IDLE,
WAIT,
OP_F,
2017-10-13 00:20:13 +00:00
OP };
2018-06-04 12:57:12 +00:00
BUSRQ = new ushort[] { I, 0, 0, SPh, 0, 0, SPh, 0, 0, PCh, 0, 0, 0 };
MEMRQ = new ushort[] { I, 0, 0, SPh, 0, 0, SPh, 0, 0, PCh, 0, 0, 0 };
IRQACKCallback();
}
2017-10-13 00:20:13 +00:00
// Interrupt mode 2 uses the I vector combined with a byte on the data bus
2018-03-16 21:50:51 +00:00
private void INTERRUPT_2()
2017-10-13 00:20:13 +00:00
{
cur_instr = new ushort[]
2018-06-04 12:57:12 +00:00
{FTCH_DB,
IDLE,
2017-10-13 00:20:13 +00:00
DEC16, SPl, SPh,
2018-06-04 12:57:12 +00:00
TR16, Z, W, DB, I,
WAIT,
2018-06-04 12:57:12 +00:00
WR_DEC, SPl, SPh, PCh,
IDLE,
WAIT,
WR, SPl, SPh, PCl,
2017-10-13 20:27:41 +00:00
IDLE,
WAIT,
RD_INC, PCl, Z, W,
IDLE,
2018-06-04 12:57:12 +00:00
WAIT,
RD, PCh, Z, W,
2017-10-13 20:27:41 +00:00
IDLE,
WAIT,
OP_F,
2017-10-13 00:20:13 +00:00
OP };
2018-06-04 12:57:12 +00:00
BUSRQ = new ushort[] { I, 0, 0, SPh, 0, 0, SPh, 0, 0, W, 0, 0, W, 0 ,0 ,PCh, 0, 0, 0 };
MEMRQ = new ushort[] { I, 0, 0, SPh, 0, 0, SPh, 0, 0, W, 0, 0, W, 0, 0, PCh, 0, 0, 0 };
IRQACKCallback();
}
2017-10-13 00:20:13 +00:00
private void ResetInterrupts()
{
IFF1 = false;
IFF2 = false;
NonMaskableInterrupt = false;
NonMaskableInterruptPending = false;
2017-10-13 20:27:41 +00:00
FlagI = false;
2017-10-13 00:20:13 +00:00
InterruptMode = 1;
}
}
}