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)