*
* Farbrotation mit dem Copper - auch in Assembler.
*
* created on 22/10/89  15:40:30  by Holger Gzella
*

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

*
* Libraries, Window und Screen öffnen
*
                lea     GfxName,a1              * Graphics öffnen
                moveq.l #0,d0
                CALLEXEC OpenLibrary
                move.l  d0,GfxBase

                lea     IntuiName,a1            * Intuition öffnen
                moveq.l #0,d0
                CALLEXEC OpenLibrary
                move.l  d0,IntuiBase

                move.l  d0,a6
                lea     ScreenDefs,a0           * Screen öffnen
                jsr     _LVOOpenScreen(a6)
                tst.l   d0
                beq     Fault
                move.l  d0,ScreenPtr

                lea     WindowDefs,a0
                jsr     _LVOOpenWindow(a6)
                tst.l   d0
                beq     Fault2
                move.l  d0,WindowPtr
                move.l  d0,a0
                move.l  $32(a0),RastPort

*
* Jetzt wird etwas gezeichnet, damit man von der Liste
* auch ordentlich was sieht!
*

                move.l  WindowPtr,a0            * ViewPort des
                jsr     _LVOViewPortAddress(a6) * Screens holen
                move.l  d0,ViewPort

                move.l  GfxBase,a6              * Vordergrundfarbe
                move.l  RastPort,a1             * auf 1 setzen, damit
                moveq.l #1,d0                   * man die schöne Copperlist,
                jsr     _LVOSetAPen(a6)         * die das Register 1
                                                * betrifft, sieht ...

                move.l  ViewPort,a0             * Hintergrundfarbe
                moveq.w #0,d0                   * auf
                moveq.w #0,d1                   * Schwarz
                moveq.w #0,d2                   * setzen!
                moveq.w #0,d3
                jsr     _LVOSetRGB4(a6)

                move.l  RastPort,a1             * Text ausgeben
                moveq.w #50,d0
                moveq.w #50,d1
                jsr     _LVOMove(a6)

                move.l  RastPort,a1
                lea     Text,a0
                move.w  #43,d0
                jsr     _LVOText(a6)

                moveq.w #1,d7

*
* Diese Schleife wird durchlaufen, bis der Benutzer
* eine Maustaste gedrückt hat. Es werden dynamisch
* immer neue Copperlists erzeugt.
*

MouseLoop:

*
* Hier wird Speicher für die Copperlist geholt.
*

                move.l  #$10001,d1              * PUBLIC u. memClear
                moveq.l #12,d0                  * 12 Bytes
                CALLEXEC AllocMem               * allokieren!
                tst.l   d0                      * alles klar?
                beq     MemFault                * nö!
                move.l  d0,CList                * Zeiger retten

*
* An dieser Stelle wird die Copperliste aufgebaut.
*

                moveq.w #0,d5                   * Zähler löschen
                lea     Colors,a2               * Tabelle laden

CopLoop:        move.w  d5,d3                   * Zähler nach d3
                sub.w   d7,d3                   * minus d7 (Zähler 2)
                move.w  d3,d0                   * d3 nach d0
                divu.w  #60,d3                  * durch Farbanzahl
                mulu.w  #60,d3                  * mal Farbanzahl
                sub.w   d3,d0                   * d0-d3

                                                * hier wurde der Modulo-
                                                * Wert (Rest) der Division
                                                * (i-j)/61 errechnet, indem
                                                * (i-j)/61 zuerst ganzzahlig
                                                * gemacht wurde (DIVU..MULU)
                                                * und dann der Ausgangswert
                                                * (i-j) weniger dem Ergebnis
                                                * der Division gerechnet
                                                * wurde.

                asl.w   #1,d0                   * d0 mal 2 (wg. Words)
                move.w  0(a2,d0.w),d6           * entsprechenden Wert aus
                                                * der Tabelle holen

                moveq.l #0,d3                   * d3 löschen (x-Position 0)
                move.l  #256,d2                 * Zeilenzahl nach d2
                divu    #60,d2                  * durch Farbanzahl
                mulu    d5,d2                   * mal Zähler
                bsr     CopWait                 * =CWAIT-y-Position

                move.w  #$182,d2                * Vordergrundfarbe 1
                move.w  d6,d3                   * Farbe setzen
                bsr     CopMove

                addq    #1,d5                   * Zähler 1 erhöhen
                cmp.l   #60,d5                  * alle Farben durch?
                bne.s   CopLoop                 * nein!

