Magic Disk 64

home to index to text: MD9406-KURSE-IRQ-KURS_8.1.txt
                IRQ-KURS                
     "Die Hardware ausgetrickst..."     
                (Teil 8)                

Herzlich willkommen zum achten Teil unseres Raster-IRQ- Kurses. Heute wollen wir uns mit einem besonders interessanten 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 8 x8- Pixel-Block, darzustellen. Durch die dabei entstehende Farbvielfalt können sehr eindrucksvolle Bilder angezeigt werden, die bei geschickten Grafikern schon an die Qualität von Amiga-Bildern reichen können!
1) GRUNDLAGEN Wollen wir uns zunächst einmal anschauen, wie der VIC vorgeht, um eine Bitmap-Grafik auf den Bildschirm zu zaubern:
Zunächst einmal muß der Grafikmodus eingeschaltet werden, wobei die Lage der Bitmap im Speicher mitangegeben wird.
Nun zeigt der VIC also die Bits des angegegebenen Speicherbereichs als einzelne Pixel auf dem Bildschirm an. Um diesen Pixeln nun auch noch Farbe zu verleihen, 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 normalerweise bei $0400( dez.1024) befindet, die Farbe der Pixel innerhalb eines 8 x8- Pixel-Blocks. So legt das erste Byte des Video-RAMs ( als Zeichen ganz links oben), die Farbe für die 8 x8, im Grafikmodus quasi " über" ihm liegenden, Pixel fest. Das zweite Byte ist für den nächsten 8 x8- Pixel-Block zuständig, und so weiter. Da der VIC insgesamt nur 16 Farben kennt, sind dabei jeweils nur die unteren vier Bits eines Video-RAM- Bytes von Bedeutung. Die oberen vier sind unbenutzt und werden ignoriert.
b) DER MULTICOLOR-MODUS In diesem Modus werden zwei nebeneinander liegende Pixel jeweils zu einem Farbcode zusammengefasst. Sind beide 0, so erscheint an ihrer Stelle die Hintergrundfarbe, sind beide auf 1, so wird für beide die Farbe aus einem äquvalenten Byte des Color-RAMs geholt ( bei Adresse $ D800- dez.55296), das normalerweise 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 festlegt.
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-$3 FFF) in 1 KB-Schritten verschieben. Hierfür ist Register 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 Darstellung der Textzeichen, bzw. im Grafikmodus der Farbzeichen, zuständig ist. Die unteren Bits von 0-3 bestimmen die Lage des Zeichengenerators, also des Speicherbereichs, 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 16 KB-Bereichs des VICs.
Die im Folgenden angegebenen Adressen verstehen sich also als Offsets, die auf die Startadresse des 16 KB-Bereichs aufaddiert 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 Kursteil.
Desweiteren wollen wir noch schnell klären, wie man den 16 KB-Bereich des VICs verschiebt, da die FLI-Routine eine Menge Video-Speicher benötigt ( nämlich die vollen 16 KB), 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-$3 FFF - 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 Bitkombinationen 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öglichkeit, einem 8 x8- Pixel Block der Grafik in jeder Zeile eine neue Farbe zuzuteilen ( im Multicolormodus sogar 2), so daß wir die 2-, bzw.4- Farbeinschränkung auf einen Bereich von 1 x8 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 Rasterzeilen darzustellen hat. Somit würde ein einfaches Umschalten auf eine neue Video- 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 zwingen, 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 Anfang der nächsten Charakterzeile durch Hochsetzen der vertikalen Bildschirmverschiebung 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 zusammenfä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 andere Video-Map um, so liest der VIC, so als wäre alles in Ordnung, die 40 Charakter 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 ebenfalls 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 Farbabstufungen!
Doch kommen wir nun zum Sourcecode dieser FLI-Routine. Zunächst einmal werde ich Ihnen die Initialisierung hier auflisten, die größenteils identisch mit den zuvorigen Init-Routinen ist, jedoch auch einige FLIspezifische Einstellungen 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 #$7 f ; 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 Betriebssystem ab, damit der Vektor auch angesprungen wird, und erlauben dem VIC in Rasterzeile $5 C einen Raster-IRQ auszulösen. Zudem wird eine Tabelle in den Zeropageadressen von $02 bis $09 initialisiert, die in Folge die Werte von $38 bis $3 F 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 Verschiebeoffset um 1 erhöht, was dann immer dem jeweiligen Wert für den Beginn einer Charakterzeile entspricht ( Startwert $38-> Verschiebung=0 für tatsächliche Charakterzeile; nächster Wert=$39-> Verschiebung=1 Zeile, wehalb die erste Rasterzeile hinter der normalen Charakterzeile vom VIC wieder als Charakterzeile aufgefasst wird; usw.) . Die Werte werden übrigens deshalb in eine Tabelle innerhalb der Zeropage eingetragen, 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 $3 C00 geladen, wo sich auch die $0400 Bytes für die Color-Map befinden. Ab Adresse $4000 beginnen nun die acht Video- Maps, die später von der FLI-Routine durchgeschaltet werden. Auch sie sind jeweils $0400 Bytes lang ( was einer Gesamtlänge von $0400*8=$2000 Bytes gleichkommt) . Hiernach, im Bereich von $6000-$8000 befindet sich nun die darzustellende Grafik-Bitmap. Was die Init-Routine nun macht, ist lediglich die Color-Map- Daten zwischen $3 C00 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 zeitkritischen 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 " Onecycle", ab dem der IRQ " geglättet" ist.
Hier nun der eigentliche Kern der Routine. Da der Interrupt bei Rasterzeile $5 C ausgelöst wurde, und die Glättung zwei Rasterzeilen verbrauchte, befinden wir uns nun also in Zeile $5 E, 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 ; Bildschirmrahmenund 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 ; Bildschirmrahmenund 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 Vorbereitungen 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 festlegen der Rasterzeile $5 C 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 $5 E für 96 Rasterzeilen aktiv sein. Hier nun der Sourcecode zur FLILINE-Routine:
( Anm. d. Red. : Bitte wählen Sie nun den zweiten Teil des Kurses aus dem Textmenu)

Valid HTML 4.0 Transitional Valid CSS!