SuperCPU rayed - Episode 7
IRQ programming with the SuperCPU
Where is the vector?
We are reminded of a very early course section: it was about Native and emulation
mode. The Native mode is not about how could initially
, for the new commands needed - namely the work also in the
emulation mode (this is also the reason why illegal Opcodes do not work).
However, in order to be able use 16 Bit-Akku and index register
, you will have to turn on every case in the native mode. Here the developers have
of the 65816 new vectors for the interrupts. The
most important thing, the for the IRQ is located in the Native mode no longer at $FFFE/ $FFFF, but
at $FFEE/ $FFEF. But what is all this? Apparently it has the
development thought in advance (well, it's a pity that something like that
is seldom the case today only): in Native Mode the battery you can at any time as well as the
X- and Y-registers between 8 and 16 bit mode. An
interrupt routine must be able
deal with registers in both conditions - finally they must be saved, if the
IRQ-routine be used! There is therefore a different IRQ for the Native Mode
vector, so that one can
switch between the two modes, if you accordingly, depending on the respective mode a concerted
IRQ-routine ready.
Let us recall a very early part of the course: It was about Native and
Emulation mode. The native mode is not about how to initially assume
could, required for new commands - the work namely in
Emulation mode (which is not the reason why illegal opcodes
can work). However, by 16 bit accumulator and index register to use
can, you have to switch to native mode in any case. Here, the
Developers of 65816 provided new vectors for the interrupts. The
most important, which is not in native mode for the IRQ at $ FFFE / $ FFFF,
but at $ FFEE / $ FFEF. But what's all this? Obviously it has in itself
made in advance of the development of thought (shame that something today only
rarely the case): In native mode, you can always switch the accumulator as well
the X-and Y-registers between 8 and 16 bit. Here an
Interrupt routine must be able to cope with registers in both
states - after all these must be saved if they
used in the IRQ routine! Therefore, there is for the Native fashion a
own IRQ vector, so you can, if you between the two modes
switches, each one according to instructions depending on the mode
IRQ routine ready.
Yes, but ...?
But for crying out loud what is with the good old vector at $ 0314/ $0315,
but otherwise the man always for IRQ-programming has used? The one could forget.
In truth namely the 6510 jumps to the address in a IRQ always
, in $FFFE/ $FFFF is saved. And the shows to the Rome - this is where
the tabs are saved, and only then is about $ 0314/ $0315 jump.
You surely remember: before each switch in the Native mode so far, we have
always carried out, and the CLI was a first came back
again, if the processor was in emulation mode. However, these were not as
solid in native mode, because no interrupts are possible, but for a different reason
: as already described, the IRQ-vector in Native Mode
with $FFEE/ $FFEF. The ROM is usually displayed, and - you sense it
probably already - what is in $FFEE/ $FFEF in Rome? The address $E505,
an operand to a JMP-command, a Betriebssystemroutine to
Screen-Spalten - and Zeilenermittlung starts. In short: determines any IRQ
-routine - even as it? Commodore 1982 could still
know nothing of 65816 (the was released), but it was not until 1985 that this processor
time thing that bothered ancestors in a unit called SuperCPU to your original C64
would be used. We must therefore either the IRQ lock in Native Mode, or
the ROM with LDA # $35 STA $01 hide and an IRQ-routine
letter. Where this is located, we then write to $FFEE/ $FFEF.
But what the hell is with the good old vector at $ 0314 / $ 0315, which one
but otherwise always for IRQ programming has used? That can safely
forgotten. In truth, namely the 6510 jumps at a IRQ always adhere to the
Address $ FFFE is stored in / $ FFFF. And the shows into ROM - there
the registers are saved and only then is about $ 0314 / $ 0315 jumped.
Surely you remember: Before changing the native mode we have
have always executed a SEI and CLI only came back when the
Processor in emulation was fashionable again. But this is not as
pulled through, because in native mode interrupts are not possible, but from
another reason: As already described is the IRQ vector in Native
Fashion at $ FFEE / $ FFEF. The usual approach, the ROM is visible, and - you guessed it
probably - what is at $ FFEE / $ FFEF in the ROM? The address $ E505,
an operand to a JMP instruction, the to an operating system routine
Screen column and row identification starts. In short: Definitely no
IRQ routine - how could they? Commodore was in 1982 but still nothing from 65816
know (which was only released in 1985) suspecting, let alone that this
Processor time in a device called SuperCPU used at their original C64
would be. Thus we must in native mode either the IRQ lock, or
but the ROM with LDA # $ 35 STA $ 01 Hide and an IRQ routine
. Write Where this is, we then write down $ FFEE / $ FFEF.
Here we go
The main problem with IRQ routines in native mode is the fact that the
Interrupt at any time to interrupt the main program, regardless of whether this
currently working with 8 or 16 bits. The IRQ routine saves the registers - the
Push commands work always the same, whether you 8 or 16 bits wide
Register pushes, or those stores with STA somewhere. But then you want to
of course also perform some operations, and since it bothers but then,
not knowing whether the accumulator and / or the index register just 8 or 16 bit
are - after all, would a LDX # $ 00, executed at slaked X flag
(Index registers are 16 bits) lead to chaos, since the command byte after
would the $ 00 yet with added taken to form the 16-bit value. Then
there will be a more or less fatal crash. But it is
nothing easier than the registers to shift the way they have
wants - after all, there are the commands REP and SEP which is the 16
Bit flags and delete can put. So far, so good - the IRQ routine is
processed and you can switch between modes kicking back and forth. Slow
approaches the interrupt routine to an end and we a problem. Because the
Registers must be restored, either as 8 - or as
16 bit registers!
Bypass?
Of course, there's an easy possibility to circumvent the whole problem -
just for demos or intros, this is certainly an acceptable way: One
omitted simply on a main program and laesstt everything is interrupt.
After the initialization part followed only a JMP to itself -
who does not need register, so we must not save them in the IRQ,
let alone us at 8 or 16 bit modes worry.
The direct solution
But suppose we do not leave anything in the main program
frame-oriented calculate or whatever, so that we solve the problem
solve instead want to avoid. As we can now command the register is 100% again
produce? In order modes recovery but we do not need to us
take care, because the flags are indeed at an IRQ automatically on the stack
saved and the interrupt end (RTI instruction) back retrieved. For us
but unfortunately too late, because we would have previously been very interested to see what
State of the M and X flags (for accumulator and index register) had. And here is
the key to a solution: At the beginning of the IRQ routine after the register
are already on the stack (according to their modes also correct), we save
us just continue the status register with all EMTeachline Flags - command
PHP. At the end of the IRQ routine now before the registers with
Pull restore commands again, we take this saved status with
PLP again from the stack - and M-and X-Flag are back in the
State that they had at the time the IRQ trigger. So we can safely
be that the subsequent pull-instructions exactly the right number of bytes
get for the corresponding register from the stack! Yes, and that's about it
- The problem is solved. Now you can in the main program anywhere between 8
and 16-bit switch, without being forced to worry that after an IRQ
maybe some high bytes are lost of 16 bit registers.
Raster interrupt
For habitually will be the IRQ, as suggested by the operating system,
about a CIA-timer can be triggered, but instead by the VIC - at a
certain raster line. When CIA you have to confirm with a LDA $ DC0D that
the IRQ was received and processed - that's what makes the Kernal at
$ EA7E. In VIC it works differently: You have to interrupt with LDA $ D019
STA $ D019 confirm. Confirmed to an interrupt - whether CIA or
VIC - not, immediately after the IRQ routines-end immediately in the
Jumped IRQ routine, because the C64 thinks the interrupt would have to still
are processed. Instead of LDA $ D019 STA $ D019 using many Coder
However, a DEC $ D019, $ D019 ASL or LSR $ D019 - do the same thing,
only it is shorter. In native mode of the 65816, however, reveals a
Curiosity, for which we also could not find any explanation: The DEC, ASL
or LSR variant shows to $ D019 no effect - you have already LDA STA
take. Hair Exactly the same routine that still worked in emulation mode goes,
when the native mode and IRQ vector at $ FFEE / $ FFEF no more.
The "cleaner" LDA $ D019 STA $ D019 is the one worry though again
going on.
Please wait
Many interrupt routines to a specific operation on a specific
Raster line Run. Let us take the simple example of a Rasterbar. Here
we wait for a raster line, timen with a short loop until we
are exactly at the end, and then quickly Change $ D020 and $ D021, thus,
when the VIC begins to draw the nearest grid line, that in a
other color appears. Then we wait again until shortly before the end of the line
and amend again, according to a color table, frame and
Background color. As a special uebel the Charline (Badline) has proved thereby,
since the VIC reads data from the screen and color RAM, but some time
needs and we therefore somewhat less than usual on hold
must hang until the next raster line is reached. Almost every
Assembler entrants are these raster beam an abomination, because until you
has understood why when you have to wait much, sometimes takes some
Time. Time also goes by the way, when we service the C64 until the
Raster line is over. About Taking the entire screen with
Grid bar, no longer even large jumps remains much screen time,
to make - and on hold while the beam structure is in each case
short that only real professional coders in there still accommodate routines.
More than 20 times faster?
With the SuperCPU one could now of course, the 20-fold amount of
Schleifendurchlaeufen wait, and would have also Gorgeous grid beams. But
There is another possibility, and we even get a
very large portion of the computing time, which is otherwise maintained, free for the
Main program! The SuperCPU is namely so fast that they at the beginning of
Raster line can alter the colors in time. One must not, as is
usual, already at the end of the previous grid line with its LDA from the
Color table to start, so you have time for the start of the new
Wrote raster line the value after $ D020/21. We leave the interrupt
just come on the line, where we want the first color, and
Write this in the VIC registers. After that we very, very much
Calculation time for the next raster line is reached and the next color
must be set. So we tell the VIC simply that he next in the
Raster line us again to say about it (an IRQ Release) so that we
then can put the next color. We provide the Registrar restores and
leave with RTI interrupt routine! Now available to the main program
Tons of clock cycles at disposal, for the calculations or similar
can be used. Meanwhile draws the VIC at rest the raster line.
Starts the next, the IRQ routine is called again, we Change
quickly the color and give control back immediately return to's
Main program. The wait for the next raster line is completely eliminated,
Thus, computation time is free. Waerde you Saemtliche existing raster lines of the
C64 pull over with scanning beams, so would not have time at 1 MHz
uebrigsein to do anything else because of poor computer mostly on
the next raster line waiting. With the SuperCPU but we have the same
Case for about 80% of computing time or more left (only one rating)!
The sample program
In Listing 7.1 Your whatâ everything explained here again see. First of is
turned the native mode and initialize the IRQ. Then, in a
Endless loop as the main program constantly 8-16 bit back and
hergeschaltet. To check is in 8-bit mode, the address $ D800, which is
the color of the sign above the left increases. Because this is done in 8-bit mode,
likely never be $ D801 affected, but this would be the case in 16 bit mode.
On these we then switch to namely and increase $ 0400 - is this
Address to $ FF is automatically incremented $ 0401. The IRQ can therefore
at any time be triggered - in 8 - or 16-bit mode. In the IRQ we save
Then, the register, using the routine itself, as well as the status to
later the registers according to regulations to be restored again. Then we turn
the index register to 8, the accumulator pack to 16 bit. Retrieve from a color table
we deal with a LDA at a stroke two values ??we after $ D020 (and
of course write down $ D021). Reminder: A LDA # $ 0102 STA $ D020
causes the $ 02 will be written by $ D020, while the $ 01
lands logically in $ D021. Then we raise $ D012, which is the
Grid line where the next IRQ will be triggered. Of course, we turn
before the accumulator again increased to 8 bits, otherwise would also $ D013, which we
certainly not necessarily want. The mixture is then queried whether we end up
our Rasterbar have arrived - if so, we let the next interrupt
again until the beginning of the Rasterbar auslaesen (for the next frame). For
Conclusion is communicated with LDA $ D019 STA $ D019 the VIC that we its IRQ
have received and processed - why, for example ASL $ D019 does not work
remains unexplained. By the way: If you in the main program frequently with 16 bit
works, kaennte the IRQ come too late a little, since the 16 bit instructions (although
they make the double work) usually one clock cycle need more.
But through clever programming of the IRQ routine lets itself the
offset - our example is by no means represents the ultimate solution
(w) Malte Mundt
©1999 Go64 Redax! & Count Zero/SCS*TRC for all HTML Stuff
[ Zum 6. Teil ][ Zum Index ][ Zum 8. Teil ]