*
* Demo für Scrolling über BitMap-Schieberei
*
* written on 30/11/89  19:13:33  by Holger Gzella
*

                incdir "asm:"
                include "exec/exec_lib.i"
                include "graphics/graphics_lib.i"

MEMREQS         EQU     $10000|$2               * CHIP u. clear

StartProg:      lea     GfxName,a1              * Graphics öffnen
                moveq   #0,d0
                CALLEXEC OpenLibrary
                move.l  d0,GfxBase

                move.l  d0,a6
                lea     Font,a0                 * Font in a0 laden
                jsr     _LVOOpenFont(a6)        * und öffnen
                beq     Fault                   * konnte nicht geöffnet
                                                * werden - schade!
                move.l  d0,FontBase             * Zeiger sichern

                move.l  #2000,d0                * 2000 Bytes
                move.l  #MEMREQS,d1             * CHIP-Memory
                CALLEXEC AllocMem               * allokieren
                tst.l   d0                      * alles klar?
                beq     Fault                   * nein - beenden!
                move.l  d0,CopperList           * Zeiger sichern

                move.l  #40*256,d0              * Speicher
                move.l  #MEMREQS,d1             * für Bitplane
                CALLEXEC AllocMem               * allokieren
                tst.l   d0                      * hat's geklappt?
                beq     Fault2                  * nein!
                move.l  d0,Bitplane             * Zeiger retten

*
* An dieser Stelle wird der Rechner übernommen.
*

                CALLEXEC Forbid                 * kein Multitasking
                move.w  #$3e0,$DFF096           * Copper-, Sprite- und
                                                * andere DMAs sowie DMAEN
                                                * löschen

*
* Nun wird die Copperlist erstellt - keine Schnörkel!
*

                move.l  CopperList,a0           * Copperlist nach a0
                move.l  Bitplane,d2             * Bitplane nach d2
                swap    d2                      * auf oberes Word richten

*
* Hier werden erstmal die Bitplane-Zeiger zurückgesetzt.
*

                move.w  #$0E0,(a0)+             * Register: BPL1PTH
                move.w  d2,(a0)+                * oberes Word des Plane-
                                                * zeigers setzen
                move.w  #$0E2,(a0)+             * Register: BPL1PTL
                swap    d2                      * unteres Word holen
                move.w  d2,(a0)+                * und setzen

*
* Jetzt geht's recht normal weiter ...
*

                move.w  #$180,(a0)+             * Farbe:
                move.w  #$000,(a0)+             * schwarzer Hintergrund
                move.l  #$fffffffe,(a0)         * Ende!

                move.l  CopperList,$DFF080      * List manipulieren
                move.w  #0,$DFF088              * COPJMP1 löschen

                move.w  #$2981,$DFF08E          * DIWSTRT setzen
                move.w  #$29C1,$DFF090          * DIWSTOP setzen
                move.w  #$0038,$DFF092          * DDFSTRT setzen
                move.w  #$00D0,$DFF094          * DDFSTOP setzen
                move.w  #$1000,$DFF100          * 1 Plane - BPLCON0 setzen
                move.w  #0,$DFF102              * kein Scrolling
                move.w  #0,$DFF104              * kein Dual-Playfield
                move.w  #0,$DFF108              * kein Modulo
                move.w  #0,$DFF10A              * soll benutzt werden

                move.w  #$83C0,$DFF096          * alle wichtigen DMAs und
                                                * und DMAEN aktivieren

*
* Nun wird gescrollt!
*
* Das Scrolling funktioniert allerdings nur
* mit 8 Pixel breiten, nicht proportionalen Fonts!
*

                moveq.l #0,d0                   * Scrollzähler löschen
                lea     Text,a4                 * Scrolltext nach a4

ScrollIt:       and.l   #$7,d0                  * sind alle 8 Pixel dieses
                                                * Buchstabens dargestellt?
                bne.s   ScrollOn                * nein ... weiterscrollen

*
* Dieser Abschnitt setzt den Font-Daten-Zeiger
* auf die letzte Zeile des Fonts.
*

                move.l  FontBase,a0             * Font-Basis holen
                move.l  34(a0),a3               * Zeiger auf Font-Daten
                move.w  38(a0),d4               * Modulo des Fonts
                move.w  d4,d5
                mulu    #7,d4                   * mal die Höhe des Fonts
                add.l   d4,a3                   * Zeiger auf die letzte Zeile
                                                * der Font-Daten richten

*
* Hier wird der nächste, "hereinzuscrollende"
* Buchstabe aus dem Textstring geholt.
*

                moveq.l #0,d1

                move.b  (a4)+,d1                * nächsten Buchstaben laden
                bne.s   NotTheLast              * sollte dieser kein Nullbyte
                                                * sein, wird gescrollt, an-
                                                * sonsten der erste Buchstabe
                                                * geladen!

                lea     Text,a4                 * Textadresse laden
                move.b  (a4)+,d1                * Buchstaben holen

NotTheLast:     cmp.b   #127,d1                 * Sonderzeichen???
                bls.s   NoSpecialChar           * nein, alles bestens!

*
* Falls im Text ein Sonderzeichen (z.B. ein Umlaut)
* vorkommt, muß dessen ASCII-Code um 32 herunter-
* gerechnet werden, da die Zeichen mit den Codes
* 128 bis 159 ($80 bis $9f) im "topaz"-Datenblock
* nicht definiert sind. Da Sonderzeichen ASCII-Codes
* von größer als 128 haben, müssen die nicht defi-
* nierten Zeichen übersprungen werden.
*

                sub.b   #32,d1                  * $80-$9f überspringen

