Scroller

Word-Bender

Diesen  Scroller  habe  ich  zur  Abwechslung  mal  fr  die hohe Auflsung
geschrieben.  Sogar  in  manchen  Megademos gibt es ein Screen fr die hohe
Auflsung  !  Den bisher besten Monochrom-Screen habe ich in der Overdrive-
Demo gefunden. Ein weiterer sw-Screen ist in der Demo von Galtan 6.

Der Zeichensatz

Ich  wollte  erst irgendein Signum-Zeichensatz verwenden. Aber leider sehen
die   Zeichen   etwas  eintnig  aus.  Dann  fiel  mir  ein,  da  man  die
Farbzeichenstze nach sw konvertieren kann. Nach einigen Versuchen habe ich
einen  guten  Font  gefunden (viele Fonts sehen nach den Konvertieren nicht
mehr  gut  aus).  Konvertiert  habe ich mit 'Guck'. Nun haben wir einen sw-
Zeichensatz in DOO-Format. Leider ist das DOO-Format fr den Scroller nicht
besonders  gut  geeignet,  da  die  Zeichen  nicht  gerade in der richtigen
Reihenfolge (ASCII) vorliegen. Also: Basic starten und schnell ein Programm
schreiben,  da  den  Font  in  die  richtige  Reihenfolge  umkopiert.  Der
Zeichensatz ( Datei: SILENTS.FNT ) hat folgende Struktur: jedes Zeichen ist
7  Byte  (  =  56  Pixel  )  breit  und  hat 80 Zeilen. Ein Zeichen braucht
demzufolge  560  Bytes. Ich habe 64 Zeichen vorgesehen, daraus ergibt sich,
das  SILENTS.FNT  35840  Bytes  gro  ist. Diese 64 Zeichen entsprechen der
ASCII-Tabelle  ab $20 (Space) bis $5f. Die nicht vorhandenen Zeichen werden
von den Basic-Programm durch Space ersetzt. 

Der Scroller

Ich werde erstmal die Grundlagen des Scrollers erklren, der Bender wird im
nexten Kapitel erklrt.

Um einen ruckelfreies Scrolling zu erreichen, mu nach jedem Bildaufbau der
Text   komplett  ein  Stck  nach  links  verschoben  werden.  Whrend  des
Bildaufbaus sollte man jedoch keine Daten in den Bildspeicher schreiben, um
Flimmereffekte  zu  vermeiden.  Daraus  folgt,  da  man  nur  whrend  des
Vertikalblanks  auf  den Bildschirm schreiben darf. Hier nun das Timing fr
den Colormodus ( 50 Hz ! ) und Monochrommodus: 

                            Colormodus              Monochrommodus
Lnge einer Zeile:          64 us                   28 us
Anzahl der Zeilen:          312                     500
davon sichtbar:             200                     400
unsichtbare Zeilen (Blank)  112                     100
Lnge des Vertikallanks     7,158 ms                2,8 ms
Bildwiederholfrequenz       50 Hz                   71 Hz
                            = 20 ms                 = 14 ms

Der  Vertikalblank ist aber viel zu kurz, die Zeit wrde vielleicht nur fr
einige  kleine  Sprites  reichen.  Mu  man  nun  doch  die  Flimmereffekte
hinnehmen ? Nein, es gibt einen anderen Weg. Man mu mit 2 Bildschirmseiten
arbeiten.  Whrend die 1. Bildschirmseite gerade auf den Monitor ausgegeben
wird,  kann  auf  der  2. Bilschirmseite das nchste Bild aufgebaut werden,
ohne  das  es  auf  dem  Bildschirm  zu  irgendwelchen  Strungen kommt. Im
Vertikalblank  schaltet  man dann auf den 2. Bildschirm um, und das nchste
Bild  wird in der 1. Bildschirmseite aufgebaut. Bein nchsten Vertikalblank
wird wieder die 1. Bild schirmseite aktiviert .....u.s.w.u.s.f. Jetzt haben
wir  viel  mehr  Zeit,  nmlich  genau die Zeit zwischen 2 Vertikalblanks (
Colormodus  20  ms,  Monochrommodus  14 ms ). Und da es im ST ein Interrupt
gibt,    der   bei   jedem   Vertikalblank   ausgefhrt   wird,   ist   das
Bildschirmseiten-Umschalten kein Problem.

