  _________________________________________________________________________
/#########################################################################\
|#####...####..######..######......####...####..#####..##......##......###|
|####.....###..######..########..#####.....###...####..##..######..#######|
|###..###..##..######..########..####..###..##....###..##..######..#######|
|###..###..##..######..########..####..###..##..#...#..##..######......###|
|###.......##..######..########..####.......##..##.....##..######..#######|
|###..###..##..######..########..####..###..##..###....##..######..#######|
|###..###..##...#####...#######..####..###..##..####...##..######..#######|
|###..###..##......##......##......##..###..##..#####..##......##......###|
|#########################################################################|
|####################################################################{RB}#|
|=========================================================================|
|									  |
|		           ----> PRESENTS <----				  |
|									  |
|			THE ABACUS SERIES - VOLUME 2		          |
|									  |
|            AMIGA GRAPHICS INSIDE AND OUT - THE COMPLETE BOOK            |
|									  |
| Typed / Scanned / Edited By : RAZOR BLADE.			          |
| Additional Typing by        : GLITCH ( + 8 pages by Asterix ! ).	  |
| Menu Coded by 	      : RAISTLIN				  |
| Original Supplied by	      : VIPER					  |
|									  |
|-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-|
| 		CALL THE ALLIANCE WORLD HQ -> THE PLACE TO BE             |
|       UNKNOWN PLEASURES --> +44 (0) 823 322 891 --> SYSOP: BARBARIAN    |
|_________________________________________________________________________|



-----------------------------------------------------------------------------
        
        
4.5 COPPER PROGRAMMING.
        
The Copper has just demonstrated how powerful it is. We are going to take
advantage of that power with our next program, which will use a technique
known as double buffering.
        
                --------------------------------------------
        
4.5.1 DOUBLE BUFFERING FOR LIGHTNING FAST GRAPHICS.
        
The drawing speed of the Amiga does not affect the Copper because the
Copper operates independantly at full speed. Because of this you can
amaze the users of your programs with lightning fast graphics created 
with double buffering. To create this effect, show the user a display
on which nothing is happening. While the user stares at this boring 
display, build your graphics in a second, invisible display. When your
graphics are complete, switch on the second display and your graphics 
will instantly appear on the screen.        
        
We will now explain how this works. The pointer to the Copper lists of 
the old display are read from View and stored. The pointer in View is
erased. Now a new bit-map with new bit-planes is prepared for the second
display. MakeVPort and MrgCop are used to generate the new copper lists, 
which are then stored. To switch from one display to the other we just 
write the new pointer to the View structure and use LoadView to activate
it.        
        
Again we have designed a small program package. If consists of the 
following SUB programs:
        
        MakeDoubleBuffer
        DoubleBufferOn
        DoubleBufferOff
        AbortDoubleBuffer
        transmit
        
        
                                PAGE 175
        
-----------------------------------------------------------------------------
        
        
        '################################################
        '#
        '# Section : 4.5.1
        '# Program : Double Buffered Display.
        '# Author  : tob
        '# Version : 1.0
        '#
        '################################################
        '
        ' This program creates a second screen that works
        ' as a backup buffer for the normal screen.
        '
        
        PRINT "Searching for .BMAP file ............"
        
        'GRAPHICS-library
        DECLARE FUNCTION BltBitMap& LIBRARY
        DECLARE FUNCTION AllocRaster& LIBRARY
        'FreeRaster()
        'MakeVPort()
        'MrgCop()
        'LoadView()
        'FreeCprList()
        
        'EXEC-library
        DECLARE FUNCTION AllocMem& LIBRARY
        'FreeMem()
        'CopyMem()
        
        'INTUITION-library
        DECLARE FUNCTION ViewPortAddress& LIBRARY
        DECLARE FUNCTION ViewAddress& LIBRARY
        
        LIBRARY "intuition.library"
        LIBRARY "graphics.library"
        LIBRARY "exec.library"
        
        init:    CLS
            PRINT "WITHOUT DOUBLE BUFFERING!"
            FOR t = 1 TO 20
                PRINT STRING$(80,"+")
            NEXT t
            FOR t = 1 TO 20
                x%  = RND(1) * 600
                y%  = RND(1) * 150
                r%  = RND(1) * 100
                CIRCLE (x%,y%),r%
            NEXT t
            CLS
            PRINT "AND NOW WITH DOUBLE BUFFERING!!!"
            MakeDoubleBuffer
            DoubleBufferOn
            FOR t = 1 TO 20
                PRINT STRING$(80,"+")
            NEXT t
            transmit
            LOCATE 1,1
        
        
                                   PAGE 176
        