*
* Auch die ASCII-Codes $00-$1f (0-31) sind nicht
* im "topaz.font"-Datenblock definiert (aus be-
* greiflichen Gründen - sie sind nicht darstellbar!).
* Somit hat JEDES darstellbare Zeichen einen ASCII-Code
* von 32 oder darüber und muß um 32 Codes herunter-
* gerechnet werden.
*

NoSpecialChar:  sub.b   #32,d1                  * $00-$1f überspringen

                add.l   d1,a3                   * Zeiger korrekt setzen

ScrollOn:       move.l  Bitplane,a0             * Bitplane-Zeiger laden

                add.l   #128*40,a0              * Position (Zeile 128) setzen
                moveq.l #7,d1                   * 8 Zeilen scrollen

                move.l  a3,a5                   * Zeiger retten

*
* Für ein fließendes Scrolling ist es wichtig, zu warten, bis
* der Elektronenstrahl die richtige Position erreicht hat.
*

BeamSyncLoop:   move.l  $DFF004,d3              * Rasterstrahl-Position
                and.l   #$1ff00,d3              * nur vertikale Position
                cmp.l   #$08000,d3              * richtige Zeile (#128)?
                bne.s   BeamSyncLoop            * nein!

*
* Hier beginnt das eigentliche Scrolling.
*

                add.b   #$8,d0                  * Scrollzähler auf Word-
                                                * größe bringen

ScrollPlane:    moveq.l #19,d3                  * 20 Words auf einen Schlag
                moveq   #0,d2                   * welches Bit?
                move.b  (a5),d2                 * entsprechende Daten holen
                sub.l   d5,a5                   * Zeiger zurücksetzen

                roxl.w  #1,d2                   * und Daten des aktuellen
                roxl.w  d0,d2                   * Zeichens ermitteln

ScrollWord:     roxl.w  -(a0)                   * Word nach links schieben
                                                * (probieren Sie mal
                                                * ROXR.W (A0)+!)

                dbra    d3,ScrollWord           * bis alle 8 Zeilen ver-
                                                * schoben sind!

                dbra    d1,ScrollPlane          * bis die gesamte Plane,
                                                * bzw. deren Inhalt, ver-
                                                * schoben ist!

*
* An dieser Stelle wird etwas gewartet ...
*

GetActTime:     move.b  $bfea01,d2              * Highbyte der Zeit lesen
                lsl.l   #8,d2                   * mal 256
                move.b  $bfe901,d2              * Midbyte der Zeit lesen
                lsl.l   #8,d2                   * mal 256
                move.b  $bfe801,d2              * Lobyte der Zeit lesen

*
* Dieser Abschnitt wird solange wiederholt, bis die
* verstrichene Zeit 1/50stel Sekunde beträgt.
*

WaitTime:       move.b  $bfea01,d3
                lsl.l   #8,d3
                move.b  $bfe901,d3
                lsl.l   #8,d3
                move.b  $bfe801,d3

                move.l  d3,d7                   * neue Zeit retten
                sub.l   d2,d7                   * subtrahieren
                cmp.b   #1,d7                   * 1/50stel Sek. Differenz?
                blt.s   WaitTime                * nein!

                addq    #1,d0                   * nächstes Zeichen

Mouse:          btst.b  #6,$bfe001              * Maustaste gedrückt?
                bne     ScrollIt                * nein ... weiterscrollen

*
* Hier wird der ursprüngliche Zustand wieder hergestellt.
*

                move.l  GfxBase,a6
                move.l  FontBase,a1             * Font schließen
                jsr     _LVOCloseFont(a6)

                move.l  a6,a1                   * Graphics laden
                move.l  38(a1),$DFF080          * System-List wieder
                                                * aktivieren

                CALLEXEC CloseLibrary           * Graphics schließen

                move.l  #0,$DFF088              * COPJMP1 löschen
                move.w  #$8020,$DFF096          * deaktivierte
                                                * DMA-Kanäle wieder
                                                * einschalten

                CALLEXEC Permit                 * Multitasking erlauben

                move.l  Bitplane,a1             * Bitplane im
                move.l  #40*256,d0              * CHIP-Speicher
                CALLEXEC FreeMem                * deallokieren

Fault2:         move.l  CopperList,a1           * Copperlist im
                move.l  #2000,d0                * CHIP-RAM wieder
                CALLEXEC FreeMem                * deallokieren

Fault:          moveq   #0,d0                   * Ende!
                rts

*
* Auch hier wieder ein Datenteil ...
*

GfxName:        dc.b     "graphics.library",0
 even

*
* Dies ist der Text, der gescrollt werden soll.
* Er kann fast beliebig lang sein und muß mit
* einem Nullbyte enden.
*

Text:           dc.b     "Dies ist ein Demoprogramm "
                dc.b     "für die Programmierung von "
                dc.b     "Laufschriften über direktes "
                dc.b     "Schieben der Bits durch die "
                dc.b     "Plane.                      "
                dc.b     "                            ",0
 even

GfxBase:        dc.l     0

CopperList:     dc.l     0                      * Zeiger auf die Copperlist
Bitplane:       dc.l     0                      * Zeiger auf die Plane

Font:           dc.l FontName                   * TextAttr-Struktur
                dc.b 0,8,0,1                    * topaz80, normal und ROMFONT

FontName:       dc.b "topaz.font",0             * Name des Fonts

FontBase:       dc.l 0                  * Zeiger auf Font

                END

