          A S S E M B L E R - K U R S       (c)  Jeff Kandle 1990

                                19.Teil...

Nun denn, jetzt kommen die vorbereitenden Sachen zur Laufschrift.
Wir haetten das auch schon viel frueher machen koennen, mit dem Rol oder
Asl befehl...Aber das ist echt Arbeit. Und mit dem Blitter ist es ein
Klacks einen Text ueber den Screen zu scrollen.
Kommen wir nun zu einer moeglichkeit die uns der Blitter bietet, und die
wir fuer Laufschriften sehr gut gebrauchen koennen. Aber erstmal will ich
es ohne erklaeren, dann erkennt ihr den Nutzen wirklich.

18.Realisation einer Laufschrift mit Hilfe des Blitters

Also wie sieht eine Laufschrift den theoretisch aus.

...Ein Buchstabe wird auf den Bildschirm geschrieben. Er wird stetig nach
Links verschoben, auf den Linken rand zu. Sobald neben ihm Platz fuer einen
neuen ist, wird der naechste Buchstaben dargestellt. Das geht immer weiter
so..Sobald einer der Buchstaben den linken rand erreicht hat, wird er immer
mehr herrausgeschoben, bis er nicht mehr zu sehen ist. So einfach ist das.

Damit die Buchstaben sich aber nicht ruckartig weiterbewegen, mueesen wir
erstmal softscrolling mit dem Blitter verstehen und anwenden.
Denn Hardscrolling hiess mit dem Blitter immer 16 Pixel weiter, weil er ja
als kleinste Einheit, nur das Wort kennt. Und das waere ja ein bisschen
viel, gell ?

Zum Glueck haben die Erbauer des Blitter uns da etwas eingebaut was uns
dabei hilft.

Der Blitter ist in der Lage, die von Quelle A oder B kommenden Daten Pixel-
weise zu verschieben, und verschoben zu schreiben. Man muss ihm den wert
nur in eines der Kontrollworte BLTCON0 oder BLTCON1 zu schreiben. Dann wird
der Wert beim lesen verschoben und dann in das Ziel geschrieben.

Den Verschiebungswert fuer die Quelle A, schreiben wir in die obersten 4
Bits des BLTCON0 registers. Den Verschiebungswert fuer die Quelle B,
schreiben wir in die obersten 4 Bit des BLTCON1 registers.

Man setzt die anzahl der Pixels die nach rechts geschoben werden soll in
das register, mit dessen Quelle wir Arbeiten. Ich nehme bei einfachen
sachen sowieso immer A, also bleiben wir dabei.

Verschieben ist allerdings nicht das richtige Wort fuer die Sache. Es
muesste eigentlich `Rotieren` heissen. Denn was rechts rausfaellt, wird
links wieder reingesetzt.

Es gibt allerdings noch andere Probleme. Wie gesagt, man gibt den Wert der
Pixelverschiebung nach rechts an. Aber so eine Laufschrift laeuft aber
immer von Rechts nach Links...Es sei den wir Schreiben in Arabisches intro,
aber das wollen wir ja nicht, oder. Wie kriegen wir also ein Verschiebung
nach links hin. Es ist nicht schwer, aber ihr muesst jetzt genau lesen.

Eine verschiebung um einen Pixel nach links, ist moeglich wenn wir als
verschiebungs wert 15 eingeben, und als  Ziel 1 Wort vorher Waehlen.

Bildlich...


   1 Wort           2 Wort         3 Wort
I               I              I
00000000000000001111111111111110000000000000000

Wenn wir nun die ganzen Einsen, eins nach Links kopieren wollen, kopieren
wir einfach alles in das Erste wort.


   1 Wort           2 Wort         3 Wort
I               I              I
11111111111111110000000000000000000000000000000

Und jetzt verschieben wir es einfach 15 Pixel nach rechts..

   1 Wort           2 Wort         3 Wort
I               I              I
0000000000000001111111111111110000000000000000

Das ist dasselbe als wenn wir es direkt eins nach links schieben, oder ?

Wenn wir also einen Teil des Bildschirms Softscrollen wollen, muessen wir
einfach das gesamte rechteck ein Wort frueher wieder hinschreiben und die
Verschiebung auf 15 Pixel stellen.

Allerdings muessen wir noch einen Sicherheits bereich erschaffen, in dem
die sachen die Links rausfallen wieder reingeschoben werden koennen ohne
das sie auf dem Bildschirm sichtbar werden. Dazu koennen wir wieder die
Modulowerte der Bitplanes gebrauchen. Mit ihnen koennen wir uns diesen
bereich schaffen. Normalerweise waehlt man die groesse eines Buchstaben als
sicherheits abstand. Gehen wir mal von einen 16*16 Zeichensatz aus, das
saehe dann ungefaehr so aus.

