Interrupts

When the Z80 is in IM2, on receiving a maskable interrupt it reads the two bytes (LSB first) at ( 0x100 * I + x ) where I is the Z80's I register and x is the value on the data bus at interrupt time. In "theory", the value on the data bus should always be 0xff, but certain pieces of hardware (notably Kempston joystick interfaces) have been alleged to put other values on the bus at interrupt time. This means that IM2 is slightly more fiddly to use and slightly less useful than it would be without this problem.

The traditional workaround for this issue is to create a table of 257 identical bytes b at 0x100 * I and then to put the ISR at 0x101 * b. A modification of this technique uses the fact that the 48K ROM contains empty space from 0x386e to 0x3cff which is filled with 0xff. Setting I to 0x38, 0x39, 0x3a or 0x3b thus means that the ISR will jump to 0xffff, at which 0x18 (JR) is placed. The JR then uses the fact that the first byte of ROM is 0xf3 (DI), so the JR occurs to 0xfff4, at which the "real" ISR is placed (quite likely a JP to somewhere else).

This technique works fine on the 48K machine, but the 128K ROM removed the full table of 0xff bytes. However, it did leave 0xffff at 0x38ff, 0x39ff, 0x3aff and 0x3bff, which are sufficient to make this work if the data bus value is 0xff (as it "almost always" is). The +3 ROM has 0xffff only at 0x3bff, so setting I to 0x38, 0x39 or 0x3a will definitely not work on that machine.