IRQ-KURS
"Die Hardware ausgetrickst..."
(Teil 8)
----------------------------------------
Herzlich willkommen zum achten Teil un-
seres Raster-IRQ-Kurses. Heute wollen
wir uns mit einem besonders interessan-
ten Rastertrick beschäftigen: der FLI-
Routine, die es uns ermöglicht, Grafiken
mit mehr als 2 Farben im Hires-Modus,
bzw. mehr als 4 Farben im Multicolor-
Modus, jeweils pro 8x8-Pixel-Block, dar-
zustellen. Durch die dabei entstehende
Farbvielfalt können sehr eindrucksvolle
Bilder angezeigt werden, die bei ge-
schickten Grafikern schon an die Qua-
lität von Amiga-Bildern reichen können!
1) GRUNDLAGEN
Wollen wir uns zunächst einmal an-
schauen, wie der VIC vorgeht, um eine
Bitmap-Grafik auf den Bildschirm zu zau-
bern:
Zunächst einmal muß der Grafikmodus ein-
geschaltet werden, wobei die Lage der
Bitmap im Speicher mitangegeben wird.
Nun zeigt der VIC also die Bits des an-
gegegebenen Speicherbereichs als einzel-
ne Pixel auf dem Bildschirm an. Um die-
sen Pixeln nun auch noch Farbe zu ver-
leihen, muß in zwei Fälle unterschieden
werden:
a) DER HIRES-MODUS
Hier bestimmt ein Farbcode im Video-RAM,
das im Textmodus zur Darstellung der
Zeichen benutzt wird und sich normaler-
weise bei $0400 (dez. 1024) befindet,
die Farbe der Pixel innerhalb eines
8x8-Pixel-Blocks. So legt das erste Byte
des Video-RAMs (als Zeichen ganz links
oben), die Farbe für die 8x8, im Grafik-
modus quasi "über" ihm liegenden, Pixel
fest. Das zweite Byte ist für den näch-
sten 8x8-Pixel-Block zuständig, und so
weiter. Da der VIC insgesamt nur 16 Far-
ben kennt, sind dabei jeweils nur die
unteren vier Bits eines Video-RAM-Bytes
von Bedeutung. Die oberen vier sind un-
benutzt und werden ignoriert.
b) DER MULTICOLOR-MODUS
In diesem Modus werden zwei nebeneinan-
der liegende Pixel jeweils zu einem
Farbcode zusammengefasst. Sind beide 0,
so erscheint an ihrer Stelle die Hinter-
grundfarbe, sind beide auf 1, so wird
für beide die Farbe aus einem äquvalen-
ten Byte des Color-RAMs geholt (bei
Adresse $D800 - dez. 55296), das norma-
lerweise zur Farbgebung der einzelnen
Zeichen im Textmodus verwendet wird. Bei
der Bitkombination "10" wird wieder das
Lownibble (die unteren vier Bits) des
Video-RAMs zur Farbgebung ausgewertet.
Bei der Bitkombination "10" sind die, im
Hires-Modus unbenutzten, oberen vier
Bits des Video-RAMs für die Pixelfarbe
zuständig. Sie sehen also, daß das Vi-
deo-RAM im Multicolormodus gleich zwei
Farbwerte für Pixelkombinationen fest-
legt.
2) DAS FLI-PRINZIP
Soviel zur Darstellung einer Grafik.
Sicherlich ist Ihnen bei den obigen
Ausführungen das häufige Auftreten des
Begriffs "Video-RAM", bzw. "Video-Map"
aufgefallen. Und genau dieser Begriff
ist der Schlüssel zu unserer FLI-
Routine. Wie Sie vielleicht wissen, kann
man die Lage der Video-Map, innerhalb
des Adressierungsbereichs des VICs (im
Normalfall von $0000-$3FFF) in 1KB-
Schritten verschieben. Hierfür ist Regi-
ster 24 des VICs (Adresse $D018 - dez.
53272) zuständig. Seine oberen 4 Bits
geben die Lage der Video-Map an, also
des RAM-Bereichs, der für die Darstel-
lung der Textzeichen, bzw. im Grafikmo-
dus der Farbzeichen, zuständig ist. Die
unteren Bits von 0-3 bestimmen die Lage
des Zeichengenerators, also des Spei-
cherbereichs, in dem die Daten für den
Zeichensatz ausgelesen werden. Dies soll
uns hier jedoch nicht interessieren und
sei nur nebenbei angemerkt.
Konzentrieren wir uns auf die Bits 4-7:
Sie bestimmen die Lage des Video-RAMs
innerhalb des 16KB-Bereichs des VICs.
Die im Folgenden angegebenen Adressen
verstehen sich also als Offsets, die auf
die Startadresse des 16KB-Bereichs auf-
addiert werden müssen:
Wert Bits Bereich (Hex) Bereich (Dez)
---------------------------------------
0: 0000 $0000-$03FF 0- 1023
1: 0001 $0400-$07FF 1024- 2047
2: 0010 $0800-$0BFF 2048- 3071
3: 0011 $0CFF-$0FFF 3072- 4095
4: 0100 $1000-$13FF 4096- 5119
5: 0101 $1400-$17FF 5120- 6143
6: 0110 $1800-$1BFF 6144- 7167
7: 0111 $1CFF-$1FFF 7168- 8191
8: 1000 $2000-$23FF 8192- 9215
9: 1001 $2400-$27FF 9216-10239
10: 1010 $2800-$2BFF 10240-11263
11: 1011 $2CFF-$2FFF 11264-12287
12: 1100 $3000-$33FF 12288-13311
13: 1101 $3400-$37FF 13312-14335
14: 1110 $3800-$3BFF 14336-15359
15: 1111 $3CFF-$3FFF 15360-16383
Obwohl die Video-Map nur 1000 Bytes lang
ist, habe ich hier dennoch 1024-Byte-
Bereiche angegeben. Das hat nämlich auch
eine Bedeutung für den nächsten Kurs-
teil.
Desweiteren wollen wir noch schnell kl-
ären, wie man den 16KB-Bereich des VICs
verschiebt, da die FLI-Routine eine Men-
ge Video-Speicher benötigt (nämlich die
vollen 16KB), sollten wir den VIC in
einem Bereich arbeiten lassen, in dem
wir nicht auf Zeropage-Adressen und
Sprungvektoren (die im ersten VIC-
Bereich - von $0000-$3FFF - eine Menge
Platz wegnehmen) Rücksicht nehmen zu
müssen.
Der Adressbereich des VIC wird nun mit
den untersten zwei Bits der Adresse
$DD00 (dez. 56576) angegeben (richtig:
dies ist ein CIA-B Register, das dem VIC
seinen Adressbereich vorschreibt). Hier
eine Auflistung der möglichen Bitkombi-
nationen und der Adressbereiche die sie
aktivieren:
3: 11 $0000-$3FFF 0-16383
2: 10 $4000-$7FFF 16384-32767
1: 01 $8000-$BFFF 32768-49151
0: 00 $C000-$FFFF 49152-65535
In unserem Programmbeispielen werden wir
den VIC-Bereich nach $4000 verschieben,
womit der Wert 2 in die Adresse $DD00
geschrieben werden muß. Die tatsächliche
Adresse der Video-Map ist dann immer
$4000 plus der oben angegebenen Offseta-
dresse.
Nachdem wir nun also die Grundlagen
gelkärt hätten, ist die Erklärung des
Prinzips der FLI-Routine höchst simpel:
Zum Einen wissen wir, daß die Video-Map
zur Farbgebung der Grafik verwendet
wird. Zum Anderen haben wir gesehen, wie
die Startadresse, aus der der VIC sich
die Video-Map-Daten holt, verschoben
werden kann. Was liegt nun also näher
als zwei und zwei zusammenzuzählen, und
eine Raster-IRQ-Routine zu schreiben,
die in JEDER Rasterzeile eine andere
Video-Map aktiviert? Die Folge dieser
Operation wäre dann nämlich die Möglich-
keit, einem 8x8-Pixel Block der Grafik
in jeder Zeile eine neue Farbe zuzutei-
len (im Multicolormodus sogar 2), so daß
wir die 2-, bzw. 4-Farbeinschränkung auf
einen Bereich von 1x8 Pixeln reduzieren!
3) DIE UMSETZUNG
Vom Prinzip her klingt das natürlich
sehr einfach, jedoch stellt sich uns
noch ein kleines Problem in den Weg:
Wie wir bei der Beschreibung des FLD-
Effektes schon gelernt hatten, liest der
VIC ja nur in jeder Charakterzeile (also
jede achte Rasterzeile), die 40 Bytes,
die er in den folgenden acht Rasterzei-
len darzustellen hat. Somit würde ein
einfaches Umschalten auf eine neue Vi-
deo-Map nichts bewirken, da der VIC ja
immer noch mit den 40 Zeichen, die er zu
Beginn der Charakterzeile gelesen hat,
die folgenden Zeilen darstellen würde -
und das selbst bei umgeschalteter Video-
Map. Also müssen wir ihn auch hier mit
einem kleinen Raster-Trick "veräppeln".
Man kann den VIC nämlich auch dazu zwin-
gen, eine Charakterzeile NOCHMALS zu
lesen. Der anzuwendende Trick ist uns
dabei gar nicht mal so unbekannt, denn
er funktioniert ähnlich wie der FLD-
Effekt. Bei diesem schoben wir den An-
fang der nächsten Charakterzeile durch
Hochsetzen der vertikalen Bildschirmver-
schiebung vor dem Rasterstrahl her, so
daß die Charakterzeile für den VIC erst
begann, als wir mit unserer Manipulation
aufhörten. Nun arbeiten wir im Prinzip
genauso, nur daß wir die Chrakterzeile
nicht VOR dem Rasterstrahl wegschieben,
sondern MIT ihm. Verschieben wir den
Vertikal-Offset nämlich so, daß er immer
mit dem Anfang einer Charakterzeile zu-
sammenfällt, so meint der VIC, er müsse
jetzt die neuen Charakterdaten lesen,
selbst wenn er das in der Rasterzeile
zuvor auch schon getan hat. Schalten wir
nun gleichzeitig auch noch auf eine an-
dere Video-Map um, so liest der VIC, so
als wäre alles in Ordnung, die 40 Cha-
rakter der neuen Map!
Bevor ich mich nun aber in theoretischen
Erklärungen verliere, möchte Ich Ihnen
ein Programmbeispiel zeigen, das alles
einfacher zu erklären vermag. Sie finden
es auf dieser MD unter dem Namen "GO-
FLI-CODE", und müssen es mit der Endung
",8,1" laden. Gleichzeitig (und eben-
falls mit ",8,1") sollte auch noch die
lange Grafik "GO-FLIPIC" geladen werden,
damit Sie beim Start der Routine mittels
"SYS4096", auch etwas auf dem Bildschirm
sehen. Es handelt sich dabei um das Logo
unseres Schwestermagazins "Game On", und
zwar in schillernd bunten Farbabstufun-
gen!
Doch kommen wir nun zum Sourcecode die-
ser FLI-Routine. Zunächst einmal werde
ich Ihnen die Initialisierung hier auf-
listen, die größenteils identisch mit
den zuvorigen Init-Routinen ist, jedoch
auch einige FLI-spezifische Einstellun-
gen vornimmt:
Init:sei ;IRQs sperren
lda $7F ;CIA-IRQs und NMIs
sta $dc0d ; sperren
sta $dd0d
bit $dc0d ;ggf. vorhandene IRQ-
bit $dd0d ;oder NMI-Anfr. löschen
lda #$0b ;Bildschirm
sta $d011 ; abschalten
ldy #$00 ;Daten für Color-Map
lda $3c00,y ; von $3C00
sta $d800,y ; nach $D800
lda $3d00,y ; kopieren
sta $d900,y
lda $3e00,y
sta $da00,y
lda $3f00,y
sta $db00,y
iny
bne color
lda #$00 ;Hardvektor füt IRQ bei
sta $fffe ; $FFFE/$FFFF auf
lda #$11 ; eigene Routine bei
sta $ffff ; $1100 setzen
ldx #$38 ;Basisw. Vert.Versch.
stx $02 ; in Zeropage ablegen
inx ;Pro Zeile +1 und
stx $03 ; ebenfalls in ZP abl.
inx ;usw. bis X=$3F
stx $04
inx
stx $05
inx
stx $06
inx
stx $07
inx
stx $08
inx
stx $09
lda #$5C ;Rasterz. $d012 ist
sta $d012 ; IRQ-Auslöser
lda #$81 ;Raster als IRQ-Quelle
sta $d01a ; einschalten
dec $d019 ;ggf. VIC-IRQ freigeben
lda #$35 ;Basic- u. Betr.Sys.-
sta $01 : ROM abschalten
cli ;IRQs freigeben
lda #$7f ;Tastaturport init.
sta $dc00
spc: lda $dc01 ;Auf 'SPACE'-Taste
cmp #$ef ; warten
bne spc
lda #$37 ;ROMs wieder
sta $01 ; einschalten
jmp $fce2 ;und RESET auslösen
Hier schalten wir zunächst alle CIA-IRQs
ab, tragen die Startadresse unserer FLI-
Routine bei $1100 in den Hard-IRQ-Vektor
$FFFE/$FFFF ein, schalten das Be-
triebssystem ab, damit der Vektor auch
angesprungen wird, und erlauben dem VIC
in Rasterzeile $5C einen Raster-IRQ aus-
zulösen. Zudem wird eine Tabelle in den
Zeropageadressen von $02 bis $09 initia-
lisiert, die in Folge die Werte von $38
bis $3F enthält. Diese müssen wir spä-
ter, je nach Rasterzeile, in Register
$D011 schreiben, damit der Anfang der
Charakterzeile immer in der aktuellen
Rasterzeile ist. Durch den Basiswert $38
legen wir zunächst nur fest, daß der
Bildschirm eingeschaltet ist, und sich
der VIC im Grafikmodus und in 25-
Charakterzeilen-Darstellung befindet.
Durch das jeweilige aufaddieren von 1
wird dann legiglich der vertikale Ver-
schiebeoffset um 1 erhöht, was dann im-
mer dem jeweiligen Wert für den Beginn
einer Charakterzeile entspricht (Start-
wert $38 -> Verschiebung=0 für tatsäch-
liche Charakterzeile; nächster Wert=$39
-> Verschiebung=1 Zeile, wehalb die er-
ste Rasterzeile hinter der normalen Cha-
rakterzeile vom VIC wieder als Charak-
terzeile aufgefasst wird; usw.). Die
Werte werden übrigens deshalb in eine
Tabelle innerhalb der Zeropage eingetra-
gen, damit das Timing später besser
klappt.
Desweiteren wird hier der Inhalt der
Color-Map initialisiert. Hierzu sollte
ich vielleicht noch erläutern, wie das
68 Blocks lange FLIPIC-File aufgebaut
ist: zunächst einmal wird es an Adresse
$3C00 geladen, wo sich auch die $0400
Bytes für die Color-Map befinden. Ab
Adresse $4000 beginnen nun die acht Vi-
deo-Maps, die später von der FLI-Routine
durchgeschaltet werden. Auch sie sind
jeweils $0400 Bytes lang (was einer Ge-
samtlänge von $0400*8=$2000 Bytes
gleichkommt). Hiernach, im Bereich von
$6000-$8000 befindet sich nun die darzu-
stellende Grafik-Bitmap. Was die Init-
Routine nun macht, ist lediglich die
Color-Map-Daten zwischen $3C00 und $4000
nach $D800 (Basisadresse des Color-
RAMs), zu kopieren. Die Video-RAM-Daten
liegen in den Speicherbereichen, die mit
den Werten von 0-7 für die Highbits von
Register $D018, angewählt werden können
(was gleichzeitig auch der Anordnung in
Rasterzeilen entspricht - Video-RAM Nr.0
($4000) für die 0. Rasterzeile innerhalb
Charakterzeile; Video-RAM Nr.1 ($4400)
für die 1. Rasterzeile innerhalb der
Charakterzeile; usw).
Kommen wir nun zur Interruptroutine
selbst. Sie beginnt wie all unsere zeit-
kritischen Raster-IRQs zunächst mit der
Glättungsroutine, wobei ein weiterer
Interrupt festgelegt und ausgelöst wird,
bevor die eigentliche FLI-Routine folgt.
Sie beginnt wieder ab dem Label "Onecyc-
le", ab dem der IRQ "geglättet" ist.
Hier nun der eigentliche Kern der Routi-
ne. Da der Interrupt bei Rasterzeile $5C
ausgelöst wurde, und die Glättung zwei
Rasterzeilen verbrauchte, befinden wir
uns nun also in Zeile $5E, womit wir
also zwei Rasterzeilen vor Beginn der
achten Charakterzeile stehen:
dec $d019 ;VIC-ICR löschen
lda #$5C ;Neue IRQ-Rasterzeile
sta $d012 ; festlegen ($5C)
lda #$00 ;IRQ-Vektor wieder auf
sta $fffe ; die erste IRQ-Routine
lda #$11 ; verbiegen (für den
sta $ffff ; nächsten Aufruf)
lda #$00 ;Bildschirmrahmen- und
sta $d020 ; Hintergrundfarbe auf
sta $d021 ; 'schwarz' setzen
NOP ;Hier folgen nun 40 NOPs
... ; um bis zum richtigen
NOP ; Zeitpunkt zu verzögern
ldy #$08 ;Rasterzeilenzähler init.
jsr fliline ;8 FLI-Rasterzeilen
jsr fliline ; für 12 Charakterzeilen
jsr fliline ; durchführen (gesamte
jsr fliline ; Größe des FLI-Bereichs:
jsr fliline ; 8x12=96 Rasterzeilen)
jsr fliline
jsr fliline
jsr fliline
jsr fliline
jsr fliline
jsr fliline
jsr fliline
lda #$02 ;Bildschirmrahmen- und
sta $d020 ; Hintergrundfarbe auf
sta $d021 ; 'rot' setzen
lda #$38 ;Vertikalverschiebung
sta $d011 ; zurücksetzen (=0)
lda #$88 ;VideoMap 8
sta $d018 ; einschalten
pla ;Prozessorregister vom
tay ; Stapel zurückholen
pla ; und IRQ beenden.
tax
pla
rti
Hier werden erst einmal die Vorbereitun-
gen für den nächsten Interrupt getroffen
(also für den nächsten Bildaufbau). Dies
ist das Rücksetzen des IRQ-Vektors, auf
die Glättung-IRQ-Routine, das neue fest-
legen der Rasterzeile $5C als IRQ-
Auslöser, sowie das Löschen des VIC-
ICR-Registers durch Zugriff auf Adresse
$D019. Nun wird das Y-Register mit dem
Wert 8 initialisiert, der in der nun
folgenden "FLILINE"-Routine gebraucht
wird. Selbige führt den eigentlichen
FLI-Effekt aus, wobei Sie immer acht
Rasterzeilen lang, seit Beginn einer
Rasterzeile, den Effekt erzeugt. Durch
den 12-maligen Aufruf lassen wir ihn
also ab Rasterzeile $5E für 96 Raster-
zeilen aktiv sein. Hier nun der Source-
code zur FLILINE-Routine:
(Anm. d. Red.: Bitte wählen Sie nun
den zweiten Teil des Kurses
aus dem Textmenu)