I                                          I    I
I  Normaler Sichtbarer                     I    I  Sicherheitsbereich
I  Bildschirm                              I    I /
I                                          I    I/
I                                          I    /
I                                          I   /I
I                                          I  / I
I                                          I    I
I                                          I    I

Bei dem erwaehnten 16 mal 16 Font, muessten wir also Modulowert 2, fuer
zwei Bytes eingeben, dann haetten wir die Zone erstellt.
Hier koennen dann die Truemmer von Links hereingeschoben werden. Sobald
aber der Buchstabe den ich waehrend des Scrollens dort rausgeschoben habe,
ich setzte die Buchstaben ebenfalls in diese Zone, damit sie in den
Bildschirm hereingeschoben werden, muss ich allerdings direkt den neuen
dort reinsetzen, da sonst der muell von eben zwischen den buchstaben
landet, und das wollen wir ja nicht.

Wie muss ich jetzt diese beiden bereiche verwalten ?
Der gesamte rechteckige bereich ist samt Sicherheitszone 21*17 Worte gross.
Eine Zeile muss ich oben auch als Sicherheitszone eingeben.

Zuerst muessen wir uns mal um die routine Kuemmern die den ganzen bereich
verschiebt. Wenn wir davon ausgehen das die Plane bei $40000 anfaengt saehe
das dann so aus.

        Move.w #$ffff,BLTAFWM           ; Masken setzen
        Move.w #$ffff,BLTALWM
        Move.w #$0000,BLTAMOD           ; Modulowerte noch nicht von
                                        ; bedeutung
        Move.w #$0000,BLTDMOD
        Move.w #%1111100111110000,BLTCON0
                                        ; Quelle und Ziel festlegen, und
                                        ; Verschiebungswert fuer A angeben
        Move.l #$40000,BLTAPT           ; Quelle Normal
        Move.l #$3fffe,BLTDPT           ; Ziel 2 Bytes frueher
        Move.w #21*64+17,BLTSIZE        ; Groesse und LOS!

Ich schreibe die WaitBlitter routine und das RTS nicht mehr dabei. Es
muesste jedem klar sein das das kommen muss wenn man die Routine selbst
benutzt.

So mit der Routine haetten wir alles um einen Pixel nach Links gesetzt.

Sobald das aber 16 mal passiert ist, muss der Puffer wieder mit dem
Naechsten zeichen gefuellt werden, damit wenn wir weiterschieben der neue
Buchstabe reingeschoben werden kann.
Das Aussehen des Buchstaben koennen wir im Source unterbringen, mit der
DC.w anweisung geht das ziemlich einfach.

Jetzt kommen auch die Modulo werte des Blitter auf die Buehne. Wenn ich das
aussehen nun in den Puffer kopiere, kann die Quelle ohne Modulowert sein,
weil die Daten ja alle hintereinander liegen. Aber in der Quelle kann ich
sie nicht hintereinander schreiben, sonst wuerden wir sie ja auf den
bildschirm setzen. Wir muessen also gucken wo die Linke obere Ecke der
Sicherheitszone ist, als Breite die Breite des Puffers angeben, und als
Modulo wert fuer das Ziel, die Breite des Sichtbaren bereiches angeben,
damit wenn eine Zeile des neuen Buchstaben geschrieben ist, der anfang der
Zeile, der ja sichtbar ist, uebersprungen wird, und erst weitergeschrieben
wird wenn der Puffer wieder erreicht ist. Das saehe dann so aus...

        Move.w #$ffff,BLTAFWM           ; Immer noch keine Maske
        Move.w #$ffff,BLTALWM
        Move.w #$0000,BLTAMOD           ; Modulo A ist null
        Move.w #$0028,BLTDMOD           ; Modulo D ist 40 ($28)
        Move.w #%0000100111110000,BLTCON0
                                        ; Keine Verschiebung, A und D an
        Move.l #Definiton im Source,BLTAPT
        Move.l #$40028,BLTDPT           ; Linke obere Ecke des Puffers
        Move.w #1*64+16,BLTSIZE         ; Groesse und los...

Das waren die beiden Wichtigsten routinen die der Blitter bei der
Programmierung einer Laufschrift ausfuehren muss.

Das schwierige an einer laufschrift ist die verwaltung der Buchstaben
definitionen, und das setzen der neue Buchstaben, die auswahl der
richtigen Buchstaben anhand eines Ascii wertes und so weiter...

Schreiben wir aber erstmal ein Prograemmchen das einen bestimmten bereich
immer weiter nach links Scrollt, und wenn ein zeichen draussen ist, ein
neues reinsetzt...

Dort setze ich diese beiden routinen ein....Achtet aber mehr auf die art
und weise wie ich auf den Zeitpunkt warte an dem ich den Puffer mit dem
Neuen zeichen fuellen muss...