Als erstes mu die Adresse der beiden Bildschirmseiten festgelegt werden:

                move.l  #s1,d0          ;Screen 1
                move.l  #s2,d1          ;Screen 2
                clr.b   d0              ;Low-Byte mu 0 sein
                clr.b   d1
                move.l  d0,screen1      ;Adresse Bildschirmseite 1
                move.l  d1,screen2      ;Adresse Bildschirmseite 2

Whrend  des  Vertikalblanks  wird  die  vbl-Routine  aufgerufen,  und  die
Bildschirmseiten werden vertauscht.




vbl:            clr.w   vbl_flag
                move.l  d0,-(sp)
                move.l  screen1,d0
                move.l  screen2,screen1 ;Screens vertauschen
                move.l  d0,screen2
                lsr.w   #8,d0
                move.l  d0,$ffff8200.w  ;Video-Base, die andere
                                        ;Bildschirmseite setzen 
                move.l  (sp)+,d0
                rte

                bss
screen1:        ds.l 1
screen2:        ds.l 1
vbl_flag:       ds.w 1
                ds.b 256
s1:             ds.b 32000
s2:             ds.b 32000
  
Wo  steht nun die Adresse der sichtbaren Bildschirmseite, im 'screen1' oder
'screen2'  ?  Die  vbl-Routine  ldt  die Adresse aus 'screen1' nach d0 und
schreibt diese nach 'screen2' und in die Video-Base-Register. Also steht im
'screen2' die sichtbare Bildschirmseite !? Denkste ! Die Anfangsadresse des
Bildschirmspeichers  wird  am Beginn des Vertikalblanks in den Videocounter
bernommen.  Wenn  die vbl-Routine aufgerufen wird, ist aber Vertikal-blank
schon  eine  Weile  aktiv  (  Interruptreaktionszeit ! ). Deswegen steht im
'screen2'  die Adresse fr das unsichtbare Bild und im 'screen1' demzufolge
die  Adresse  der sichtbaren Bildschirmseite ! ( Die Videobase-Adresse wird
also  um  1  vbl  verzgert  wirksam  )  Jetzt  sind  wir  die Flimmer- und
Zeitprobleme los. Wir warten einfach bis zu einen vbl ( 'vbl_flag' abfragen
)  und  haben nun fast 14 ms (oder 20 ms ) Zeit, ein neues Bild aufzubauen.
Welche Bildschirm-seite neu aufgebaut werden mu, steht im 'screen2'.

wait_vbl:       tst.w   vbl_flag        ;auf vbl warten
                bne.s   wait_vbl
                move.w  #1,vbl_flag
                move.l  screen2,a0      ;a0 zeigt auf den unsichtbaren Scre
                
                ;hier knnen alle Routinen stehen,
                ;die fr den Bildaufbau notwendig sind
                ;max 14 ms ! ( 20 ms )
                                
                bra     wait_vbl
                
Fast  alle  Demos  oder Spiele arbeiten nach diesen 2-Seiten Prinzip. (Oder
mit  noch  mehr  Seiten,  aber  das  ist  ein  Thema  fr  sich  )  Wer die
Flimmereffekte sehen will, kann in der vbl-Routine die Labels 'screen1' und
'screen2' untereinander vertauschen. 

