interrupt method

void interrupt(
  1. bool nonMaskable,
  2. int data
)

Simulates pulsing the processor's INT (or NMI) pin

nonMaskable - true if this is a non-maskable interrupt data - the value to be placed on the data bus, if needed

Implementation

void interrupt(bool nonMaskable, int data) {
  if (nonMaskable) {
    // The high bit of R is not affected by this increment,
    //  it can only be changed using the LD R, A instruction.
    _r = (_r & 0x80) | (((_r & 0x7f) + 1) & 0x7f);
    // Non-maskable interrupts are always handled the same way;
    //  clear IFF1 and then do a CALL 0x0066.
    // Also, all interrupts reset the HALT state.
    _halted = false;
    _iff2 = _iff1;
    _iff1 = 0;
    _pushWord(_pc);
    _pc = 0x66;
    _cycleCounter += 11;
  } else if (_iff1 != 0) {
    // The high bit of R is not affected by this increment,
    //  it can only be changed using the LD R, A instruction.
    _r = (_r & 0x80) | (((_r & 0x7f) + 1) & 0x7f);
    _halted = false;
    _iff1 = 0;
    _iff2 = 0;
    if (_interruptMode == 0) {
      // In the 8080-compatible interrupt mode,
      //  decode the content of the data bus as an instruction and run it.
      // it's probably a RST instruction, which pushes (PC+1) onto the stack
      // so we should decrement PC before we decode the instruction
      _pc = (_pc - 1) & 0xffff;
      _decodeInstruction(data);
      _pc = (_pc + 1) & 0xffff; // increment PC upon return
      _cycleCounter += 2;
    } else if (_interruptMode == 1) {
      // Mode 1 is always just RST 0x38.
      _pushWord(_pc);
      _pc = 0x38;
      _cycleCounter += 13;
    } else if (_interruptMode == 2) {
      // Mode 2 uses the value on the data bus as in index
      //  into the vector table pointer to by the I register.
      _pushWord(_pc);
      // The Z80 manual says that this address must be 2-byte aligned,
      //  but it doesn't appear that this is actually the case on the hardware,
      //  so we don't attempt to enforce that here.
      var vectorAddress = ((_i << 8) | data);
      _pc = _core.memRead(vectorAddress) |
          (_core.memRead((vectorAddress + 1) & 0xffff) << 8);
      _cycleCounter += 19;
    }
  }
}