*
* Playfield-Scrolling
*
* written on 5/11/89  18:38:50  by Holger Gzella
*
* Die Bitplanes sollen übergroß sein: 640*512 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  #80*512*2,d0            * Speicher für
                move.l  #MEMREQS,d1             * 2 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   #80*512,d0
                move.l  d0,Plane2

*
* 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   #1,d0                   * 1+1=2 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   #80*512,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  #$2981,$DFF08E          * DIWSTRT setzen
                move.w  #$29C1,$DFF090          * DIWSTOP setzen

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

                move.w  #$0030,$DFF092          * DDFSTRT setzen
                move.w  #$00D0,$DFF094          * DDFSTOP setzen
                move.w  #$2000,$DFF100          * 2 Planes - BPLCON0 setzen
                move.w  #0,$DFF102              * Scrollzähler zurück
                move.w  #0,$DFF104              * Standard-Priorität
                move.w  #40,$DFF108             * Modulo-Wert: 40 Bytes
                move.w  #40,$DFF10A             * Differenz

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

*
* Nun wird ein RastPort initialisiert ...
*

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

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

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

                moveq   #0,d3

DrawSomething:  lea     RastPort,a1
                move.w  #0,d0
                move.w  d3,d1
                jsr     _LVOMove(a6)

                lea     RastPort,a1
                move.w  #1023,d0
                move.w  d3,d1
                jsr     _LVODraw(a6)

                add.w   #32,d3
                cmp.w   #512,d3
                blt.s   DrawSomething

                lea     RastPort,a1
                moveq.w #2,d0
                jsr     _LVOSetAPen(a6)

                moveq   #0,d4

DrawSomething2: lea     RastPort,a1
                move.w  d4,d0
                move.w  #0,d1
                jsr     _LVOMove(a6)

                lea     RastPort,a1
                move.w  d4,d0
                move.w  #511,d1
                jsr     _LVODraw(a6)

                add.w   #32,d4
                cmp.w   #1024,d4
                blt.s   DrawSomething2

                moveq.w #0,d1                   * x-Scrollzähler löschen
                moveq.w #0,d2                   * y-Scrollzähler löschen
                moveq.w #0,d5                   * Spezialwert löschen

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

*
* Hier setzt das Scrolling ein. Die Plane 2 wird vertikal,
* Plane 1 horizontal gescrollt. Das gibt einen chaotischen,
* aber dennoch in gewisser Hinsicht coolen Effekt.
*

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.
*

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

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

                moveq.w #0,d2                   * y-Scrollzähler löschen

GoOnVert:       move.w  d2,d3                   * y-Scrollzähler kopieren
                lsr.w   #2,d3                   * und durch 4 teilen
                mulu.w  #40,d3                  * mal 40 Bytes/Zeile
                add.l   a1,d3                   * und Planeadresse
                add.l   #80*512,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

*
* Nun wird die Plane 1 horizontal gescrollt.
*

                addq.w  #1,d1                   * x-Scrollzähler erhöhen
                cmp.w   #1280,d1                * 1280 (4*320) erreicht?
                bne.s   GoOnHoriz               * nein!

*
* Der horizontale Scrollzähler muß zurückgesetzt werden!
*

                moveq.w #0,d1                   * x-Scrollzähler löschen

GoOnHoriz:      move.w  d1,d3                   * x-Scrollzähler kopieren
                lsr.w   #2,d3                   * und, wegen der Word-
                                                * Zählweise, durch 4
                                                * dividieren
                move.w  d3,d4                   * und wieder kopieren
                and.w   #$FFF0,d3               * unteren Bits sind egal
                sub.w   d3,d4                   * die unteren Bits müssen
                                                * allein stehen
                lsr.w   #3,d3                   * durch 8 dividieren =
                                                * neue Adresse der Plane
                add.l   a1,d3                   * Ursprungsadresse addieren
                move.w  d3,6(a0)                * unteres Word speichern
                swap    d3                      * oberes Word holen
                move.w  d3,2(a0)                * und ebenfalls speichern

                move.w  d5,$DFF102              * der letzte Scrollwert
                                                * gibt den Pixelzähler an.
                                                * er muß nach BPL1CON, da
                                                * durch ihn der horizontale
                                                * Scrolloffset angegeben
                                                * wird
                move.w  d4,d5                   * alten Scrolloffset retten

                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  #80*512*2,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

GfxBase:        dc.l     0

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

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

BitMap:         dc.w     80                     * 80 Bytes pro Zeile
                dc.w     512                    * 512 Zeilen
                dc.b     0,2,0,0                * 2 Bitplanes
Plane1:         dc.l     0                      * Zeiger
Plane2:         dc.l     0

                END