-----------------------------------------------------------------------------
        
        
            FOR t = 1 TO 20
                x% = RND(1) * 600
                y% = RND(1) * 150
                r% = RND(1) * 100
                CIRCLE (x%,y%),r%
            NEXT t
            transmit
            LOCATE 5,10
            LINE (38,29)-(442,67),3,b
            PRINT "Even this works!"
            PRINT "Double Buffering = Backup Display"
            PRInt "These are two separate screen that"
            PRINT "are switched back and forth"
            FOR loop% = 1 TO 15
                DoubleBufferOn
                FOR T = 1 TO 1000: NEXT t
                DoubleBufferOff
                FOR T = 1 TO 1000: NEXT t
            NEXT loop%
            PRINT
            PRINT "PRESS THE LEFT MOUSEBUTTON!"
            SLEEP:SLEEP
            AbortDoubleBuffer
            LIBRARY CLOSE
            END
        
        
    SUB MakeDoubleBuffer STATIC
        '* Create second display.
        SHARED TargetBitmap&, rasInfo&, SourceBitMap&, view&
        SHARED bufferx%, buffery%, vp&
        SHARED home1&, home2&, guest1&, guest2&
        view&           = ViewAddress&
        vp&             = ViewPortAddress&(WINDOW(7))
        rasiInfo&       = PEEKL(vp&+36)
        SourceBitMap&   = PEEKL(rasInfo&+4)
        opt&            = 2^0 + 2^1 + 2^16
        TargetBitmap&   = AllocMem&(40,opt&)
        
        '* Copy Bitmaps
        IF TargetBitmap& = 0 THEN ERROR 7
        '* NOTE: FOR KICKSTART VERSION 1.2 AND ABOVE.
        '* FOR 1.0 AND 1.1 USE LINES BELOW.
        '*
        '*
        '* For loop& = 0 TO 40 STEP 4
        '*   POKEL TargetBitmap&+loop&,PEEKL(SourceBitMap&+loop&)
        '* NEXT loop&
        '
        
        CALL CopyMem(SourceBitMap&,TargetBitmap&,40)
        
        ' Get Planes.
        bufferx%     = PEEKW(SourceBitMap&)*8
        buffery%     = PEEKW(SourceBitMap&+2)
        
        
                                PAGE 177
        
-----------------------------------------------------------------------------
        
        
        depth%      = PEEK(SourceBitMap&+5)
        FOR loop% = 0 TO depth% - 1
            plane&(loop%) = AllocRaster&(bufferx%,buffery%)
            IF plane&(loop%) = 0 THEN ERROR 7
            POKEL TargetBitmap&+8+loop%*4,plane&(loop%)
        NEXT loop%
        
        'Copy active display to buffer.
        plc% = BltBitMap&(SourceBitMap&,0,0,TargetBitmap&,0,0,bufferx%
    buffery%,200,255,0)
        IF plc%<>depth% THEN ERROR 17
        
        ' Store original Copper List
        home1& = PEEKL(view&+4)
        home2& = PEEKL(view&+8)
        
        'Generate Second Copper List
        POKEL view&+4,0
        POKEL view&+8,0
        POKEL rasInfo&+4,TargetBitmap&
        CALL MakeVPort(view&,vp&)
        CALL MrgCop(view&)
        CALL LoadView(view&)
        guest1& = PEEKL(view&+4)
        guest2& = PEEKL(view&+8)
        
        'Reset
        POKEL rasInfo&+4,SourceBitMap&
        POKEL view&+4,home1&
        POKEL view&+8,home2&
        CALL LoadView(view&)
    END SUB
        
        
    SUB DoubleBufferOn STATIC
        '* Activate new copper list.
        SHARED view&, guest1&, guest2&
        SHARED rasInfo&, TargetBitmap&
        POKEL view&+4,guest1&
        POKEL view&+8,guest2&
        CALL LoadView(view&)
    END SUB
        
    SUB DoubleBufferOff STATIC
        '* ACtivate old Copper List
        SHARED view&, home1&, home2&
        SHARED rasInfo&, SourceBitMap&
        POKEL view&+4,home1&
        POKEL view&+8,home2&
        CALL LoadView(view&)
    END SUB
        
    SUB transmit STATIC 
        'Copy old display to the new buffer.
        SHARED SourceBitMap&,TargetBitmap&,bufferx%,buffery%
        plc% = BltBitMap&(SourceBitMap&,0,0,TargetBitmap&,0,0,bufferx%,
    buffery%,200,255,0)
    END SUB
        
        
                                PAGE 178
        
-----------------------------------------------------------------------------
        
        
    SUB AbortDoubleBuffer STATIC
        SHARED rasInfo&, view&, TargetBitmap&
        SHARED vp&, bufferx%, buffery%
        SHARED home1%, home2%, guest1%, guest2%
        
        '* Restore Old Display and VPort copperlists.
        POKEL view&+4,home1&
        POKEL view&+8,home2&
        CALL MakeVPort(view&,vp&)
        CALL MrgCop(view&)
        CALL LoadView(view&)
        
        '* Delete new VPort Copper List Set
        CALL FreeCprList(guest1&)
        
        '* Delete Second Copper list set.
        IF guest2&<>0 THEN CALL FreeCprList(guest2&)
        add& = TargetBitmap&+8
        pl& = PEEKL(add&)
    
        '* Delete BitPlanes and BitMap
        WHILE pl&<>0
            CALL FreeRaster(pl&,bufferx%,buffery%)
            add& = add&+4
            pl&  = PEEKL(add&)
        WEND
        CALL FreeMem(TargetBitmap&,40)
    END SUB
        
        
DESCRIPTION: 
 
You switch the double buffer system on with the command:
 
        MakeDoubleBuffer
 
The double buffer is used to create the invisible display. This command
can only be used once. When you are ready to start, execute:
        
        DoubleBufferOn
 
This command activates the hidden display. Your old display, where you are
drawing, becomes invisible. Now you can take your time to create you
graphics, no drawing can be seen on the screen.
        
As soon as your graphic is complete you only have to call:
        
        transmit
        
        
        
                                PAGE 179
        
-----------------------------------------------------------------------------
        
        
to display the contents of the hidden display (in other words, to send your
graphic to the visible screen). You can use the transmit command as often
as desired.
        
When you want to quickly switch to an unbuffered display simply call:
        
        DoubleBufferOff
        
All graphic and print commands will, from this point on, appear immediately
on the screen. With DoubleBufferOn, you can activate the buffered system
again.        
        
Should you desire to leave the system entirly because your program is 
finished or you are tired of double buffer drawing, then use:
        
        AbortDoubleBuffer
        
All memory areas used for the buffer displays are returned to the system.
        
                --------------------------------------------
        
4.5.2  PROGRAMMING THE COPPER YOURSELF.
        
So far we have let the Amiga create the copper lists for us, from the data
we provided. Another possibility is to program the copper ourselves.
        
Before you do this, you need to understand the Copper functions. The copper
works very closely with the electronic beams of the display. These 
electronic beams scan from the upper left hand corner to the lower right
hand corner of the screen sixty (50 uk) times a second.        
        
The copper is capable of waiting for this electronic beam to reach a 
specific position. This is handled by the WAIT instruction of the 
processor. The instruction requires a Y and X coordinate and tells the 
Copper to wait until the electronic beam has reached this coordinate.
Until this occurs, the Copper will not process any more instructions.
        
The MOVE instruction allows the copper to directly address hardware 
registers in the special purpose chips (the hardware registers are detailed
in appendix C). The MOVE instruction requires an offset for the hardware
register and a value to store in the register.        
        
The third and last instruction for the Copper is named SKIP. This 
instruction is used to actually skip past items in the copper list.
        
        
                                PAGE 180
        
-----------------------------------------------------------------------------
        
        
Writing a Copper list for an entire display would be a very tedious job.
Fortunately, this isn't necessary because most of the work can be 
accomplished easily by using MakeVPort. However, if you want to add your
own Copper instructions to the Copper list for the displays, there is 
another method. In the structure of every ViewPort you will find a pointer
for a user copper list. When you want to integrate your own instructions
with a display, create a stand alone Copper list with the desired commands.
Then store the starting address of your list to the User Copper list 
pointer. Now you can continue as usual. MakeVPort links the user list to
the display list of the viewport, MrgCop links this list to the entire
list in View and LoadView activates the manipulated copper lists.
        
We will now show you how to create your own Copper list. The next program
contains 4 SUB programs for this purpose.
        
        InitCop
        ActiCop
        WaitC
        MoveC
        
First you need to create a data structure name UCopList. This structure
requires 12 bytes of memory which is reserved with InitCop.
        
We can program the user list with the commands MoveC and WaitC (skip is
not necessary for our application).
   
The call to the wait command looks like this:
        
        WaitC y%,x%
        
The Y coordinate, which the Copper waits for, must be first. WaitC 
requires that this coordinate is first because it is easier to combine
the copper lists using MrgCop if they all have the same order.
        
MoveC can write any desired 16 bit value to a hardware register. In this
chapter we use only a few of the many available registers. The complete 
register list is located in Appendix C. Here is the call :
        
        MoveC register%, value%
        
        register%     : Offset of the desired hardware register.
        value%        : 16 bit value.
        
Here is a selection of the most important hardware registers we are 
going to use:
        
        
                                PAGE 181
        
-----------------------------------------------------------------------------
        
        
        Register    Meaning
        ---------   ------------------------------------------------
           384      Colour Register 0 (Background colour)
           386      Colour Register 1 (Drawing Colour)
           388      Colour Register 2
          (...)
           444      Colour Register 30
           446      Colour Register 30
        -------------------------------------------------------------
        
Now we can add to our user Copper list. After calling InitCop you can 
call as many MoveC's and WaitC's as you like. However, you must make
sure that your WaitC's correspond with the screen coordinates you are 
calling. The top left hand corner of the display is at (0,0). This is
where the electronic beam starts. Your WaitC coordinates must be in 
ascending X and Y coordinate sequence.
        
When your user Copper list is finished, it is linked to the existing display
with ActiCop. Your assigments will then be executed by the copper.
        
In our example program, we open our new screen. In order to return the
memory used by our copper instructions (including those in our reserved
user list), we simply close the Intuition screen. Intuition automatically
takes care of this. Do not attempt to create user instructions in the 
Workbench screen because when the instructions are executed, there will be
no way to restore the normal display and release the assigned memory.
        
The following program is an example of Copper programming basics.
        
        '##############################################
        '#
        '# Section: 4.5.2
        '# Program: Copper Raster Interrupt.
        '# Date   : 12/15/86
        '# Author : tob
        '# Version: 1.0
        '#
        '###############################################
        
        ' Demonstrates programming the Amiga graphic
        ' co-processor (copper) from AmigaBASIC
        
        PRINT "Searching for .BMAP file ..........."
        
        'INTUITION-library
        DECLARE FUNCTION ViewAddress& LIBRARY
        DECLARE FUNCTION ViewPortAddress& LIBRARY
        
        
                                PAGE 182
        
