*
* Dual-Playfield-Scrolling
*
* written on 5/11/89  20:06:33  by Holger Gzella
*
* Die Bitplanes sollen übergroß sein: 416*345 Pixel
* ohne Interlace. Da läßt sich was scrollen!
*

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

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

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

                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  #52*345*6,d0            * Speicher für
                move.l  #MEMREQS,d1             * 6 Planes
                CALLEXEC AllocMem               * allokieren
                tst.l   d0                      * hat's geklappt?
                beq     Fault2                  * nein!
                move.l  d0,Bitplanes            * Zeiger retten
                move.l  d0,Plane1
                add.l   #52*345,d0
                move.l  d0,Plane2
                add.l   #52*345,d0
                move.l  d0,Plane3
                add.l   #52*345,d0
                move.l  d0,Plane4
                add.l   #52*345,d0
                move.l  d0,Plane5
                add.l   #52*345,d0
                move.l  d0,Plane6

*
* An dieser Stelle wird das Multitasking abgeschaltet - sorry.
*

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

*
* Nun wird die Copperlist erstellt - nur das Nötigste ...
*

                move.l  CopperList,a0           * Copperlist nach a0
                moveq   #5,d0                   * 5+1=6 Planes
                move.l  Bitplanes,d1            * Planes nach d1
                move.w  #$E0,d2                 * BPL1PTH nach d2

ListLoop:       move.w  d2,(a0)+                * Register speichern
                addq.w  #2,d2                   * Register-Nr. erhöhen
                swap    d1                      * 1. Word des Zeigers
                move.w  d1,(a0)+                * speichern
                move.w  d2,(a0)+                * Register speichern
                addq.w  #2,d2                   * Register-Nr. erhöhen
                swap    d1                      * 2. Word des Zeigers
                move.w  d1,(a0)+                * speichern
                add.l   #52*345,d1              * Größe einer Plane als
                                                * Offset erhöhen
                dbra    d0,ListLoop             * bis zum Ende

                move.l  #$fffffffe,(a0)         * Ende!

*
* Jetzt werden die wichtigsten Register gesetzt ...
*

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

                move.w  #$1A64,$DFF08E          * DIWSTRT setzen
                move.w  #$39CA,$DFF090          * DIWSTOP setzen

*
* Achten Sie 'drauf: DDFSTRT ist 8 Zyklen kleiner!
*

                move.w  #$0020,$DFF092          * DDFSTRT setzen
                move.w  #$00D8,$DFF094          * DDFSTOP setzen
                move.w  #25600,$DFF100          * 6 Planes/DBPLF -
                                                * BPLCON0 setzen
                move.w  #0,$DFF102              * Scrollzähler zurück
                move.w  #0,$DFF104              * keine spezielle Priorität
                move.w  #4,$DFF108              * Modulo-Wert: 4 Bytes
                move.w  #4,$DFF10A              * Differenz

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

*
* Nun werden zwei RastPorts initialisiert ...
*

                lea     RastPort1,a1            * RastPort 1 laden
                move.l  GfxBase,a6              * Graphics laden
                jsr     _LVOInitRastPort(a6)    * RastPort 1 initialisieren

                lea     RastPort1,a1            * RastPort 1 laden
                lea     BitMap1,a0              * BitMap 1 laden
                move.l  a0,4(a1)                * und eintragen

                lea     RastPort2,a1            * RastPort 2 laden
                move.l  GfxBase,a6              * Graphics laden
                jsr     _LVOInitRastPort(a6)    * RastPort 2 initialisieren

                lea     RastPort2,a1            * RastPort 2 laden
                lea     BitMap2,a0              * BitMap 2 laden
                move.l  a0,4(a1)                * und eintragen

*
* Jetzt werden ein paar zünftige Farben eingeladen ...
*

                lea     Colors,a0               * Farbtabelle
                lea     $DFF180,a1              * Farbregister
                moveq.w #15,d0                  * 15+1=16 Farben

StoreColor:     move.w  (a0)+,(a1)+             * Farbe kopieren
                dbra    d0,StoreColor           * bis zur 8. Farbe

*
* An dieser Stelle wird etwas gezeichnet ...
*

*
* Zuerst widerfährt Playfield 1 eine Zeichnung ...
*

                lea     RastPort1,a1            * erstmal das gesamte
                moveq.w #0,d0                   * Playfield 1 mit der
                jsr     _LVOSetAPen(a6)         * Hintergrundfarbe
                                                * füllen, so daß
                lea     RastPort1,a1            * Playfield 2 durch-
                moveq.w #0,d0                   * schimmern kann!
                moveq.w #0,d1
                move.w  #384,d2
                move.w  #290,d3
                jsr     _LVORectFill(a6)

                lea     RastPort1,a1            * hier wird der Schatten
                moveq.w #2,d0                   * des Kastens gezeichnet.
                jsr     _LVOSetAPen(a6)

                lea     RastPort1,a1
                moveq.w #75,d0
                moveq.w #35,d1
                move.w  #337,d2
                move.w  #245,d3
                jsr     _LVORectFill(a6)

                lea     RastPort1,a1            * natürlich müssen wir
                moveq.w #3,d0                   * auch den Kasten selbst
                jsr     _LVOSetAPen(a6)         * zeichnen, das ist doch
                                                * klar!
                lea     RastPort1,a1
                moveq.w #70,d0
                moveq.w #30,d1
                move.w  #332,d2
                move.w  #240,d3
                jsr     _LVORectFill(a6)

                lea     RastPort1,a1
                moveq.w #5,d0
                jsr     _LVOSetAPen(a6)

                moveq.w #65,d4                  * das mächtige H,
                moveq.w #90,d5                  * ein Buchstabe im
                moveq.w #4,d6                   * Namen des Autors,
                                                * sei nun gezeichnet!
