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 () { };
|
|
|
|
|
2019-11-04 01:55:38 +00:00
|
|
|
// this will be a few cycles off for now
|
|
|
|
// it should suffice for now until Alyosha returns from hiatus
|
|
|
|
public Action IRQACKCallback = delegate () { };
|
2018-07-13 15:34:36 +00:00
|
|
|
|
2017-10-13 00:20:13 +00:00
|
|
|
private void NMI_()
|
|
|
|
{
|
2018-12-21 13:46:47 +00:00
|
|
|
PopulateCURINSTR
|
|
|
|
(IDLE,
|
2018-09-30 03:04:37 +00:00
|
|
|
IDLE,
|
|
|
|
IDLE,
|
|
|
|
IDLE,
|
|
|
|
DEC16, SPl, SPh,
|
2018-06-04 12:57:12 +00:00
|
|
|
TR, ALU, PCl,
|
2018-06-01 01:05:41 +00:00
|
|
|
WAIT,
|
2018-06-04 12:57:12 +00:00
|
|
|
WR_DEC, SPl, SPh, PCh,
|
|
|
|
TR16, PCl, PCh, NMI_V, ZERO,
|
2018-06-01 01:05:41 +00:00
|
|
|
WAIT,
|
2018-12-21 13:46:47 +00:00
|
|
|
WR, SPl, SPh, ALU);
|
2018-06-04 12:57:12 +00:00
|
|
|
|
2018-12-21 13:46:47 +00:00
|
|
|
PopulateBUSRQ(0, 0, 0, 0, 0, SPh, 0, 0, SPh, 0, 0);
|
|
|
|
PopulateMEMRQ(0, 0, 0, 0, 0, SPh, 0, 0, SPh, 0, 0);
|
2018-12-21 10:29:10 +00:00
|
|
|
IRQS = 11;
|
2018-09-30 03:04:37 +00:00
|
|
|
}
|
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)
|
|
|
|
{
|
2018-12-21 13:46:47 +00:00
|
|
|
PopulateCURINSTR
|
|
|
|
(IDLE,
|
2018-09-30 03:04:37 +00:00
|
|
|
IDLE,
|
2018-10-08 14:48:27 +00:00
|
|
|
IORQ,
|
|
|
|
WAIT,
|
2018-06-04 12:57:12 +00:00
|
|
|
IDLE,
|
2018-06-01 01:05:41 +00:00
|
|
|
WAIT,
|
2018-12-21 13:46:47 +00:00
|
|
|
RD_INC, ALU, PCl, PCh);
|
2018-06-04 12:57:12 +00:00
|
|
|
|
2018-12-21 13:46:47 +00:00
|
|
|
PopulateBUSRQ(0, 0, 0, 0, PCh, 0, 0);
|
|
|
|
PopulateMEMRQ(0, 0, 0, 0, PCh, 0, 0);
|
2018-12-21 10:29:10 +00:00
|
|
|
IRQS = 7;
|
2019-11-04 01:55:38 +00:00
|
|
|
}
|
2017-10-13 00:20:13 +00:00
|
|
|
|
|
|
|
// Just jump to $0038
|
|
|
|
private void INTERRUPT_1()
|
|
|
|
{
|
2018-12-21 13:46:47 +00:00
|
|
|
PopulateCURINSTR
|
|
|
|
(IDLE,
|
2018-09-30 03:04:37 +00:00
|
|
|
IDLE,
|
2018-10-08 14:48:27 +00:00
|
|
|
IORQ,
|
|
|
|
WAIT,
|
2018-09-30 03:04:37 +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,
|
2018-12-21 13:46:47 +00:00
|
|
|
WR, SPl, SPh, ALU);
|
2018-06-04 12:57:12 +00:00
|
|
|
|
2018-12-21 13:46:47 +00:00
|
|
|
PopulateBUSRQ(0, 0, 0, 0, I, 0, 0, SPh, 0, 0, SPh, 0, 0);
|
|
|
|
PopulateMEMRQ(0, 0, 0, 0, I, 0, 0, SPh, 0, 0, SPh, 0, 0);
|
2018-12-21 10:29:10 +00:00
|
|
|
IRQS = 13;
|
2019-11-04 01:55:38 +00:00
|
|
|
}
|
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
|
|
|
{
|
2018-12-21 13:46:47 +00:00
|
|
|
PopulateCURINSTR
|
|
|
|
(IDLE,
|
2018-09-30 03:04:37 +00:00
|
|
|
IDLE,
|
2018-10-08 14:48:27 +00:00
|
|
|
IORQ,
|
|
|
|
WAIT,
|
2018-09-30 03:04:37 +00:00
|
|
|
FTCH_DB,
|
2018-06-04 12:57:12 +00:00
|
|
|
IDLE,
|
2017-10-13 00:20:13 +00:00
|
|
|
DEC16, SPl, SPh,
|
2018-12-21 13:46:47 +00:00
|
|
|
TR16, Z, W, DB, I,
|
2018-06-01 01:05:41 +00:00
|
|
|
WAIT,
|
2018-06-04 12:57:12 +00:00
|
|
|
WR_DEC, SPl, SPh, PCh,
|
|
|
|
IDLE,
|
2018-06-01 01:05:41 +00:00
|
|
|
WAIT,
|
|
|
|
WR, SPl, SPh, PCl,
|
2017-10-13 20:27:41 +00:00
|
|
|
IDLE,
|
2018-06-01 01:05:41 +00:00
|
|
|
WAIT,
|
|
|
|
RD_INC, PCl, Z, W,
|
2017-11-29 21:28:08 +00:00
|
|
|
IDLE,
|
2018-06-04 12:57:12 +00:00
|
|
|
WAIT,
|
2018-12-21 13:46:47 +00:00
|
|
|
RD, PCh, Z, W);
|
2018-06-04 12:57:12 +00:00
|
|
|
|
2018-12-21 13:46:47 +00:00
|
|
|
PopulateBUSRQ(0, 0, 0, 0, I, 0, 0, SPh, 0, 0, SPh, 0, 0, W, 0, 0, W, 0, 0);
|
|
|
|
PopulateMEMRQ(0, 0, 0, 0, I, 0, 0, SPh, 0, 0, SPh, 0, 0, W, 0, 0, W, 0, 0);
|
2018-12-21 10:29:10 +00:00
|
|
|
IRQS = 19;
|
2019-11-04 01:55:38 +00:00
|
|
|
}
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|