12

I'm trying to learn about C64 interrupt handling (with the goal of putting it in practice). My understanding is that interrupts can be triggered by different sources but there is only one interrupt handler vector for all of them (apart from NMI and reset having their own vectors). It is possible to chain different interrupt handlers, but there are no dedicated interrupt handlers for different interrupt events.

For this reason I would assume that every interrupt handler would first have to check whether the event it is interested in had actually happened or whether the interrupt had been triggered by a different type of event. Yet every interrupt handler example I see just assumes that it was triggered by the right kind of event and proceeds to handle it. Even the default interrupt handler in the KERNAL ROM just seems to assume that it was triggered because 1/60 sec has elapsed and proceeds to increment the real time clock.

I found this article that briefly touches on this topic:

Interrupts [...] will call the same memory address. In a modern setting this would be as if you had to connect all your events to a single function, and then sort out which one has actually occurred.

But then it proceeds to show an example that does not check the interrupt source.

I also found the multiple interrupt service routines pattern, but it just keeps switching between a fixed number of interrupt handlers for the same number of interrupt triggers that follow each other in a regular repeating pattern.

Based on my findings above, it seems that there is no need to identify the IRQ source in interrupt handlers, or at least it is not a regular practice. Why?

2 Answers 2

15

To save space and execution time (and partly of necessity, cf. below), interrupt handlers are typically set up for the context they are used in with assumptions on expected system interrupt sources.

If you were to set up a context in which you might be receiving interrupts from both the VIC (maybe raster or sprite collision interrupt) and a CIA (maybe a timer fired, a TOD alarm triggered or a peripheral port signals) you would indeed need to determine the source of the interrupt to handle/acknowledge it correctly.

There is no concept of an interrupt source on the 6502/6510 and the C64 kernal provides no abstractions by itself. So basically, you have to beat about the known bushes and see what falls out. For instance, you can look at $D019 to determine if there's an unacknowledged VIC interrupt. Similarly, you'd look at $DC0D to see if a CIA1 had something to say (CIA2, with interrupt register $DD0D, triggers the NMI instead of the IRQ, but same principle applies to determine the NMI source).

But it gets worse. Because the IRQ (and NMI) can be triggered from anything in the expansion port as well, and who knows where some random cartridge has its I/O space and interrupt registers; there's no plug and play resource manager to track that kind of thing. ;) Fx, add a MIDI interface and it may trigger IRQs (or sometimes NMIs) whenever a MIDI event occurs.

So you will need to explicitly support the specific interrupt sources that are expected to occur and suffer the consequences if unexpected ones occur. :)

0
13

Based on my findings above, it seems that there is no need to identify the IRQ source in interrupt handlers, or at least it is not a regular practice. Why?

Because there are no unknown/unexpected interrupts?

The C64 is a rather simple machine, originally developed as a game console. Later usage is still much like one. C64 software assumes to be loaded as the only application and takes control of the whole machine. There is no concept of concurrent applications and extensions, if they exist at all are made specific for one application they extend - like adding a command to BASIC.

A program loaded owns the machine until power off.

There is always only one program loaded and in charge. It does not need to care for any previous loaded program or its interrupts. Only those interrupts enabled by this program will occur, thus it needs to care only for those.

When a program finishes it should disable all interrupts and restore all previous handlers, but more often than not, program termination is assumed to be done via a power cycle. Where others like Apple, Atari, BBC or MSX try to establish protocols for extensions and limited multi programming, the C64 stays true to its heritage.

Due this one program to rule them all 'feature' chances are slim to find any cooperative example sharing interrupts. Programms using multiple will do it in custom fashion. In addition, when interrupts are used for screen manipulation timing is essential and cycles are in short supply. This encourages tight programming, including interrupt state machines like mentioned. Depending on the task it may be faster to have every state put the next states routine address into the interrupt vector.

Long story short: Go with whatever pleases you. If your task isn't as tight, using a nice series of detection function, like suggested, may be good style.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .