Your Spectrum
Issue 17, August 1985 - Interrupt Manager
Home Contents KwikPik

See also these letters about the article:
Issue 19"Grid Bug"
Issue 20"More Interruptions"

J U S T   A   T I C K !
It may be rude to interrupt but it's certainly dead easy now, 'cos Toni Baker's back with a program that lets you have up to sixteen interrupt routines running at once. You'll wonder how you ever managed before!
You may have noticed just how many routines there are these days that are interrupt driven - that's to say, routines that make use of the Spectrum's interrupts. They're run automatically once every TV frame (50 times per second) and they make it quite possible for the Spectrum to appear to be doing two things at once.
The big drawback is that they're all pretty exclusive. If you've got one running it's very difficult to get another one running at the same time. You can have, for instance, a real time clock or moving sprites or continuous music - all during the running of normal Basic,
of course, but you can't have more than one at once - or, at least, it's more than a little tricky.


This program provides the solution - it's called an Interrupt Manager and with it you can have up to sixteen user- defined interrupt routines running together. One routine, say, runs a clock, another plays music and both could run together quite happily without disturbing normal Basic or machine code.
The Interrupt Manager not only knots the separate interrupt routines
together but it can also save space by making each interrupt routine a little simpler. For instance, it's normally necessary in an interrupt routine to preserve all the registers. The manager looks after that for you so you can corrupt the registers as much as you like. You'll only need to take special action if you want to make use of the alternative registers as well.
Another point that's often glossed over is that many interrupt routines need to take very special precautions when calling routines in the ROM. If you don't, and you have Interface 1 attached, then the Spectrum's very

This is the Interrupt Manager. We haven't presented you with a Hex Loader program to help you type it in - it's not that we're mean (though we are, of course) it's just that to use the program fully you'll really need an Assembler. To make the whole routine work, you must first call it by typing RAND USR 61441. This clears the complete Manager table and makes sure the routine's accessed every 50th of a second.
EFFF               ORG  0EFFFH
These two bytes store the address of the Manager program. The low byte of this address must always be FF - for example, we've located it at 0EFFh.
F001 2167F0  INITI LD   HL,TABLE
This part of the program must be called for the Manger to work - it may also be called while the Manger is in operation, when it cancels all the user-defined routines from the table.
F004 1168F0        LD   DE,TABLE+1
F007 015000        LD   BC,0050H
F00A 3600          LD   (HL),0
Resets the table flags.
F00C EDB0          LDIR
Resets the remainder of the table.
F00E 3EEF          LD   A,0EFH
Loads the A register with the high byte of the interrupt vector (INTVC).
F010 ED47          LD   I,A
Copies the value in the A register into the interrupt register.
F012 ED5E          IM2
Selects interrupt mode 2 - this is the mode that allows you to use your own interrupt routines on the Spectrum rather than the one in the ROM.
F014 C9            RET
F015 F5      MNGER PUSH AF
The Interrupt Manager program starts here. This is called by the interrupt procedure fifty times a second.
F016 E5            PUSH HL
F017 2167F0        LD   HL,TABLE
Points HL to the Manager table.
F01A 7E            LD   A,(HL)
Loads the A register with the main table flags.
F01B 23            INC  HL
Points HL to the first entry in the table.
F01C 1F            RRA
F01D D43800        CALL NC,0038H
Calls the ROM interrupt procedure if it's required.
F020 1F            RRA
F021 303F          JR   NC,MNOFF
F023 F3            DI
F024 C5            PUSH BC
F025 D5            PUSH DE
F026 0610          LD   B,10H
F028 5E      MNLOP LD   E,(HL)
F029 23            INC  HL
F02A 56            LD   D,(HL)
Loads DE with the routine address (if specified).
F02B 23            INC  HL
F02C 4E            LD   C,(HL)
Loads C with the flags for the routine.
F02D 23            INC  HL
F02E CB29          SRA  C
F030 302A          JR   NC,NONOW
Jumps if the routine is de-activated.
F032 35            DEC  (HL)
F033 2027          JR   NZ,NONOW
Jumps unless the routine has priority.
F035 23            INC  HL
F036 7E            LD   A,(HL)
Loads A with the normal routine priority.
F037 2B            DEC  HL
F038 77            LD   (HL),A
Stores the priority.
F039 C5            PUSH BC
F03A E5            PUSH HL
F03B EB            EX   DE,HL
Places the routine address into HL.
F03C 3A0000        LD   A,(0000H)
Loads A with the first byte of ROM. If A holds F3 hex then the Spectrum ROM is in use, but if it holds E1 hex then the shadow ROM is in use.
F03F A9            X0R  C
F040 FEF0          CP   0F0H
F042 2811          JR   Z,SHFRS
Jumps to call a shadow ROM routine.
F044 FEE0          CP   0E0H
F046 2805          JR   Z,SPFRS
Jumps to call a Spectrum ROM routine.
F048 CD66F0        CALL MNCAL
Call a sub-routine that's in the current ROM.
F04B 180D          JR   RETIN
F04D 2251F0  SPFRS LD   (SPJP),HL
Stores the routine address within the program.
F050 D7            RST  10H
Calls a Spectrum ROM routine.
0002         SPJP  DEFS 02H
F053 1805          JR   RETIN
F055 22ED5C  SHFRS LD   (5CEDH),HL
F058 CF            RST  08H
Calls a shadow ROM routine.
F059 32            DEFB 32H
F05A E1      RETIN POP  HL
Puts the address of the Manager table into HL.
F05B C1            POP  BC
Puts the count of the remaining entries into the B register.
F05C 23      NONOW INC  HL
F05D 23            INC  HL
HL now points to the next entry in the table.
F05E 10C8          DJNZ MNLOP
F060 D1            POP  DE
F061 C1            POP  BC
F062 E1      MNOFF POP  HL
F063 F1            POP  AF
F064 FB            EI
F065 C9            RET
F066 E9      MNCAL JP   (HL)
Jumps to the sub-routine at the address stored in HL.
0051         TABLE DEFS 81
Eighty-one bytes of memory are set aside for the table.

