Magic Disk 64

home to index to text: MD9402-KURSE-16_FARBEN_SCROLL.txt
          16-FARBEN-SCROLLING           
                 Teil II                

Im ersten Teil dieses Kurses wurde viel Theoretisches gesagt. Um nun langsam ( !) zur Praxis zu kommen, wollen wird diesmal anhand eines Source-Codes, welchen ich ausführlich dokumentieren und erklären werde, einen Schritt in Richtung " Linecrunching", so wie' s wirklich funktioniert, machen.
Der " Linecrunching-Sourcecode" als sequentielles File, wurde nur wenig dokumentiert. Doch sollte er für jeden, der folgendes Kapitel " durchackert" hat, leicht verständlich sein.
Um kurz zu wiederholen:
Horizontale Bildverschiebung erreichen wir, indem wir den VIC dazu bringen, eine neue Cursor-Zeile aufzubauen, obwohl die alte noch nicht abgeschlossen wurde und der darstellende Elektronen-Strahl gerade am sichtbaren Bereich unterwegs ist. So läßt sich durch Timing eine X-Versetzung auf Cursor-Positionen genau erreichen.
Vertikal dupliziert sich die Trickserei!
Und zwar simuliert man für den oberen Screen-Bereich beliebig viel Cursor-Zeilen, dir nur eine Rasterzeile hoch sich ( Verhältnis 1 :8) . So werden die Zeilen " geschrumpft" und der Bildscirm-Inhalt nach oben gezogen. Was oben fehlt kommt ( so wie beim Horizontalen Versetzen rechts) unten wieder rein.
Gut, nun wird' s ernst. Sehn' wir uns die Sache mit dem $ d011- Register genauer an:

      lda #$1b  ;Register               
      sta $d011 ;reinitialisieren       
      lda #$2c                          
fl1   cmp $d012 ;auf Rasterzeile #$2c   
      bne fl1                           
      ldx #4                            

