DEN C64'er AUSGEREIZT (Teil 2)
INTERRUPTKURS
Lassen Sie uns das Wichtigste aus dem
ersten Teil des Kurses zusammenfassen.
a) Als erste Unterbrechungsanforderung
ist der Assemblerbefehl BRK ganannt
worden. Trifft der Prozessor auf solch
einen Befehl, dann wird indirekt über
die Adressen $0316 und $0317 ins Unterbrechungsprogramm gesprungen.
b) Als zweite Interrupt-Quelle wurden
die beiden CIAs genannt.
Ist IRQ-TIMER ($ DC00) auf Interrupt
programmiert, dann wird indirekt über
die Adressen $0314/$0315 vezweigt.
c) Der NMI-TIMER ($ DD00) wird auch als
Zwilling des IRQ-TIMERS bezeichnet
und läßt sich auch auf die gleiche
Weise programmieren. Der Unterschied
besteht in der Art des Interrups.
IRQ und NMI
Zu guter Letzt soll noch geklärt werden
was hinter diesen unterschiedlichen Begriffen steckt.
IRQ ( Interrupt ReQuest) Dies ist ein sogenannter maskierbarer
Interrupt. Maskierbar heißt, daß per Software gesagt werden kann, ob er ausgelöst
werden darf oder nicht. Das Abschalten
erfogt durch den Assemblerbefehl SEI und
das Einschalten durch CLI.
NMI ( Non Maskable Interrupt) Dieser Interrupt ist softwaremäßig nicht
abschaltbar. Ein NMI-Interrupt wird ausgelöst, durch Drücken der RESTORE-Taste
oder durch den NMI-TIMER ($ DD00) .
In beiden Fällen wird indirekt über die
Adressen $0318 und $0319 gesprungen.
Der VIDEO-INTERRUPT
Ein Interrupt kann aber auch durch andere Ereignisse als durch den Ablauf
eines Timers ausgelöst werden.
z.B. LIGHTPEN SPRITE-SPRITE-KOLLISION SPRITE-HINTERGUND KOLLISION RASTERZEILENINTERRUPT
Die ersten drei Interrupts sollen uns
hier nicht weiter interessieren. Den
RASTERINTERRUPT dagegen, könnte man ohne
Übertreibung als ein Reservoir unerschöpflicher Möglichkeiten bezeichnen.
Wer die zahlreichen neuen Entwicklungen
und Entdeckungen auf dem Softwaresektor
seit 1985 mitverfolgt hat, der kann sich
vorstellen wovon die Rede ist.
Ich denke dabei besonders an die vielen
Demos die seit Jahren den Public-Domain
Markt unsicher machen.
Einige dieser Werke sorgten sogar für
weltweites Aufsehen. Man denke nur an
das allgemeine Erstaunen, daß ein DEMO
der 1001 CREW seinerzeit auslöste. Zum
aller ersten Mal, seit der Herstellung
des C64' er, hatte es jemand geschafft, den Bildschirmrand durch einen programmiertechnischen Trick auszuschalten und
Graphiken auf der gesamten Bildschirmfläche darzustellen. Diese Entdeckung
löste eine einzigartige Experimentierwelle unter den Freaks aus, denn mit
einem Schlag wurde klar, daß der C64' er
doch etwas mehr zu bieten hatte, als aus
dem mageren Handbuch ersichtlich war. Es
gab zu der Zeit aber auch noch andere
Programmierer( gruppen) wie die 1001 CREW, die mit ihren Werken einen respektablen
Bekanntheitsgrad erreichten. Hierzu gehörten schillernde Gestallten wie FLASH, S0 DAN, THE JUDGES, THE CREAM CRACKERS, WOM, STAR FRONTIERS und MEANTEAM.
Heutzutage sind es eher Gruppen wie
HORIZON, UPFRONT und BEYOND FORCE, die
versuchen durch eine immer raffinierter
werdende Ausnutzung der Interrupttechnik
an die Grenzen des guten alten C64' er zu
stoßen. Und was da auf den Bildschirm
gezaubert wird, stellt manchmal sogar
AMIGA und ST in den Schatten.
Einige der Routinen, die den erwähnten
Gruppen zu Ruhm und Ehre verhalfen, werden in dieser und weiteren Ausgaben
vorgestellt. Doch bevor wir uns auf
die Programmierung von komplizierten
Routinen stürzen, wollen wir anhand eines
einfachen Beispiels die Funktionsweise
der Raster-Unterbrechung erläutern.
DER RASTER-INTERRUPT
Wie Sie vieleicht wissen, wird das Bild
auf dem Monitor oder dem Fernseher durch
einen Elektronenstrahl erzeugt, der mit
hoher Geschwindigkeit Rasterzeile für
Rasterzeile abarbeitet. Ohne an dieser Stelle allzusehr in technische Einzelheiten einzugehen, soll hier nur erwähnt
werden, das sich der gesamte Bildschirm
aus 312 Rasterzeilen zusammensetzt. Von
disen 312 Rasterzeilen bilden 200 das
Textfenster. Die restlichen 112 befinden
sich im Rand oder unterhalb des Randes.
Zwei Register des Video-Chips stehen mit
dem Elektronenstrahl in direkter Verbindung:
$ D011$ D012
Es ist nun so, daß diese beiden Register
eine DOPPELFUNKTION haben:
a) Werden sie ausgelesen, dann erhällt man die aktuelle Rasterzeile, die gerade aufgebaut wird.
b) Wird ein Wert hineingeschrieben, dann
ist die so festgelegte Rasterzeile
der Auslöser des IRQ. Bei $ D011 ist
nur Bit 7 von Bedeutung. Es stellt
Hi-Byte des Rasterstrahls dar.
In dem folgenden Programm, wird gleich
an drei verschiedenen Stellen des Bildschirms ein Rasterinterrupt ausgelöst.
;*** RASTER-DEMO 1 *** ;***** Initialisierung ***** 1000 SEI ;IRQ sperren 1001 LDA #$7F ;Timer-Interrupt 1003 STA $DC0D ;abschalten!!! 1006 LDA $DC0D ;ICR löschen 1009 LDA #$00 ;Rasterzeile $00 als 100B STA $d012 ;IRQ-Auslöser festlegen 100E LDA $D011 ;Bit 7 (Hi-Position) 1011 AND #$7F ;löschen 1013 STA $D011 1016 LDA #$01 ;Raster als IRQ-Quelle 1018 STA $D01A ;wählen 101B LDX #$27 ;IRQ-Vektor auf 101D LDY #$10 ;Interrupt Routine Nr.1 101F STX $0314 ;richten 1022 STY $0315 1025 CLI ;IRQ freigeben 1026 RTS ;***** ERSTER INTERRUPT ***** 1027 LDA #$70 ;RASTERZEILE $70 als 1029 STA $D012 ;IRQ-Auslöser festlegen 102c DEC $D019 ;IRR Register löschen 102F LDX #$44 ;IRQ-Vektor auf 1031 LDY #$10 ;RASTER-Routine Nr.2 1033 STX $0314 ;richten 1036 STY $0315 1039 LDA #$00 ;Rahmen- und 103B STA $D020 ;Hintergrundfarbe 103E STA $D021 ;auf schwarz setzen 1041 JMP $FEBC ;Return from Interrupt ;***** ZWEITER INTERRUPT ***** 1044 LDA #$C0 ;RASTERZELE $c0 als 1046 STA $D012 ;IRQ-Auslöser festlegen 1049 DEC $D019 ;IRR Register löschen 104C LDX #$61 ;IRQ-Vektor auf 104E LDY #$10 ;RASTER-Routine Nr.3 1050 STX $0314 ;richten 1053 STY $0315 1056 LDA #$02 ;Rahmen- und 1058 STA $D020 ;Hintergrundfarbe 105B STA $D021 ;auf rot setzen 105E JMP $FEBC ;Return from Interrupt ;***** DRITTER INTERRUPT ***** 1061 LDA #$00 ;RASTERZEILE $00 als 1063 STA $D012 ;IRQ-Auslöser festlegen 1066 DEC $D019 ;IRR Register löschen 1069 LDX #$27 ;IRQ-Vektor auf 106B LDY #$10 ;RASTER-Routine Nr.1 106D STX $0314 ;richten 1070 STY $0315 1073 LDA #$07 ;Rahmen- und 1075 STA $D020 ;Hintergrundfarbe 1078 STA $D021 ;auf gelb setzen 107B JMP $EA31 ;Return from Interrupt
Sobald Sie das Programm mit ' SYS 4096' starten, lösen die Rasterzeilen $00,$70 und $ c0 fortlaufend Interrupte aus.
Da jeder Interrupt dazu benutzt wird, Rahmenund Hintergrundfarbe zu ändern, entsteht ein Effekt, der eine gewisse
Ähnlichkeit mit der deutschen Fahne hat.
Gleich zu Beginn der Initialisierung
wird der Interrupt gesperrt( SEI) und der
TIMER-IRQ abgeschaltet.
Als nächstes müssen wir festlegen, daß
RASTERZELE $00 Auslöser des erster Interupts ist. Zu diesem Zweck schreibt man
den Wert $0 in $ d012 und löscht BIT 7 in
$ D011 . Dieses BIT stellt die Hi-Position
des Rasterstrahls dar und muß nur dann
gesetzt werden, falls der IRQ irgendwo
im untern Rand ausgelöst werden soll.
Durch Löschen oder Setzen der BITS des
Registers $ D01 A wird festgelegt, welches
Ereignis IRQ-Auslöser sein soll.
BIT 0 ;RASTERINTERRUPT ($D012) BIT 1 ;SPRITE-HINTERGR.Koll. ($D01F) BIT 2 ;SPRITE-SPRITE Koll. ($D01E) BIT 3 ;LIGHTPEN sendet Impuls
Da wir uns für eine Unterbrechung durch
den Rasterstrahl entschieden haben, muß
der Wert $1 in $ D01 A geschrieben werden.
Zu guter Letzt müssen wir wieder einmal
den IRQ-Vektor $0314/0315 umstellen.
Nun müssen wir aber aufpassen, denn die
gleichen Adressen werden auch vom TIMER-IRQ als Sprungvektoren benutzt. Hätten
wir den Timer-IRQ nicht abgestellt, so
würden beide Interrupts abwechselnd und
völlig unkontrolliert dieselbe Routine
anspingen. Das Ergebnis wäre ein totales
Durcheinander, gefolgt von einem Absturz.
Damit wären fast alle Vorbereitungen
getroffen. Der Rest liegt nun ganz bei
unserer IRQ-Routine die an Adresse $1027 beginnt.
Sobald der Elektronenstrahl mit Rasterzeile $00 in Berührung kommt, wird der
erste Interrupt ausgelöst und die CPU
führt das Programm an Adresse $1027 aus.
Die folgende Beschreibung gilt für alle
Routinen die durch einen RASTERINTERRUPT
angesprungen werden:
1) Als erstes wird die neue Rasterzeile
festgelegt, die als nächstes Interrupt
auslösen soll.
2) IRQ-Request- Register ($ D019) löschen.
Falls der Interrupt durch den Raster
ausgelöst wurde, ist BIT 7 gesetzt.
Das Löschen erfolgt, indem man das
Register ausliest und den selben Wert
gleich wieder zurückschreibt.
z. B. LDA $ D019 STA $ D019 oder einfacher: DEC $ D0193) Will man mehrere Interrupte der Reihe
nach auslösen, dann muß der IRQ-Vektor
erneut umgestellt werden.
4) Erst jetzt kommt die eigentliche Aufgabe der Unterbrechung. In unserem
Beispiel ändern wir nur die Farben.
Sie können aber auch genau so gut eine
Musikoder eine Joystick-Routine anspringen.
5) Die Unterbrechung wird abgeschlossen
durch einen Sprung zum Ende der normalen IRQ-Routine.
Unser erstes Rasterdemo besteht aus 3 kurzen Routinen die der Reihe nach angesprungen werden und somit den Bildschirm
in 3 Farbzonen einteilen. Theoretisch
könnte man beliebig viele Routinen aneinander reihen und so den Bildschirm in
allen Farben schillern lassen.
Die folgenden Befehle geben dem Benutzer
die Möglichkeit die Routine wieder abzuschalten. Start mit SYS4140
SEI ;IRQ sperren LDA #$81 ;Timer-IRQ STA $DC0D ;einschalten LDA #$00 ;Raster-IRQ STA $D01A ;abschlten LDX #$31 ;IRQ-Vektor LDY #$EA ;auf ursprünglichen STX $0314 ;Wert setzen STY $0315 CLI ;IRQ freigeben RTS
Der Rasterinterrupt erlaubt aber noch
eine große Anzahl weiterer Effekte. Versuchen sie doch mal Text mit Hochauflösender Graphik zu mischen oder mehrere
Zeichensätze auf einmal darzustellen.
Selbst die Darstellung von mehr als acht
Sprites gleichzeitig oder das Scrollen
von einzelnen Bildschirmteilen lassen
sich nun ( fast) problemlos realisieren.
Als nächstes wollen wir uns wieder einmal mit Farbeffekten befassen und auch
eine Spezialroutine vorstellen.
Wer sich unter ' RASTER-PROGRAMMIERUNG' nichts konkretes vorstellen kann, sollte
sollte am besten gleich ' RASTER-DEMO 2' einladen und und mit SYS4096 starten.
Diese interessanten Farbverläufe, wie
sie in fast allen DEMOS der letzten Zeit
geboten werden, nennt man RASTEREFFEKTE.
Sie entstehen durch Ändern von Rahmenund Hintergrundfarbe zu Beginn jeder
Rasterzeile.
Mit dem nun folgenden Source-Listing
ist es möglich solche Rastereffekte auf
ganz einfache Weise zu programmieren.
;*** RASTER-DEMO 2 *** 1000 SEI ;IRQ sperren 1001 LDA #$7F ;Timer-Interrupt 1003 STA $DC0D ;abschalten!!! 1006 LDA $DC0D ;ICR löschen 1009 LDA #$82 ;Rasterzeile $82 als 100B STA $d012 ;IRQ-Auslöser festlegen 100E LDA $D011 ;Bit 7 (Hi-Position) 1011 AND #$7F ;löschen 1013 STA $D011 1016 LDA #$01 ;Raster als IRQ-Quelle 1018 STA $D01A ;wählen 101B LDX #$27 ;IRQ-Vektor auf 101D LDY #$10 ;Interrupt Routine Nr.1 101F STX $0314 ;richten 1022 STY $0315 1025 CLI ;IRQ freigeben 1026 RTS ;--------------------------------------- 1027 LDA #$82 ;RASTERZEILE $82 als 1029 STA $D012 ;IRQ-Auslöser festlegen 102C LDA #$1B 102E STA $D011 1031 DEC $D019 ;IRR Register löschen 1034 LDX #$27 ;IRQ-Vektor 1036 LDY #$10 ;auf sich selbst 1038 STX $0314 ;richten 103B STY $0315 103E NOP 103F LDY #$00 ;ZEILENZÄHLER 1041 LDX #$08 ;CHARACTER-ZÄHLER 1043 LDA $1100,Y ;Farbwert aus Tabelle 1046 STA $D020 ;Rahmen- und 1049 STA $D021 ;Hintergrund ändern 104C INY ;ZEILENZÄHLER+1 104D DEX ;CHARACTER-ZEILE ? 104E BEQ 1041 ;JA? Dann neue Farbe 1050 LDA $1026 ;Sonst verzögern 1053 JSR $1026 1056 JSR $1026 1059 JSR $1026 105C CPY #$48 ;Routine beenden 105E BCC 1043 ;NEIN?? dann neue Farbe 1060 LDA #$0E ;Sonst IRQ beenden 1062 STA $D020 1065 LDA #$06 1067 STA $D021 106A JMP $EA31 ;Sprung zum IRQ-Ende
Um das obige Listing zu verstehen, ist
es unbedingt notwendig, sich mit einigen
technischen Besonderheiten des VIC-Chips
und des CPU auseinander zu setzen.
Um einen Assembler-Befehl auszuführen, braucht der Prozessor eine gewisse Zeit.
Diese Zeit wird in TAKTZYKLEN gemessen.
Ein Befehl benötigt in der Regel 2 bis
7 Taktzyklen. Einige ' Illegalen-Opcodes' benötigen sogar 8 Taktzyklen.
Zuvor haben wir erfahren, daß das Bild
auf dem Monitor oder Fernseher von einem
Elektronenstrahl erstellt wird. Dies geschied mit großer Geschwindigkeit, denn
immerhin wird das Bild 20 mal pro Sekunde
erneuert.
Um eine einzige Rasterzeile zu zeichnen," vergehen" im Normalfall genau 63 Taktzyklen. Man müßte eigentlich nur eine
Schleife in Maschinensprache schreiben, die alle 63 Taktzyklen die Bildfarben
ändert. Das alles klingt schon wahnsinnig
kompliziert, aber es wird gleich noch
komplizierter. Der Haken ist nämlich der, daß der Prozessor in regelmäßigen Abständen unterbrochen wird und deshalb
ungleichmäßig läuft.
Diese Unterbrechung erfolgt jedesmal
durch den VIC-Chip, der eine gewisse Zeit
benötigt, um die CHARACTER-ZEILEN zu regenerieren.
Diese Unterbrechung erfolgt jede achte
Rasterzeile und jedesmal am Anfang einer
CHARACTER-ZEILE für genau 42 Taktzyklen.
Mit diesen Informationen ist es uns nun
möglich, den Ablauf des Source-Listings
nachzuvollziehen.
In der Initialisierung wird Rasterzeile
$82 als IRQ-Auslöser festgelegt. Von nun
an laufen alle IRQs über unsere eigene
Routine die bei $1027 beginnt.
Da es in diesem Beispiel nur eine einzige Routine gibt, die fortlaufend angesprungen wird, ist es erforderlich, die
Vektoren jedesmal auf sich selbst zu
richtenen.
Da wir inzwischen wissen, daß jede achte
Rasterzeile ein besonderes ' TIMING' erfordert, haben wir einfach das Prinzip
der GESCHACHTELTEN-SCHLEIFEN angewand.
Das Y-Register ist der Zähler für die
Anzahl der RASTERZEILEN die durchlaufen
werden.
Das X-Register ist eine Art Indikator
für alle Rasterzeilen mit gesondertem
Timing, daß in jeder Rasterzeile um den
Wert 1 verringert wird. Ist der Wert 0 erreicht worden( ZERO-FLAG wird gesetzt), so erfolgt ein Rücksprung an die Adresse
$1041 . Die so entstandene Schleife hat
genau 21 Taktzyklen.
Sollte das X-Register den Wert 0 noch
nicht erreicht haben, so wird die Laufzeit um 42 Taktzyklen verlängert.
Bei Adresse $1000 wird das Y-Register
mit der Anzahl der Rasterzeilen die dargestellt werden verglichen. Ist der Wert
größer, dann erfolgt ein Sprung zum IRQ
Ende.
Die Routine erlaubt noch einige Experimente. Aus Adresse $1043 ist ersichtlich, daß sämtliche Farbwerte aus der Tabelle
bei $105 C geholt werden ( LDA $1100, Y) .
Wollen sie andere Farben darstellen, dann müssen Sie mit einem Monitor die
Zahlenwerte in dieser Tabelle ändern.
Besonders gut - finde ichsieht das
Ganze aus, wenn man sehr weiche Farbverläufe darstellt und diese zusätzlich
noch bewegt werden.
Sie sehen, der Raster-Interupt ist ein
sehr interessantes Spielzeug, das eine
Fülle von Varriationen zu bieten hat.
(IVO HERZEG)