-----------------------------------------------------------------------------
        
        
        'RethinkDisplay()
        
        'EXEC-library
        DECLARE FUNCTION AllocMem& LIBRARY
        'FreeMem()
        
        'GRAPHICS-library
        'CWait()
        'CMove()
        'CBump()
        
        LIBRARY "intuition.library"
        LIBRARY "graphics.library"
        LIBRARY "exec.library"
        
    pre: CLS
        SCREEN 1,640,200,2,2
        WINDOW 2,"COPPER!",(0,0)-(630,186),16,1
        PRINT "Raster Interrupt through Copper programming:A Split Screen!"
        
    init:
        kolorregister%    = 384
        red%              = 15,'0...15
        green%            = 4 ,   '0 to 15'
        blue%             = 4 ,   '0 .... 15'
        kolorvalue%       = red%*2^8+green%*2^4+blue%
        yCoordinate%      = 100
        xCoordinate%      = 20
        
    main:
        InitCop
        WaitC yCoordinate%, xCoordinate%
        moveC kolorregister%, kolorvalue%
        ActiCop
        
        PRINT " Press a Key ! "
        WHILE INKEY$ = "":WEND
        
        WINDOW CLOSE 2
        SCREEN CLOSE 1
        
    endprog:
        LIBRARY CLOSE
        END
        
    SUB InitCop STATIC
        SHARED UCopList&
        opt&         = 2^0+2^1+2^16
        UCopList&    = AllocMem&(12,opt&)
        IF UCopList& = 0 THEN ERROR 7
    END SUB
        
    SUB ActiCop STATIC
        SHARED UCopList&
        waitC 10000,256
        
        
                                PAGE 183
        
-----------------------------------------------------------------------------
        
        
        viewport& = ViewPortAddress&(WINDOW(7))
        POKEL viewport&+20,UCopList&
        CALL RethinkDisplay
    END SUB
        
    SUB waitC(y%,x%) STATIC
        SHARED UCopList&
        CALL CWait(UCopList&,y%,x%)
        CALL CBump(UCopList&)
    END SUB
        
    SUB moveC(reg%,value%) STATIC
        SHARED UCopList&
        CALL CMove(UCopList&,reg%,value%)
        CALL CBump(UCopList&)
    END SUB
        
        
SUB program descriptions:
        
InitCop :
        The exec function AllocMem assigns a 12 byte memory area for the
        UCopList data structure.
        
WaitC   :
        A wait instruction is placed in the user list. The graphic library
        command CWait, also called CBump(), raises the internal pointer
        for the user list.
        
MoveC   :
        Calls the function CMove, from the graphic library, which places
        a move instruction in the user list. CBump() raises the user list
        pointer again.
        
ActiCop :
        a last WaitC is placed in the user list. This wait is for a screen
        position that the electron beam will never reach. This assignment
        closes the list and equals the macro CEND.
        
The address of our user list is written to the appropriate pointer in 
ViewPort for the desired screen. The Intuition function RethinkDisplay
generates the new copper list for View and sends it into the copper. The
new display then appears.        
        
At the end, the screen is closed and the copper list is removed from the
main copper list in View. All reserved memory is returned to the system.
        
        
                                PAGE 184
        
-----------------------------------------------------------------------------
        
        
4.5.3 PROGRAMMING 400 SIMULTANEOUS COLOURS.
        
We now know the principle of Copper programming. The next program is a 
small demonstration of this powerful technique. We are going to change
the background colour for each screen row by using WaitC. At the same
time we will also be changing the drawing colour for each row. With 200
screen rows per display, we finish with 400 colours on the screen at the
same time. Colours two and three remain normal.
        
NOTE : Do not use more than 1600 Copper instructions in one list.
        
        '##############################################
        '#
        '# Section: 4.5.3
        '# Program: Copper Raster Interrupt II
        '# Date   : 12/15/86
        '# Author : tob
        '# Version: 1.0
        '#
        '###############################################
        
        ' Copper programmning can create 400 different colours in the
        ' background and foreground instead of the usual 4 colors
         ' with 2 bit-planes.
        
        PRINT "Searching for .BMAP file ..........."
        
        'INTUITION-library
        DECLARE FUNCTION ViewAddress& LIBRARY
        DECLARE FUNCTION ViewPortAddress& LIBRARY
        'RethinkDisplay()
        
        'EXEC-library
        DECLARE FUNCTION AllocMem& LIBRARY
        'FreeMem()
        
        'GRAPHICS-library
        'CWait()
        'CMove()
        'CBump()
        
        LIBRARY "intuition.library"
        LIBRARY "graphics.library"
        LIBRARY "exec.library"
        
        
                                PAGE 185
        