Jetzt  mu man sich berlegen, wie schnell der Scroller eigentlich scrollen
soll.   Da   die   Bildwiederholfrequenz  fest  vorgegeben  ist,  kann  die
Geschwindigkeit  nur  ber  die  Anzahl  der  Pixel,  die  der Scroller pro
Bildwechsel nach links verschoben wird, festgelegt werden. Ich habe 8 Pixel
(  =  1 Byte ) gewhlt. Wenn die Anzahl der Pixel ein Vielfaches von 8 ist,
werden   die   Scrollroutinen  besonders  einfach  und  effektiv.  Aber  im
Colormodus werden viele Scroller mit 4 Pixel pro vbl bewegt, da 8 Pixel pro
vbl etwas schnell ist. Das erfordert aber mehr Aufwand ( shift-Befehle oder
Fonts vorshiften ).

So,  wer jetzt ber ein 8-Pixel-Verschieberoutine nachdenkt, denkt falsch !
Warum  ?  Da  war  noch  die  Sache  mit  den 2 Bildschirmseiten ! Dazu ein
Beispiel:  'PAC'  wird  ber ein 10 Zeichen breiten 'Bildschirm' gescrollt.
Bei  allen  ungeraden  vbl's  wir  die  Bildschirmseite  1 dargestellt, bei
geraden  vbl's  die Seite 2. 'PAC' mu also um 2 Zeichen verschoben werden,
da jede Seite erst wieder nach 2 vbl's dargestellt wird. 

vbl Seite   0123456789
1   1      |         P|
2   2      |        PA|
3   1      |       PAC|
4   2      |      PAC | 
5   1      |     PAC  |
6   2      |    PAC   |
7   1      |   PAC    |
8   2      |  PAC     |
9   1      | PAC      |
10  2      |PAC       |
11  1      |AC        |
12  2      |C         |

Wir  brauchen  also  eine  16-Pixel-Verschieberoutine. Dazu teilen wird den
Bildschirm  in 40 senkrechte 16 Pixel breite Spalten ein ( 40 * 16 = 640 ).
Die  16  Pixel lassen sich mit einen move.w Befehl kopieren. Wir fangen bei
Spalte  1  an  und kopieren 80 ( Zeichenhhe ) untereinanderliegenden Words
nach  Spalte  0. Dann folgen 80 Words von Spalte 2 nach Spalte 1 ...... und
zuletzt  die 80 Words von Spalte 39 nach Spalte 38. Jetzt mu die Spalte 39
mit  den neuen Fontdaten versorgt werden. Die hherwertigen 8 Bits besorgen
wir  uns  von der anderen Bildschirmseite. Die niederwertigen 8 Bits werden
aus dem Zeichensatz geholt.

Zum besseren Verstndnis ein Beispiel:
(Der 'Bildschirm' ist hier 144 Pixel breit, ein 'X' entspricht 8 Pixel, 144
/ 16 = 9 16-Pixel-Spalten)
 

|                  |  die zur Zeit sichtbare Bildschirmseite       
|  XXXXX  XXXXXX XX|
|  X    X X    X X |
|  X    X X    X X |
|  XXXXX  XXXXXX X |
|  X      X    X X |
|  X      X    X XX|
                  ^
|                  |  die unsichtbare Seite
|   XXXXX  XXXXXX X|  wird um 16 Pixel nach rechts verschoben
|   X    X X    X X|
|   X    X X    X X|
|   XXXXX  XXXXXX X|
|   X      X    X X|
|   X      X    X X|




|                  |  durch die Verschiebung ist links eine leere
| XXXXX  XXXXXX X  |  16-Pixel-Spalte entstanden
| X    X X    X X  | 
| X    X X    X X  |
| XXXXX  XXXXXX X  |
| X      X    X X  |
| X      X    X X  |
|                  |

| XXXXX  XXXXXX XX |  die hherwertigen 8 Pixel werden von den nieder-
| X    X X    X X  |  wertigen 8 Pixeln aus der letzten 16-Pixel-Spalte
| X    X X    X X  |  des sichtbaren Bildes geholt (^)
| XXXXX  XXXXXX X  |
| X      X    X X  |
| X      X    X XX |