fl2 dex ; extaktes Timing bne fl2 Bis jetzt wurde nur $ d011 richtiggesetzt ( muß jeden Rasterdurchlauf reinitialisiert werden!) und auf die entsprechende Raster-Y- Position gewartet ( hängt ja bekanntlich vom 3- Bit-Wert im $ d011- Register ab. Die Schleife danach bringt nur genaueres Timing, damit der Rasterstrahl in etwa dort ist, wo wir ihn brauchen ( dieses Timing ist noch nicht auf Zyklen ganau; die Schwankungen liegen von 1-4 Taktzyklen) .

fl4   lda dtab,x ;$d011-Wert-Tabelle    
      dec $d02f  ;$d02f(?) erniedrigen  
      sta $d011  ;Wert schreiben        
      inc $d02f  ;(?) wieder erhöhen    
      nop        ;Timing-nops!          
      .                                 
      . u.s.w.                          
      .                                 

Zuerst wird der entsprechende $ d011- Wert aus einer angelegten Tabelle ( kommt noch!) ausgelesen. Danach folgt wieder was typisch " C64- Mäßiges" : Bevor nun der ausgelesene Wert ins $ d011- Reg. geschrieben wird, erniedrigen wir das Register $ d02 f, um es danach wieder zu erhöhen. Rein sinnlos, oder ? Doch wer die beiden " Sinnlosigkeiten" aus dem Code entfernt, wird sich wundern: Kein Linecrunching ohne $ d02 f! Warum ? Wer den C64 so lange und gut kennt wie ich, fragt so was nicht. Er wundert sich gar nicht mal.
Danach kommt wieder Rasterzeitfüllendes Timen. Erwähnt sei, daß ein NOP-Befehl genau 2 Taktzyklen benötigt, wohingegen ein BIT $ XX-Befehl 3 braucht. So läßt sich auf Zyklen genau verzögern. Ein entsprechendes Beispiel finden wir später beim X-Scrollen, da wir dort den Rasterstrahl ja an jeder möglichen X-Position austricksen werden.
.

      .       ...und weiter:            
      .                                 
      inx           ;Pointer erhöhen    
up    cpx #2        ;fertig ?           
      bne fl4                           
fll4  lda dtab+1,x  ;aus Tabelle+#1     
      dec $d02f     ;wie gehabt         
      sta $d011                         
      inc $d02f                         
      nop                               
      .                                 
      .                                 
      .                                 

Ab " fll4" passiert anscheinend ganau dasselbe wie zuvor, doch: Wir lesen den $ d011- Wert aus der Tabelle+1 . Warum ?
Folgende Rasterzeilen wird sozusagen nur Zeit verbraucht, um die Lücke zu füllen. Die Lückenspanne ist linear zur Y-Versetzung. Wenn viele Zeilen " ge- staucht" werden, ist die Spanne klein - und umgekehrt. Und dadurch, daß wir aus der Tabelle+1 lesen, passiert gar nichts. Allerdings müssen wir in $ d011 etwas schreiben, da wir sonst mit dem Soft-Scrolling in Y-Richtung nicht zurechtkommen.
.

      .       ...und weiter:            
      .                                 
      inx       ;Pointer erhöhen        
      cpx #28   ;Zeilen-Limit ?         
      bne fll4  ;zurück!                
      ldx #1                            
fl5   dex       ;wieder timen...        
      bne fl5                           
      lda #$59  ;Neuer Fix-Wert für     
      sta $d011 ;$d011                  
      ldx #$4f  ;x-Reg.für Raster-Check 
      lda #$5f  ;$d011-Wert in Akku     
fl6   cpx $d012 ;Rasterzeile schon      
      bne fl6   ;erreicht ?             
      ldx #3                            
fl7   dex       ;und wieder timen...    
      bne fl7                           
      sta $d011 ;jetzt in $d011!        

Linecrunching ist abgeschlossen ( max.
28 Rasters!) und zwischen den gewohnten " Austimereien" wurde der Fixwert #$59 in $ d011 geschrieben und anschließend nochmal #$5 f. Das war die Vorbereitung für das X-Scrolling, dem jetzt nichts mehr im Wege steht. . .

      lda #208  ;Border eng             
      ora xsoft ;mit Xsoft verknüpft    
      sta 53270 ;ins X-Scroll-Register  
      lda #$0f                          
      sta $d02f ;$d02f zurücksetzen     
      ldx #3                            
jumpi dex       ;zum Xten mal Timen     
      bne jumpi                         

Alles ist nun vorbereitet:" Softscroll-3- Bit-Byte"(0-7) verknüpft,$ d02 f reinitialisiert ( für nächsten Durchlauf notwendig!) und wieder Verzögerung.
Warum zwei mal ins $ d011- Reg. geschrieben wird, ist auch ganz einfach: Durch diese besondere Zusammensetzung der beiden Werte und auch dem Zeitraum zwischen den beiden, erreichen wir, daß der Prozessor nun den nächsten Befehl auf einer fixen Raster-X- Position durchführt. D. h. das relativ ungenaue ( auf 1-4 Zyklen genaue) Timing ist jetzt auf 1 Taktzyklus genau. Und genau das ist absolut notwendig für den X-Trick, für das sog. Hard-Scrolling. . .

      lda #$59    ;Wert für $d011       
xhard bne jumpl+0 ;variabler jump       
jumpl cmp #$c9    ;22 x "cmp #$c9"      
      cmp #$c9                          
      .                                 
      .                                 
      cmp #$c9                          
      bit $ea     ;versteckter "NOP"    
      sta $d011                         

Im Grunde genommen sind diese 22 platz- füllend wirkenden " cmp #$ c9" wieder Timer-Elemente. Und zwar ist der Jump-BNE- Befehl ausschlaggebend: Gesprungen wird immer ( da #$59 ja unequal 0 ist!), und zwar soweit, wie wir in xhard+1 schreiben. Logische Werte wären 0-39, da wir eine Cursor-Auflösung von 40 Zeichen haben.
Wir wissen, daß wir eine Verzögerung von 0-39 Taktzyklen brauchen, um den Screen an alle möglichen Position versetzen zu können. Genau das erledigen die " CMP #$ c9" Befehle. Wenn wir uns den Opcode dieses Befehls in einem Monitor ansehen, merken wir, daß der Opcode des Befehls " CMP" den Wert #$ c9 besitzt. Das heißt, wir können den BNE-Jump irgendwo in die Liste steuern, und der Prozessor wird immer " CMP #$ c9" entdecken, egal ob der Wert nach dem " BNE"( xhard+1) gerade oder ungerade ist.
Schließlich wird die " CMP #$ c9"- Liste noch mit einem " BIT #$ ea" abgeschlossen.
Erraten!#$ ea ist der Opcode-Wert für " NOP" . Nun liest der Prozessor je nachdem, ob es eine gerade oder ungerade Sprungadresse ist, folgende Befehls-Serien. . .
gerade: ungerade:

   ...          ...                     
   cmp #$c9     cmp #$c9                
   cmp #$c9     cmp #$c9                
   cmp #$c9     cmp #$24 ;#$24 = Opcode 
   bit #$ea     nop              für BIT

Diese Lösung scheint auf den ersten Blick vielleicht ein wenig aufwendig und kompliziert, doch wenn man das Prinzip und die Problemstellung richtig verstanden hat, so entdeckt man einen kleinen Touch von Genialität dahinter.
Gut, auch diesmal war wieder ' ne Menge " Stuff" dabei, der Köpfe zum Rauchen bringen kann. Doch Assembler-Tüftler werden mit Hilfe des Source-Files bald den Durchblick haben.

Der HAMMER und  die  KRONE  im  Teil  3:
Scroll-Action pur  für  eigene  Projekte
und  ein   super   Editor   für   bunte,
riesengroße Scrollfields...             
                                 (hs/wk)

Valid HTML 4.0 Transitional Valid CSS!