Actually, there is more to it, as Gerald already mentionned. On the z80, the INT signal is level triggered, but NMI is edge triggered. In simple cases, this doesn't matter, but imagine the following situations:
* One device triggers INT
* The z80 does an automatic DI and enters the interrupt handler code
* During the interrupt processing, another device triggers INT
* The z80 acknowledges the interrupt of the first device, and exits the interrupt handler (EI, RET)
* Because the second device is still holding INT low, immediately after the RET, the z80 enters the INT handler again (if using IM2, it goes to device 2 handler directly)
* The z80 can now process the interrupt from the second device
In the case of an NMI, it doesn't work this way. The NMI is "disabled" as long as the pin is held low.
* One device puts NMI low and holds it low
* The z80 enters the NMI handler
* Second device also pulls NMI low
* The z80 processes only the NMI from the first device
* The z80 exits the NMI routine, but the NMI line is still low because of device 2
* No NMIs can happen anymore!
This means the NMI handler must be carefully written to:
* Check ALL devices that could trigger an interrupt
* Disable the NMI on each device to make sure the NMI line goes up again (just acknowledging the interrupt is not enough, it must be locked at the "high" state until re-enabled by the CPU, providing a way to mask the NMI)
* Process all requests from the devices
* Finally, re-enable the NMI line of each device. If there is again an interrupt pending, we will enter the NMI handler again (before exiting it - we can't use the "EI/RET" trick of the regular INT here, where EI is effective only after RET is executed) - This means the NMI handler should also detect this condition and make sure to not overflow the stack by too many re-entries
* Do this in a loop until all devices are quiet again and there is no NMI to process anymore
Essentially, this emulates the behavior of INT in software.
There are other ways to handle this, for example the NMI handler could just increment a variable to signal that the NMI occured, then your main loop would check for that, do the actual processing and acknowledge each device.
And of course there is the case where you don't want to handle multiple NMIs at the same time. You first load something from Albireo (snapshot file, files from the USB, whatever), then you swithc Albireo interrupts off. Then, the program starts, and it uses the PlayCity after setting up its own handler. In this case there are no interrupt conflict problems, still the two devices have used the NMI at some point.