RectLoop1:      lea     RastPort1,a1
                move.w  #128,d0
                move.w  d4,d1
                move.w  #173,d2
                move.w  d5,d3
                jsr     _LVORectFill(a6)

                add.w   #30,d4
                add.w   #30,d5

                dbra    d6,RectLoop1

                lea     RastPort1,a1
                move.w  #181,d0
                moveq.w #125,d1
                move.w  #226,d2
                move.w  #150,d3
                jsr     _LVORectFill(a6)

                moveq.w #65,d4
                moveq.w #90,d5
                moveq.w #4,d6

RectLoop2:      lea     RastPort1,a1
                move.w  #234,d0
                move.w  d4,d1
                move.w  #279,d2
                move.w  d5,d3
                jsr     _LVORectFill(a6)

                add.w   #30,d4
                add.w   #30,d5

                dbra    d6,RectLoop2

                lea     RastPort1,a1
                moveq.w #0,d0
                jsr     _LVOSetAPen(a6)

                moveq.w #68,d4
                moveq.w #87,d5
                moveq.w #4,d6

RectLoop3:      lea     RastPort1,a1
                move.w  #131,d0
                move.w  d4,d1
                move.w  #170,d2
                move.w  d5,d3
                jsr     _LVORectFill(a6)

                add.w   #30,d4
                add.w   #30,d5

                dbra    d6,RectLoop3

                moveq.w #68,d4
                moveq.w #87,d5
                moveq.w #4,d6

RectLoop4:      lea     RastPort1,a1
                move.w  #237,d0
                move.w  d4,d1
                move.w  #276,d2
                move.w  d5,d3
                jsr     _LVORectFill(a6)

                add.w   #30,d4
                add.w   #30,d5

                dbra    d6,RectLoop4

                lea     RastPort1,a1
                move.w  #184,d0
                move.w  #128,d1
                move.w  #223,d2
                move.w  #147,d3
                jsr     _LVORectFill(a6)

                lea     RastPort1,a1            * Schatten des Textes
                moveq.w #2,d0                   * zeichnen
                jsr     _LVOSetAPen(a6)

                lea     RastPort1,a1
                moveq.w #0,d0
                jsr     _LVOSetDrMd(a6)

                lea     RastPort1,a1
                moveq.w #78,d0
                moveq.w #56,d1
                jsr     _LVOMove(a6)

                lea     RastPort1,a1
                lea     Text,a0
                moveq.w #31,d0
                jsr     _LVOText(a6)

                lea     RastPort1,a1            * Text selbst
                moveq.w #1,d0                   * zeichnen
                jsr     _LVOSetAPen(a6)

                lea     RastPort1,a1
                moveq.w #76,d0
                moveq.w #54,d1
                jsr     _LVOMove(a6)

                lea     RastPort1,a1
                lea     Text,a0
                moveq.w #31,d0
                jsr     _LVOText(a6)

*
* Dann ist auch Playfield 2 'dran ... es bekommt ein
* schickes Gittermuster, das beim Scrolling einen
* etwas futurischen Effekt ausweist. Es erinnert an
* künftige Welten ...
*

                lea     RastPort2,a1
                moveq.w #7,d0
                jsr     _LVOSetAPen(a6)

                moveq.w #0,d2                   * horizontales Gitter
                                                * zeichnen ...
GridLoop1:      lea     RastPort2,a1
                move.w  d2,d0
                moveq.w #0,d1
                jsr     _LVOMove(a6)

                lea     RastPort2,a1
                move.w  d2,d0
                move.w  #344,d1
                jsr     _LVODraw(a6)

                add.w   #10,d2
                cmp.w   #383,d2
                blt.s   GridLoop1

                lea     RastPort2,a1
                moveq.w #6,d0
                jsr     _LVOSetAPen(a6)

                moveq.w #0,d2                   * vertikales Gitter
                                                * zeichnen ...
GridLoop2:      lea     RastPort2,a1
                moveq.w #0,d0
                move.w  d2,d1
                jsr     _LVOMove(a6)

                lea     RastPort2,a1
                move.w  #383,d0
                move.w  d2,d1
                jsr     _LVODraw(a6)

                add.w   #10,d2
                cmp.w   #344,d2
                blt.s   GridLoop2