Hier das Listing..

Execbase=       4
Openlibrary=    -408
Vhposr=         $dff006
Forbid=         -30-102
Permit=         -30-108
Bltafwm=        $dff044
Bltalwm=        $dff046
Bltcon0=        $dff040
Bltcon1=        $dff042
Bltamod=        $dff064
Bltdmod=        $dff066
Bltapt=         $dff050
Bltdpt=         $dff054
Dmacon=         $dff096
Intena=         $dff09a
Dmaconr=        $dff002
Bltsize=        $dff058


        Move.w  #$0020,dmacon
        Move.w  #$4000,intena
        Move.l  execbase,a6
        Jsr     forbid(a6)


        Move.l  #$40000,a0
        Move.l  #$2800/4,d0
clearloop:
        Move.l  #0,(a0)+
        Dbf     d0,clearloop

        Bsr.l   Set_letter
        Bsr.l   Makecl

Wait:
        Cmpi.b  #$80,vhposr
        Bne.s   Wait
        Bsr.l   Scroll
        Sub.w   #1,Lettercount
        Bne.s   Weiter
        Bsr.l   Set_letter
Weiter: Btst    #6,$bfe001
        Bne     Wait

        Move.l  Execbase,a6
        Jsr     Permit(a6)
        Lea     Gfxname(pc),a1
        Jsr     Openlibrary(a6)
        Move.l  d0,a6
        Move.w  #$83e0,dmacon
        Move.w  #$c000,intena
        Move.l  38(a6),$dff080
        Moveq   #0,d0
        Rts
Makecl:
        Lea     $05f000,a0
        Move.l  a0,$dff080

        Move.l  #$00e00004,(a0)+
        Move.l  #$00e20000,(a0)+
        Move.l  #$008e3081,(a0)+
        Move.l  #$009030c1,(a0)+
        Move.l  #$00920038,(a0)+
        Move.l  #$009400d0,(a0)+
        Move.l  #$01001200,(a0)+
        Move.l  #$01080002,(a0)+
        Move.l  #$01800000,(a0)+
        Move.l  #$018200ff,(a0)+
        Move.l  #$fffffffe,(a0)+
        Rts

Waitblit:
        Btst    #6,dmaconr
        Bne.s   Waitblit
        Rts

Set_lettEr:
        Bsr.s   Waitblit
        Move.w  #$ffff,bltafwm
        Move.w  #$ffff,bltalwm
        Move.w  #%0000100111110000,bltcon0
        Move.w  #0,bltamod
        Move.w  #40,bltdmod
        Move.l  #Smiledefi,bltapt
        Move.l  #$40028,bltdpt
        Move.w  #15*64+1,bltsize
        Move.w  #$10,lettercount
        Rts
Scroll:
        Bsr.s   Waitblit
        Move.w  #$ffff,bltafwm
        Move.w  #$ffff,bltalwm
        Move.w  #%1111100111110000,bltcon0
        Move.w  #0,bltamod
        Move.w  #0,bltdmod
        Move.l  #$40000,bltapt
        Move.l  #$3fffe,bltdpt
        Move.w  #16*64+21,bltsize
        Rts

Gfxname:        dc.b "graphics.library",0

even

Lettercount: dc.w 0

Smiledefi:

dc.w %0000111111110000
dc.w %0011000000001100
dc.w %0100000000000010
dc.w %0100000000000010
dc.w %1001110000111001
dc.w %1001010000101001
dc.w %1001110110111001
dc.w %1000000110000001
dc.w %1000001111000001
dc.w %1000000110000001
dc.w %1001100000011001
dc.w %0100011111100010
dc.w %0100000000000010
dc.w %0011000000001100
dc.w %0000111111110000


So, kurz mal zu der Routine die den Zeitpunkt fuer das Neu-Fuellen des
Puffers bestimmt. Sie Arbeitet sehr einfach...Bevor ich in die
Endlosschleife springe, setze ich das Zeichen schon einmal in den Puffer.
Gleichzeitg mit diesem Aufruf wird das Wort Lettercount auf 16 gesetzt.
Sobald ich mit der Endlosschleife die Zeile $80 erreicht habe, wird der
Bereich einmal nach links geSoftscrollt. Dann wird der Zaehler in
Lettercount eins runtergesetzt, war das ergebnis nicht null, sind die 16
noch nicht abgezaehlt und er springt direkt zur mausabfrage, und von da
wieder in die Endlosschleife. Sobald die 0 aber erreicht ist, verzweigt der
bne befehl nicht und arbeitet weiter. Nach dem Bne befehl steht dann der
Aufruf der PufferFuellroutine, sie setzt auch den Zaehler in lettercount
wieder auf 16.

Wie ihr seht, ist es alles sehr einfach...

Viel Spass beim Expirientieren...

                Jeff Kandle