*
* Die Instruktionsliste muß natürlich auch noch aktiviert werden.
*

                move.l  #10000,d2               * auf (256;10000) warten:
                move.l  #256,d3                 * unmögliche Position, heißt
                bsr     CopWait                 * Ende der Liste!

                move.l  ViewPort,a5

                addq    #1,d7                   * Zähler erhöhen

                move.l  8(a5),a2                * dspIns retten
                move.l  12(a5),a3               * sprIns retten
                move.l  16(a5),a4               * clrIns retten

                CALLEXEC Forbid                 * Multitasking verbieten

                move.l  #0,8(a5)                * dspIns löschen
                move.l  #0,12(a5)               * sprIns löschen
                move.l  #0,16(a5)               * clrIns löschen

                move.l  a5,a0                   * User-List freigeben
                move.l  GfxBase,a6
                jsr     _LVOFreeVPortCopLists(a6)

                move.l  a2,8(a5)                * dspIns setzen
                move.l  a3,12(a5)               * sprIns setzen
                move.l  a4,16(a5)               * clrIns setzen

                move.l  CList,20(a5)            * User-List eintragen

                CALLEXEC Permit                 * Multitasking erlauben

                move.l  GfxBase,a6              * synchronisieren
                jsr     _LVOWaitTOF(a6)

                move.l  IntuiBase,a6            * Display erneuern
                jsr     _LVORethinkDisplay(a6)

                btst.b  #6,$bfe001              * Maustaste?
                bne     MouseLoop               * nein!

*
* Ende - alles schließen
*

MemFault:       move.l  WindowPtr,a0
                jsr     _LVOCloseWindow(a6)

Fault2:         move.l  ScreenPtr,a0
                move.l  IntuiBase,a6
                jsr     _LVOCloseScreen(a6)

Fault:          move.l  IntuiBase,a1
                CALLEXEC CloseLibrary

                move.l  GfxBase,a1
                CALLEXEC CloseLibrary

                moveq.l #0,d0
                rts

*
* Unterprogramme ...
*

*
* Diese Routine entspricht etwa CWAIT aus GfxMacros.
* Übergeben werden müssen:
*
* D2 - y-Koordinate der Position, auf die gewartet werden soll.
* D3 - x-Koordinate der Position, auf die gewartet werden soll.
*

CopWait:        move.l  d2,d0                   * y-Koordinate und
                move.l  d3,d1                   * x-Koordinate sowie
                move.l  CList,a1                * Copperlist-Zeiger setzen!
                move.l  GfxBase,a6              * CWait
                jsr     _LVOCWait(a6)           * aufrufen!
                move.l  CList,a1                * CBump
                move.l  GfxBase,a6              * auf-
                jsr     _LVOCBump(a6)           * rufen
                rts                             * und zurück!

*
* Hier steht eine Art Äquivalent zu CMOVE.
* Diese Parameter werden benötigt:
*
* D0 - Offset des Hardware-Registers von $DFF000.
* D1 - Wert, den das Register erhalten soll.
*

CopMove:        move.l  d2,d0                   * Offset,
                move.l  d3,d1                   * Wert und
                move.l  CList,a1                * Zeiger setzen,
                move.l  GfxBase,a6              * dann
                jsr     _LVOCMove(a6)           * CMove und
                move.l  CList,a1                * darauf
                move.l  GfxBase,a6              * CBump
                jsr     _LVOCBump(a6)           * aufrufen!
                rts                             * zurück!

*
* Datenteil ...
*

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

 even
WindowDefs:     dc.w    0,11,640,245,1
                dc.l    $200,$E,0,0,Titel
ScreenPtr:      dc.l    0,0,0,0
                dc.w    $F

 even
ScreenDefs:     dc.w    0,0,640,256,2,1,$8000,$F,0,0
                dc.l    0,0,0

Titel:          dc.b    "Ein Copper-Demoprogramm",0
 even

*
* Die Tabelle mit den zu rotierenden Farben ... 60 an der Zahl,
* verteilt auf Rot- und Grünabstufungen ...
*

Colors:         dc.w    $000,$100,$200,$300,$400,$500,$600,$700,$800
                dc.w    $900,$A00,$B00,$C00,$D00,$E00,$F00,$E00,$D00
                dc.w    $C00,$B00,$A00,$900,$800,$700,$600,$500,$400
                dc.w    $300,$200,$100
                dc.w    $000,$010,$020,$030,$040,$050,$060,$070,$080
                dc.w    $090,$0A0,$0B0,$0C0,$0D0,$0E0,$0F0,$0E0,$0D0
                dc.w    $0C0,$0B0,$0A0,$090,$080,$070,$060,$050,$040
                dc.w    $030,$020,$010

Text:           dc.b    "Farbrotation mit dem Copper - in Assembler!",0
 even

GfxBase:        dc.l    0
IntuiBase:      dc.l    0
WindowPtr:      dc.l    0
RastPort:       dc.l    0
CList:          dc.l    0
ViewPort:       dc.l    0

                END