*
* Hier beginnt die eigentliche Scrollroutine ...
* vertikales Scrolling von Playfield 2
* (das mit dem Gittermuster)!
*

                moveq.w #0,d1                   * x-Scrollzähler löschen
                moveq.w #0,d2                   * y-Scrollzähler löschen
                moveq.w #0,d5                   * Richtung: aufwärts!

                move.l  CopperList,a0           * Copperlist laden
                move.l  Bitplanes,a1            * Bitplane-Zeiger laden

*
* Hier setzt das Scrolling ein.
*

MouseLoop:      move.l  $DFF004,d0              * Rasterstrahl-Position
                and.l   #$1ff00,d0              * nur vertikale Position
                cmp.l   #$01000,d0              * Zeile 16?
                bne.s   MouseLoop               * nein!

*
* Mit diesem Code wird fortgesetzt, wenn die Rasterzeile 16 erreicht
* ist und der Elektronenstrahl das Bild noch nicht zeichnet.
*

                cmp.w   #1,d5                   * abwärts scrollen?
                beq.s   ScrollDown              * ja!

                addq.w  #1,d2                   * y-Scrollzähler erhöhen
                cmp.w   #256,d2                 * 256 (8*32) erreicht?
                bne.s   GoOnVert                * nein ... normal weiter

*
* Der vertikale Scrollzähler befindet sich am Rand
* der BitMap. Er muß zurückgesetzt werden!
*

                moveq.w #1,d5                   * Richtungswechsel!

ScrollDown:     subq.w  #1,d2                   * y-Scrollzähler - 1
                cmp.w   #0,d2                   * 0 erreicht?
                bne.s   GoOnVert                * nein ... weiter

                moveq.w #0,d5                   * Richtungswechsel!

GoOnVert:       move.w  d2,d3                   * y-Scrollzähler kopieren
                lsr.w   #2,d3                   * und durch 4 teilen
                mulu.w  #52,d3                  * mal 52 Bytes/Zeile
                add.l   a1,d3                   * und Planeadresse
                add.l   #52*345,d3              * und Planegröße ergibt
                                                * einen Offset
                move.w  d3,14(a0)               * dieser Offset entspricht
                                                * der neuen Plane-Endadresse,
                                                * genauer gesagt, dem
                                                * unteren Word, das in die
                                                * Copperlist gespeichert
                                                * werden muß.
                swap    d3                      * oberes Word holen
                move.w  d3,10(a0)               * auch das obere Word
                                                * muß gespeichert werden
                swap    d3                      * unteres Word holen

                add.l   #52*345*2,d3            * und Planegröße*2 ergibt
                                                * einen Offset für die
                                                * nächste gerade Plane
                move.w  d3,30(a0)               * dieser Offset entspricht
                                                * der neuen Plane-Endadresse,
                                                * genauer gesagt, dem
                                                * unteren Word, das in die
                                                * Copperlist gespeichert
                                                * werden muß.
                swap    d3                      * oberes Word holen
                move.w  d3,26(a0)               * auch das obere Word
                                                * muß gespeichert werden
                swap    d3                      * unteres Word holen

                add.l   #52*345*2,d3            * und Planegröße*2 ergibt
                                                * einen brauchbaren Offset
                move.w  d3,46(a0)               * dieser Offset entspricht
                                                * der neuen Plane-Endadresse,
                                                * genauer gesagt, dem
                                                * unteren Word, das in die
                                                * Copperlist gespeichert
                                                * werden muß.
                swap    d3                      * oberes Word holen
                move.w  d3,42(a0)               * auch das obere Word
                                                * muß gespeichert werden

                btst.b  #6,$bfe001              * Maustaste abfragen
                bne     MouseLoop               * nicht gedrückt

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

                move.l  GfxBase,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  #$83E0,$DFF096          * deaktivierte
                                                * DMA-Kanäle wieder
                                                * einschalten

                CALLEXEC Permit                 * Multitasking erlauben

                move.l  Bitplanes,a1            * Bitplanes im
                move.l  #52*345*6,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

Text:           dc.b     "D U A L  -  P L A Y F I E L D S",0
 even

GfxBase:        dc.l     0

CopperList:     dc.l     0                      * Zeiger auf die Copperlist
Bitplanes:      dc.l     0                      * Zeiger auf die Planes

RastPort1:      ds.b     100                    * Speicher für einen RastPort
RastPort2:      ds.b     100                    * Speicher für einen RastPort

BitMap1:        dc.w     52                     * 52 Bytes pro Zeile
                dc.w     345                    * 345 Zeilen
                dc.b     0,3,0,0                * 3 Bitplanes
Plane1:         dc.l     0                      * Zeiger
Plane3:         dc.l     0
Plane5:         dc.l     0

BitMap2:        dc.w     52                     * 52 Bytes pro Zeile
                dc.w     345                    * 345 Zeilen
                dc.b     0,3,0,0                * 3 Bitplanes
Plane2:         dc.l     0
Plane4:         dc.l     0
Plane6:         dc.l     0

Colors:         dc.w     $000,$FFF,$333,$555,$00F,$FB0,$CCC,$444
                dc.w     $000,$FFF,$F00,$0F0,$00F,$FB0,$CCC,$888

                END