|                  |  die niederwerigen 8 Pixel werden von Zeichensatz  
| XXXXX  XXXXXX XXX|  geholt, jetzt kann diese Seite dargestellt werden
| X    X X    X X  |  und die andere Seite kann gescrollt werden
| X    X X    X X  |
| XXXXX  XXXXXX X  |
| X      X    X X  |
| X      X    X XXX|
|                  |
 
Der Bender

Bis  jetzt  haben  wir einen einfachen Scroller, der immer auf der gleichen
Hhe  scrollt.  Um  einen Bender zu realisieren, mu bei dem Umkopieren der
Spalten  ein  y-Offset bercksichtigt werden. Dieser y-Offset wir aus einer
Tabelle  'pos'  geholt.  Die  Tabelle  habe  ich  mit  einen Basic-Programm
erstellt.  Die Werte sind immer ein Vielfaches von 80, da eine Bildzeile in
Monochrommodus  80 Bytes lang ist. Die Werte werden mit einer Sinusfunktion
ermittelt.  Wichtig  ist, da am Ende der Tabelle wieder die gleichen Werte
wie  am Anfang sind. Dies ist notwendig, weil die Tabelle irgendwann mal zu
Ende  ist.  Dann wird die Tabelle wieder vom Anfang an ausgelesen. Wenn die
Endwerte  und  die  Anfangswerte nicht bereinstimmen, springt der Scroller
pltzlich  in  eine andere Position. Pro Bildaufbau werden 40 Werte aus der
Tabelle  bentigt.  Wenn  aber z.B. nach 30 Werten die Tabelle zu Ende ist,
mten  die  nchsten  10  Werte  ab  Tabellenanfang gelesen werden. Um das
Problem zu lsen, wird einfach die Tabelle zweimal direkt hintereinander im
Speicher gehalten. Die 10 Werte befinden sich dann gleich nach dem Ende der
1. Tabelle ( Anfang der 2. Tabelle ).

Beim  Umkopieren wird mit Hilfe der Tabelle die y-Position der Quell-Spalte
und  Ziel-Spalte  bestimmt.  Dabei werden 'clr-lines' Zeilen ber und unter
der  Zielspalte  gelscht. Warum das notwendig ist, kann man feststellen in
dem  'clr_lines' z.B. auf 1 gesetzt wird. Je grer die Frequenz ist, um so
mehr Zeilen mssen gelscht werden. Eigentlich bruchte man nur 'clr_lines'
Zeilen  ber  !oder!  unter der Zielspalte zu lschen, aber ich hatte keine
Lust mehr, dafr einen Algorithmus auszudenken.

Der Sound

Damit  der  Scroller nicht so langweilig wird, habe ich noch ein Musikstck
eingebunden.  Das  Thema 'Soundchipmusik' ist aber schon wieder eine andere
Story  (  ich  will auch endlich mit diesen Artikel fertig werden :-) ) Nur
soviel: Das Soundprogramm mu alle 20 ms aufgerufen werden. Im Colormodus (
50  Hz  ) wird dafr der VBL-Interrupt benutzt. Im sw-Modus wrde der Sound
etwas  zu  schnell  abgespielt  (  71 Hz ). Deswegen habe ich fr den Sound
Timer B verwendet und diesen natrlich auf 50 Hz = 20 ms programmiert.

PS:

Als  Extra  gibt  es noch einen Source-Code fr einen Byte-Bender-Distorter
(fr  Colormodus).  Der  Code  ist  von  den  Intro der Toxic-Mac 1. Dieser
Scroller  verbraucht viel ( fast 20 ms ) Rechenzeit und kann nur 1-Bitplane
Fonts scrollen. Dafr ist er einfach und unaufwendig programmiert.

written by bITmASTER

  