*
* Demo für den Blitter-Linienmodus
*
* created on 12/11/89  17:10:43  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  #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

*
* Hier wird der Blitter übernommen.
*

                move.l  GfxBase,a6              * GfxBase laden
                jsr     _LVOOwnBlitter(a6)      * auch wenn das Multitasking
                                                * abgeschaltet wird, sollte
                                                * der Blitter IMMER mit
                                                * OwnBlitter übernommen
                                                * werden!
                jsr     _LVOWaitBlit(a6)        * auf Blitter warten

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

*
* An dieser Stelle werden zufällige Linien gezeichnet,
* bis irgendwer die Maustaste drückt oder ein sonstiges
* Ereignis dem Programm ein Ende bereitet (z.B. ein
* Stromausfall) ...
*

                moveq.w #40,d4                  * Breite: immer 40 Bytes
                move.l  Bitplane,a0             * Planeadresse laden

LineLoop:       move.w  #319,d7                 * Schleifenzähler

DrawLoop:       move.w  #319,d0                 * x1 immer 319
                moveq.w #0,d1                   * y1 immer 0
                move.w  d7,d2                   * Schleifenzähler nach x2
                move.w  #255,d3                 * y2 immer 255
                move.w  $DFF006,a1              * Zufallswert(???) laden
                move.l  GfxBase,a6              * GfxBase laden
                bsr     BlitLine                * Linie zeichnen
                dbra    d7,DrawLoop             * Zähler-1 und wiederholen

                move.w  #319,d7                 * Zähler neu setzen

DrawLoop2:      move.w  #319,d0                 * x1 immer 319
                move.w  #255,d1                 * y1 immer 255
                move.w  d7,d2                   * x2 mit Zähler laden
                moveq.w #0,d3                   * y2 immer 0
                move.w  $DFF006,a1              * Muster holen
                move.l  GfxBase,a6              * GfxBase laden
                bsr     BlitLine                * Linie zeichnen
                dbra    d7,DrawLoop2            * Zähler-1 und wiederholen

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

*
* F E R T I G !
*

                move.l  GfxBase,a6              * GfxBase laden
                jsr     _LVOWaitBlit(a6)        * auf Blitter warten

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

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

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

                move.l  GfxBase,a6              * GfxBase holen
                jsr     _LVODisownBlitter(a6)   * Blitter freigeben

                move.l   a6,a1
                CALLEXEC CloseLibrary           * Graphics schließen

                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

*
* Diese Routine zeichnet eine Linie mit dem Blitter.
* Für die Übernahme des Blitters muß der Aufrufer sorgen.
* Folgende Parameter sind notwendig:
*
* D0 - x-Koordinate des Startpunktes der Linie
* D1 - y-Koordinate des Startpunktes der Linie
* D2 - x-Koordinate des Endpunktes der Linie
* D3 - y-Koordinate des Endpunktes der Linie
* D4 - Breite der Bitplane in Bytes
* A0 - Zeiger auf die Bitplane
* A1 - Linienmaske
* A6 - Zeiger auf die GfxBase
*

BlitLine:       movem.l d2-d7/a2-a6,-(SP)       * Register retten

*
* Hier wird die Anfangsadresse der Linie berechnet.
*

                moveq   #-16,d6                 * -16 nach d6
                and.w   d0,d6                   * untere vier Bits der
                                                * x-Koordinate des Start-
                                                * punktes ausmaskieren
                lsr.w   #3,d6                   * durch 8 dividieren
                move.w  d4,d5                   * Breite kopieren
                mulu    d1,d5                   * mit der y-Koordinate
                                                * multiplizieren
                add.w   d6,d5                   * x1/8 addieren
                add.l   a0,d5                   * Anfangsadresse der
                                                * Plane addieren

*
* Nun müssen die SUL-/SUD-/AUL-Bits gefunden werden ...
*

                moveq.l #0,d6                   * d6 löschen

                sub.w   d1,d3                   * y-Delta errechnen
                roxl.b  #1,d6                   * Vorzeichen des y-Deltas
                                                * nach d6
                tst.w   d3                      * ist das y-Delta positiv?
                bge.s   yDeltaPos               * ja!

                neg.w   d3                      * jetzt ist es positiv!

yDeltaPos:      sub.w   d0,d2                   * x-Delta errechnen
                roxl.b  #1,d6                   * Vorzeichen des x-Deltas
                                                * nach d6
                tst.w   d2                      * ist das x-Delta positiv?
                bge.s   xDeltaPos               * es ist!

                neg.w   d2                      * nun ist es positiv!
                
xDeltaPos:      move.w  d3,d1                   * y-Delta nach d1
                sub.w   d2,d1                   * x-Delta subtrahieren
                bge.s   BigYdelta               * y-Delta ist größer

                exg     d2,d3                   * y-Delta nach d2

BigYdelta:      roxl.b  #1,d6                   * Oktanten-Offset holen
                lea     Oktanten,a2             * Tabellenadresse holen
                move.b  0(a2,d6),d6             * Wert holen
                lsl.w   #1,d2                   * kleineres Delta mal 2

                movem.l d0/d1/a0/a1,-(SP)       * Trash-Register retten
                jsr     _LVOWaitBlit(a6)        * ist der Blitter fertig?
                movem.l (SP)+,d0/d1/a0/a1       * Trash-Register holen

                move.w  d6,$DFF042              * d6 nach BLTCON1
                move.w  d2,$DFF062              * 2 mal kleineres Delta
                                                * nach BLTBMOD
                sub.w   d3,d2                   * größeres Delta abziehen
                bge.s   Unsigned                * kein Vorzeichen

                or.b    #64,d6                  * Vorzeichenbit (SIGN)
                                                * setzen

Unsigned:       move.w  d2,$DFF052              * d2 nach BLTAPTL
                sub.w   d3,d2                   * größeres Delta abziehen
                move.w  d2,$DFF064              * d2 nach BLTAMOD

                move.w  a1,$DFF072              * Maske nach BLTBDAT
                and.w   #15,d0                  * untere vier Bits der
                                                * x-Koordinate des Start-
                                                * punktes ausmaskieren
                ror.w   #4,d0                   * heraufschieben
                or.w    #3018,d0                * Rest von BLTCON0 hinzufügen
                move.w  d0,$DFF040              * d0 nach BLTCON0
                move.w  d4,$DFF066              * Breite nach BLTDMOD
                move.w  d4,$DFF060              * und nach BLTCMOD
                move.l  d5,$DFF048              * Startadresse der Linie
                                                * nach BLTCPTH/L
                move.l  d5,$DFF054              * und nach BLTDPTH/L
                move.w  #$ffff,$DFF044          * $FFFF nach BLTAFWM
                move.w  #$8000,$DFF074          * $8000 nach BLTADAT
                lsl.w   #6,d3                   * Liniengröße ausrechnen
                addq.w  #2,d3
                move.w  d3,$DFF058              * Blitter starten

                movem.l (SP)+,d2-d7/a2-a6       * Register holen

                rts

*
* Auch hier wieder ein Datenteil ...
*

*
* Dies ist die Tabelle mit den SUL-/SUD-/AUL-WERTEN (nicht Bits!!)
* inklusive gesetztem LINE-Bit (Bit 0).
*

Oktanten:       dc.b     1,17,9,21,5,25,13,29

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

GfxBase:        dc.l     0

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

                END

