*
* Ein Späßchen.
*
* created on 17/10/89  17:44:13
*
* Die Routine, die das Drehen der BitMap verursacht, basiert
* auf einem Programm von MIKE BERRO (RPD 30).
*

                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                   * Window öffnen
                lea     WindowDefs,a0
                jsr     _LVOOpenWindow(a6)
                tst.l   d0
                beq     Fault
                move.l  d0,WindowPtr

                move.l  d0,a0                   * WindowPtr nach A1
                move.l  50(a0),a1               * und den RastPort holen

                move.l  4(a1),srcBitMap         * BitMap retten

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

                move.l  d0,a0                   * BitMap2 retten
                lea     184(a0),a1
                move.l  a1,dstBitMap

*
* Nun tritt der Blitter in Aktion.
*

                move.l  srcBitMap,a0            * 1. BitMap
                moveq.w #0,d0                   * srcX
                moveq.w #0,d1                   * srcY
                moveq.w #0,d2                   * dstX
                moveq.w #0,d3                   * dstY
                move.w  0(a0),d4                * sizeX in Pixeln
                lsl.w   #3,d4                   * und in Bytes
                move.w  2(a0),d5                * sizeY
                move.b  #$c0,d6                 * Minterm: 1:1-Kopie
                move.b  #$ff,d7                 * alle Bitplanes
                move.l  #0,a2                   * kein temporärer Speicher
                move.l  GfxBase,a6              * GfxBase laden
                jsr     _LVOBltBitMap(a6)       * und BitMap kopieren!

                move.w  #$100,d0                * Display abschalten
                move.w  d0,$dff096

                move.l  dstBitMap,a0
                move.l  8(a0),a0                * Plane 1 flippen
                bsr     FlipIt
                move.l  dstBitMap,a0
                move.l  12(a0),a0               * Plane 2 flippen
                bsr     FlipIt

                move.w  #$8100,d0               * Display einschalten
                move.w  d0,$dff096

*
* Hier wird's interessant ... nun wird gewartet, bis der User
* das Close-Gadget angeklickt hat. Ohne Zweifel ein gutes Beispiel
* für die Handhabung von IDCMPs, die Sie aber schon aus früheren
* Programmen kennen müßten.
*

MessageLoop:    move.l  WindowPtr,a0            * WindowPtr holen
                move.l  $56(a0),a0              * UserPort holen
                move.l  a0,a5                   * und retten
                move.b  $f(a0),d1               * SigBit holen
                moveq   #0,d0                   * und in
                bset    d1,d0                   * Bitmaske wandeln
                CALLEXEC Wait                   * warten

                move.l  a5,a0                   * UserPort holen
                CALLEXEC GetMsg                 * Nachricht holen
                move.l  d0,a1                   * Message nach A1
                move.l  $14(a1),d4              * Art der Message holen
                CALLEXEC ReplyMsg               * und beantworten

                cmpi.l  #$200,d4                * Schließsymbol betätigt?
                beq     End                     * ja!

                bra     MessageLoop             * Schleife

*
* Ende - alles schließen
*

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

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

Fault:          move.l  IntuiBase,a1
                CALLEXEC CloseLibrary

                move.l  GfxBase,a1
                CALLEXEC CloseLibrary

                moveq.l #0,d0
                rts

*
* Dies ist die Routine, die den Effekt bewirkt
* (nach MIKE BERRO; von der RPD 30; etwas überarbeitet) ...
* übergeben werden muß ein Zeiger auf die zu bearbeitende
* Bitplane in A0.
*

FlipIt:         move.l  a0,a1                   * Zeiger nach a1
                add.l   #20480,a1               * Offset addieren - der
                                                * Zeiger wird an die unterste
                                                * Ecke der betreffenden
                                                * Plane gesetzt - in diesem
                                                * Fall muß man 80*256 Bytes
                                                * (=20480) addieren.

                move.l  #128,d0                 * Anzahl der zu flippenden
                                                * Zeilen durch 2
Flip1:          move.l  #20,d1                  * Anzahl der Longwords
                                                * pro Zeile

Flip2:          move.l  (a0),d2                 * nächste Longword (vom An-
                                                * fang her gesehen) holen
                bsr     SideFlip                * seitlich flippen
                move.l  -(a1),d2                * nächste Longword (vom Ende
                                                * her gesehen) holen
                move.l  d5,(a1)                 * geflipptes Longword
                                                * speichern
                bsr     SideFlip                * nochmal flippen
                move.l  d5,(a0)+                * und wieder speichern
                subq.l  #1,d1                   * Longwordzähler - 1
                bne.s   Flip2                   * Zeile weiterflippen
                subq.l  #1,d0                   * Zeilenzähler - 1
                bne.s   Flip1                   * Plane weiterflippen
                rts                             * und zurück

*
* Diese Routine flippt das in D2 übergebene Longword.
* Das geflippte Longword wird in D5 zurückgegeben.
*

SideFlip:       moveq.l #0,d5                   * D5 (Ziel) löschen
                moveq.l #31,d3                  * Anzahl Bits/Longword
                moveq.l #0,d4                   * Zähler löschen
SideFlip2:      btst.l  d3,d2                   * Bit im Quell-Longword
                                                * testen
                beq.s   SideFlip3               * scheint gesetzt zu sein!
                bset.l  d4,d5                   * entsprechende Bit im
                                                * Ziel-Longword setzen
SideFlip3:      addq.l  #1,d4                   * Bitzähler (Ziel) erhöhen
                subq.l  #1,d3                   * Bitzähler (Quelle) - 1
                bpl.s   SideFlip2               * bis das Longword fertig
                                                * geflippt ist ...
                rts                             * zurück

*
* Datenteil
*

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

 even
WindowDefs:     dc.w    0,11,100,11,1
                dc.l    $200,$E,0,0,Titel,0,0,0,0
                dc.w    1

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

Titel:          dc.b    "?!?",0
 even

GfxBase:        dc.l    0
IntuiBase:      dc.l    0
WindowPtr:      dc.l    0
ScreenPtr:      dc.l    0
RastPort:       dc.l    0

srcBitMap:      dc.l    0
dstBitMap:      dc.l    0

                END

