Magic Disk 64

home to index to html: MD9406-KURSE-IRQ-KURS_8.1.html
                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)           
Valid HTML 4.0 Transitional Valid CSS!