Interrupt Table diagram
likely to crash if an interrupt occurs whilst the Shadow ROM's paged in. The Interrupt Manager program avoids this trap - at each stage it'll determine which ROM is current, which ROM is needed, and it'll switch between the two as desired. In other words, the individual interrupt routines don't have to concern themselves with worrying about ROMs - the Manager will take care of it all.
Also, interrupt routines usually require a RST 38 instruction. This ensures that the keyboard is properly
scanned for Basic. Not so with the Manager though. RST 38 is automatic, and individual routines needn't concern themselves with it. Still, you can deactivate this facility if, for example, you want to modify the keyboard scan or do without it altogether.


OK, so now you've got an Interrupt Manager, what are you going to do with it? Just to get you started here's a selection of simple routines that have been compiled to show you how easily the Manager can be used. If you want a demo, type them into your Assembler at memory location 61800. Once you've got the Manager and the demo program in memory you're ready to go. As you'll see the first routine randomly changes the border colour - to make it work, type:


This places the address of the routine on the Manager table - in this case the high byte is 241 (F1h) and the low byte is 104 (68h). Now type:


If the counter and the priority both hold 10, this
means that the routine will be called every ten 50ths of a second - of course, you can change this as you please. Now (finally) type:


The flags hold the info that tells the Manager which of the two ROMs to access if they're needed, or even if the routine's to be called at all. In this case the flags should be 1.
In all these examples TABLE refers to the start location in memory of the Manager table which here is 61543. Now number your routine according to where on the table it's to appear - the number you assign it is, of course, INTNO.
To use the other four routines, all you've got to do is change the values for the low and high bytes, the counter, the priority and the flag. The last demo routine is the only one where the choice of ROM is important as it uses the Spectrum's, so make sure you have the correct value in FLAGS when you're mucking about with it.
Finally, if you still can't get the demo to work, change the value in the master Flag at 61543 to 2.
F168                ORG  61800
F168 ED5B785C BORDC LD   DE,(23672)
F16C 1A             LD   A,(DE)
F16D E607           AND  7
F16F D3FE           OUT  (254),A
F171 C9             RET
This is a simple routine that changes the colour of the border at random.
F172 210058   INKCH LD   HL,22528
F175 7E       ICLOP LD   A,(HL)
F176 E6F8           AND  248
F178 4F             LD   C,A
F179 ED5F           LD   A,R
F17B E607           AND  7
F17D B1             OR   C
F17E 77             LD   (HL),A
F17F 23             INC  HL
F180 3E5B           LD   A,91
F182 BC             CP   H
F183 C8             RET  Z
F184 18EF           JR   ICLOP
This is a slightly more complicated routine that randomly changes the first three bits of every byte in the attributes file and so changes all the Ink colours.
F186 210058   PAPCH LD   HL,22528
F189 7E       PCLOP LD   A,(HL)
F18A E6C8           AND  200
F18C 4F             LD   C,A
F18D ED5F           LD   A,R
F18F E638           AND  56
F191 B1             OR   C
F192 77             LD   (HL),A
F193 23             INC  HL
F194 3E5B           LD   A,91
F196 BC             CP   H
F197 C8             RET  Z
F198 18EF           JR   PCLOP
This is very similar to the previous routine but changes the Paper colours.
F19A 210040   SCRGB LD   HL,16384
F19D 7E       SCRLP LD   A,(HL)
F19E CB0F           RRC  A
F1A0 A7             AND  A
F1A1 77             LD   (HL),A
F1A2 23             INC  HL
F1A3 3E58           LD   A,88
F1A5 BC             CP   H
F1A6 C8             RET  Z
F1A7 18F4           JR   SCRLP
This routine does a wrap-around scroll to the right on each character on the screen within its own character block.
F1A9 110A00   KEYBP LD   DE,10
F1AC 21D007         LD   HL,2000
F1AF 3A085C         LD   A,(23560)
F1B2 6F             LD   L,A
F1B3 CDB503         CALL 949
F1B6 C9             RET
This routine produces a short bleep and the frequency depends on the last key that was pressed.
Home Contents KwikPik