-----------------------------------------------------------------------------
    pre: CLS
        SCREEN 1,640,200,2,2
        WINDOW 2,"COPPER!",(0,0)-(630,186),16,1
        PRINT "Direct copper programming makes it possible."
        PRINT "200 background Colours!"
        PRINT "Patience Please ... Calculating Instruction lists.."
        
    init:
        kolorregister1%    = 384
        kolorregister2%    = 386
        xCoordinate%      = 20
        maxY%             = 200
        
    main:
        InitCop
        FOR loop% = 1 TO maxY%
            waitC loop%,xCoordinate%
            moveC kolorregister1%,loop%
            moveC kolorregister2%,4096-loop%
        NEXT loop%
        ActiCop
        
        ' Display text for this effect
        LOCATE 5,1
        PRINT  "The background colour shows 200 individual"
        PRINT "Colors! The text colors are also not plain"
        PRINT "anymore: 200 yellows, one per raster."
        PRINT "line. Here a useful program could"
        PRINT "take over the job instead of "
        PRINT "this useless program loop!...."
        LOCATE 15,1
        PRINT "Please press a key when you"
        PRINT "Have finished reading."
        WHILE INKEY$="": WEND
        
        LOCATE 11,1
        PRINT "Thats not going to happen this time!"
        
        FOR t=1 TO 2000: NEXT t
        CLS
        PRINT "Graphic Demo Coming up!"
        
        LINE (0,100)-(630,190),2,bf
        FOR loop% = 0 TO 630 STEP 30
            LINE (loop%*1.5,190)-(loop%,100),1
        NEXT loop%
        FOR loop% = 100 TO 190 STEP 20
            LINE (0,loop%)-(630,loop%),1
        NEXT loop%
        
        CIRCLE (300,80),120,3
        
        
                                PAGE 186
        
-----------------------------------------------------------------------------
        
        
            PAINT (300,80),3,3
            
            CIRCLE (300,80),100,1
            PAINT (300,80),1,1
        
            CIRCLE (300,146),180,3,,,1/15
            PAINT (300,146),1,3

            LOCATE 1,1
            PRINT "Press a Key!"+SPACE$(40)
        WHILE INKEY$ = "":WEND
        
        WINDOW CLOSE 2
        SCREEN CLOSE 1
        
    ende:
        LIBRARY CLOSE
        END
        
    SUB InitCop STATIC
        SHARED UCopList&
        opt&         = 2^0+2^1+2^16
        UCopList&    = AllocMem&(12,opt&)
        IF UCopList& = 0 THEN ERROR 7
    END SUB
        
    SUB ActiCop STATIC
        SHARED UCopList&
        waitC 10000,256
        viewport& = ViewPortAddress&(WINDOW(7))
        POKEL viewport&+20,UCopList&
        CALL RethinkDisplay
    END SUB
        
    SUB waitC(y%,x%) STATIC
        SHARED UCopList&
        CALL CWait(UCopList&,y%,x%)
        CALL CBump(UCopList&)
    END SUB
        
    SUB moveC(reg%,value%) STATIC
        SHARED UCopList&
        CALL CMove(UCopList&,reg%,value%)
        CALL CBump(UCopList&)
    END SUB
        
        
The text displayed by the program makes the details of the changed display
clearer and more impressive. A simple graphic is created but it has a
fascinatin appearance because of the Copper programming. This graphic is
formed from more than 400 colors with only two bit-planes. After pressing
a key the normal screen appears.
        
        
                                PAGE 187
        
-----------------------------------------------------------------------------