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


             CHAPTER 3 - INTUITION - THE USER INTERFACE

We begin our trip through the graphic world of the Amiga with a system
component named INTUITION, which refers to a library within the operating
system (see chapter 2). Intuition is directly related to the graphic
libraries' capabilities and is responsible for windows, screens, reqesters,
alerts (Guru Meditations, for example) and much more.

                ----------------------------------------------

3.1  INTUITION WINDOWS.

Unless you are running another operating system. Intuition will mamage all
windows. This also applies to the standard windows of the BASIC
interpreter, LIST and BASIC. A data block used for intuition windows
consists of 124 bytes and contains all data specific to a window. The
starting address of the BASIC output window data is always stored in the
variable WINDOW(7). You can obtainn the start address like this:
        
        windo&=WINDOW(8)

The data block is stored in the following format:

        Data structure  Window/Intuition/124 bytes.

OFFSET  TYPE    DEFINITION
------- ------- ------------------------------------------------
+000    Long    Pointer to next window.
+004    Word    X coordinate of upper left corner.
+006    Word    Y coordinate of upper edge.
+008    Word    Width of window.
+010    Word    Height of Window.
+012    Word    Y coordinate of mouse, rel. to window.
+014    Word    X coordinate of mouse, rel. to window.
+016    Word    Minimum width of window.
+018    Word    Minimum height of window.
+020    Word    Maximum width of window.
+022    Word    Maximim height of window.
+024    Long    Window modes
                Bit 0:  1=Sizing Gadget Available.
                Bit 1:  1=Dragbar gadget available.
                Bit 2:  1=Fore/Background gadgets available.

                                PAGE 93

----------------------------------------------------------------------------

WINDOW DATA STRUCTURE (CONT'D) ....

OFFSET  TYPE    DEFINITION              
------- ------- ----------------------------------------------------

                Bit 3:  1=Close gadget available.
                Bit 4:  1=Sizing gadget is right.
                Bit 5:  1=Sizing gadget is bottom.
                Bit 6:  1=Simple refresh.
                Bit 7:  1=Superbitmap.
                Bit 8:  1=Backdrop Window.
                Bit 9:  1=Report Mouse.
                Bit 10: 1=GimmeZeroZero.
                Bit 11: 1=Borderless.
                Bit 12: 1=Activate.
                Bit 13: 1=This window is active.
                Bit 14: 1=This window is in request mode.
                Bit 15: 1=Active window with active menu.

+028    Long    Pointer to menu header.
+032    Long    Pointer to title text for this window.
+036    Long    Pointer to first active requester.
+040    Long    Pointer to double click requester.
+044    Word    Number of the window block request.
+046    Long    Pointer to the screen, of this window.
+050    Long    Pointer to the RastPort of this window.
+054    Byte    Left Border.
+055    Byte    Top Border.
+056    Byte    Right Border.
+057    Byte    Bottom Border.
+058    Long    Pointer to border RastPort.
+062    Long    Pointer to the first gadget.
+066    Long    Pointer to previous window (father).
+070    Long    Pointer to next window (child).
+074    Long    Pointer to sprite data for pointer.
+078    Byte    Height of sprite pointer.
+079    Byte    Width of sprite pointer.
+080    Byte    X offset of pointer.
+081    Byte    Y offset of pointer.
+082    Long    IDCMP flags.
+086    Long    User message port.
+090    Long    Window message port.
+094    Long    IntuiMessage message key.
+098    Byte    Detailpen.
+099    Byte    Blockpen.
+100    Long    Pointer to menu checkmarks.
+104    Long    Pointer to screen title text.
+108    Word    GZZ-MouseX
+110    Word    GZZ-MouseY

                                PAGE 94

----------------------------------------------------------------------------

Offset  Type    Definition.
------- ------- --------------------------------------------
+112    Word    GZZ-Width.
+114    Word    GZZ-Height.
+116    Long    Pointer to external data.
+120    Long    Pointer to user data.

Every window has a data block like the one in the above format. To access
the different data fields in the data block, first select the desired
output window using the WINDOW OUTPUT statement. After this command, the
data block address will be in the variable WINDOW(7). You add the offset
value of the desired field to this address. There are 3 types of data
fields, byte, word and long. A byte field which consists of exactly one
byte is read with PEEK and is changed with POKE. A word is two bytes wide
and is read and written with PEEKW and POKEW. A long field is four bytes
wide and is read and written with PEEKL and POKEL. We will present several
examples of each.

                                PAGE 95

----------------------------------------------------------------------------

3.2 THE WINDOW DATA STRUCTURE.

Now you know the method used to access the data structure of your output
window. The following is a detailed explanation of each data field to
explain what you can do with them.


OFFSET 0 : POINTER TO NEXT WINDOW.

Intuition manages all windows in a type of chain. This offset contains the
starting address of the next window data block. You can find the data block
of the next and previous window from your current data block. This
particular pointer is not important because the chain pointers come later
at offsets 66 and 70.


OFFSETS 4 AND 6 : POSITION OF WINDOW IN UPPER LEFT HAND CORNER.

These two word fields contain the X and Y coordinates of the upper left
hand corner of their window. These coordinates are relative to the
upperleft hand corner of the screen that contains the window. The lines
below provide you with the coordinates:

        windo&=WINDOW(7)
        x%=PEEKW(windo&+4)
        y%=PEEKW(windo&+6)
        PRINT "Upper left window corner is at "
        PRINT "Coordinates (";x%;",";y%;")"
        END

Because the BASIC output window sits in the upper leeft hand corner of the
Workbench screen you would receive coordinates of (0,0). The moment you
drag this window to a different position, the coordinates are changed.
Later we will use these values to access various intuition routines.


OFFSETS 8 AND 10 : WINDOW DIMENSIONS.

Since we can change the window size with the sizing gadget in the lower
right hand corner of the window, the program doesn't always know the
current window size. The small program below provides the current window
size:

                                PAGE 96

-----------------------------------------------------------------------------

        windo&=WINDOW(7)
        windoWidth%=PEEKW(windo&+8)
        windoHeight%=PEEKW(windo&+10)
        PRINT "At the moment your window is ";windoWidth%
        PRINT "pixels wide and ";windoHeight%;" Pixels high."
        END

OFFSETS 12 AND 14 : MOUSE COORDINATES.

These two word fields contain the actual mouse coordinates relative to the
upper left hand corner of the window. The first field contains the Y
coordinate and the second field the X coordinate.

Using these two values you can easily create a small drawing program. The
following lines demonstrate this:

        '##################################
        '#
        '# Section:  3.2
        '# Program:  Mouse Draw I
        '# Date   :  04/05/87
        '# Author :  tob
        '# Version:  1.0
        '#
        '###################################

        init:   windo&=WINDOW(7)
                'Address of window structure
        loop:   'wait for key press
                PRINT "Press any key to exit"
                WHILE INKEY$ = ""
                   mouse.y% = PEEKW(windo&+12)
                   mouse.x% = PEEKW(windo&+14)
                   PSET(mouse.x%,mouse.y%)
                WEND

Two things are immediately visible. First the line drawn starts several
pixels below the mouse pointer and second, only a dotted line is being
drawn. The mouse position fields contain the mouse coordinates relative to
the upper left hand corner of the window. However, PSET draws in a plane
that uses an offset relative to the upper left hand corner of the drawing
plane and not the window (as long as the window is a GimmeZeroZero window;
we will have more on this later). To correct the window/plane problem,
subtract 11 from the Y value and 4 from the X value. The second problem is
caused by BASIC's slow speed. The mouse moves faster than BASIC can draw.
Test this by moving the mouse very slowly across the screen. You should see
a complete line from one point to another. The next program contains both
changes :

                                PAGE 97

----------------------------------------------------------------------------

        '###################################
        '#
        '# Section: 3.2B
        '# Program: Mouse Draw II
        '# Date   : 04/05/87
        '# Author : tob
        '# Version: 1.0
        '#
        '###################################
        init:   windo&=WINDOW(7)
                '* Address of Window Data Structure.
                mouse.y% = PEEKW(windo&+12)-11
                mouse.x% = PEEKW(windo&+14)-4
        loop:   '* Wait for keypress.
                PRINT "Press any key to Exit"
                WHILE INKEY$=""
                    oldmouse.y% = mouse.y%
                    oldmouse.x% = mouse.x%
                    mouse.y% = PEEKW(windo&+12)-11
                    mouse.x% = PEEKW(windo&+14)-4
                    LINE(oldmouse.x%,oldmouse.y%)-(mouse.x%,mouse.y%)
                WEND

When you speed around the screen with this program, you will discover that
individual "peaks" appear. This happens when the mouse coordinates are
calculated but the Y value has not changed.

     
OFFSET 16,18,20 AND 22: WINDOW LIMITS.

Some windows can be made larger and smaller using the mouse. Every window
has it's own maximum and minimum size. A window can be any size within
these limits in the window data structure.

        windo&=WINDOW(7)
        min.x%=PEEKW(windo&+16)
        min.y%=PEEKW(windo&+18)
        max.x%=PEEKW(windo&+20)
        max.y%=PEEKW(windo&+22)
        PRINT "Minimum Size: X=";min.x%;
        PRINT " Y=";min.y%
        PRINT "Maximum Size: X=";max.x%;
        PRINT " Y=";max.y%
        END

In this example we read the limit values. You can easily set your own
window limits by using POKEW to the required addresses:

        windo&=WINDOW(7)
        min.x%=5
        min.y%=7
        max.x%=640
        max.y%=200
        POKEW,windo&+16,min,x%
        POKEW,windo&+18,min.y%
        POKEW,windo&+20,max.x%
        POKEW,windo&+22,max.y%
        END

                                PAGE 98

-----------------------------------------------------------------------------

There are two things you must always be sure of:

1.) The minimum size has to be smaller than the maximum size.

2.) The maximum size cannot be smaller than the current window you are
    changing. (Dimensions are available fromm offsets 8 and 10).


OFFSET 24: WINDOW MODES.

Intuition has different window types and each window can have various
gadgets assigned to them :

        a.)     Sizing gadget.
        b.)     Dragbar.
        c.)     Fore/Background gadget.
        d.)     Close gadget.

You can also set the refresh mode for the window. This mode determines how
a window is restored once another window covers it. SIMPLE REFRESH leaves
the restoring up to you. Normally this means that if another window covers
your window, the covered part is lost. SMART REFRESH uses Intuition to save
the covered portion of the window and restores it after the window is
uncovered. This method requires more time and can use much more memory,
depending on how many windows are active. The SUPERBIT method keeps a copy
of the entire window contents in RAM. Although this expends a large amount
of memory, it allows a window to show a piece of a much larger graphic.

Besides the basic attributes of a window, there are also special windows. A
BACKDROP window is always behind all other windows and cannot be put in
front. For example, it works as the background or graphic plane. The
visible workbench screen is nothing more than a backdrop window the covers
the screen. A GimmeZeroZero window has two parts, a border and a drawing
plane. This method allows easy drawing because it is impossible to
accidentally draw over the border. The BASIC window is an example of a
GimmeZeroZero window. The BORDERLESS window does not have a borderr frame.
An example of this type is the backdrop Workbench window because it does
not have a borderr frame and it merges with the background.

To access these modes use the bit pattern from the table in section 3.1

NOTE: Changes to this field only take effect after workbench refreshes the 
      window (for example, when you drag it to move it).

                                PAGE 99

------------------------------------------------------------------------------

OFFSET 28: THE MENU HEADER.

A special property of all intuition windows is their ability to have menus.
When you press the right mouse button the menus appear in the top window
bar.

This field contains the pointer to the intuition menu system for this
window.


OFFSET 32: TITLE TEXT FOR THE WINDOW.

Every window has it's own name. This offsett contains the starting address
for the title text. The following lines demonstrate an easy way to change
this:

        window.name$="Hello World"+CHR$(0)
        POKEL WINDOW(7)+32,SADD(window.name$)

As soon as you perform an action with the window, such as dragging (cuasing
intuition to refresh the window), the new menu name appears. Later we will
show you a method for changing a window name that will give you instant
results.

The CHR$(0) is a null byte added at the end of the text that tells
Intuition where the text ends.


OFFSET 36,40 AND 44: REQUESTER HANDLING.

Intuition uses this data field to remember how many (and what kind) of
requesters are blocked by this window. Basic programmers can ignore this
field for now.


OFFSET 46: POINTER TO SCREEN.

Windows with complete freedom of movement do not exist. Every window
appears in a screen. The Workbench screen is the first screen and the other
screens can be overlaid by using the SCREEN statement. This offset contains
the address of the Intuition screen data structure. In the same way that
each window has it's own data structure, each screen has its own data
structure. Screen data is arranged somewhat differently. We will discuss
that in more detail later.


OFFSET 50: POINTER TO RASTPORT OF WINDOW.

The RastPort is nothing more than another data structure. It could be
defined as an intersection. From the RastPort there are paths to windows,
screens and even the most simple graphic components like bit-maps and
layers. We will discuss all of these in detail later.

                                PAGE 100

----------------------------------------------------------------------------

OFFSET 54,55,56 AND 57: WINDOW BORDERS.

This 4 byte field contains the dimensions in pixels of the window border.
When we were working with the mouse coordinates (offset 12,14) we
subtracted the values 11 and 4. The same values are located here; they are
the height of the top border and the width of the left border.

You can calculate the drawing coordinates in a GimmeZeroZero window by
adding these values. This determines your relative position to the top left
hand corner of the window.

When working with other window types you have to be careful not to draw
over the window border. The following rules can help you avoid this:

a.) Your X coordinate must be greater than the window border and smaller
    than the width of the window (offset 8) minus the width of the right
    border.

b.) Follow the same rule for the Y coordinates.


OFFSET 58: THE RASTPORT BORDER.

All GimmeZeroZero windows control two independant drawing planes: the
window border and the window contents. This offset contains the address
pointer for the RastPort of a GimmeZeroZero window. The following program
uses the RastPort border and the Graphic function TEXT to display a status
line in the window header:

        '###############################
        '#
        '# section: 3.2C       
        '# Program: Status Line                                 
        '# Date   : 12/17/89                                    
        '# Author : tob                                 
        '# Version: 1.0
        '#
        '###############################

        ' This program creates a user status liine in a 
        ' GimmeZeroZero window. BorderRastPort is the
        ' length of x. x is independant of the actual window 
        ' size. Error checking prevents any Gadgets from 
        ' being disturbed.

        PRINT "Searching for .bmap file ...."


                                PAGE 101

-----------------------------------------------------------------------------

        'graphics.library
        'Text()
        'SetAPen()
        'SetDrMd()
        'Move()

        LIBRARY "graphics.library"

        main:   CLS
                Status "STATUS: Demo window. Please press a key!",60
                WHILE INKEY$=""
                WEND
                WHILE yn$<>"y"
                   Status "STATUS: Please enter your name!",60
                   CLS
                   LOCATE 1,1
                   LINE INPUT "--> ";n$
                   Status "Name: "+n$+". Correct (y/n) ? ",60
                   LOCATE 1,1
                   PRINT SPACE$(50)
                   LOCATE 1,1
                   LINE INPUT "--> ";yn$       
                WEND

        endprog: WINDOW 1,""            
                 LIBRARY CLOSE
                 END

        SUB Status(text$,t.width%) STATIC
                borderRast%     = PEEKL(WINDOW(7)+58)
                IF borderRast% = 0 THEN
                   BEEP
                   PRINT "This is not a GimmeZeroZero type window."
                   ERROR 255
                END IF

                windoWidth% = PEEKW(WINDOW(7)+8)
                maxchar%    = INT((windoWidth%-86)/8)
                TextLen%    = LEN(text$)
                IF t.width% = 0 THEN t.width% = TextLen%
                IF t.width% < maxChar% THEN maxChar%=t.width%
                IF TextLen% < t.width% THEN
                   text$=text$+SPACE$(t.width%-TextLen%)
                END IF
                CALL SetAPen(borderRast&,1)
                CALL Move(borderRast&,32,7)
                CALL text(borderRast&,SADD(text$),maxChar%)
                CALL SetDrMd(borderRast&,0)             
                CALL SetAPen(borderRast&,3)
                CALL Move(borderRast&,31,7)
                CALL text(borderRast,SADD(text$),maxchar%)
                CALL SetDrMd(borderRas&,1)
        END SUB

                                PAGE 102

----------------------------------------------------------------------------

OFFSET 62: FIRST GADGET.

Gadgets are small (or large) "switch elements" that you select with the
mouse. Among these are the on/off gadget and the sizing gadget. This offset
contains the address of the first gadget structure in a chain. BASIC users
can disregard this.


OFFSETS 66 AND 70: FATHER AND CHILD WINDOWS.

In our discussion of offset 0 we mentioned that Intuition manages all
windows in a data chain. Every window has it's own data structure block. In
each data structure there is a pointer to the previous (father) window and
to the next (child) window. The first window in a chain does not have a
father pointer (=0) and the last has no child pointer (=0).

These two fields are very important. Up until now it was possible for us to
determine the address of the output window by using the variable WINDOW(7).
Now we can use a window to determine where the data for any window is
located. The following program demonstrates this:

        '#######################################
        '#
        '# section: 3.2
        '# Program: Window Finder.
        '# Date   : 04/05/87
        '# Author : tob 
        '# Version: 1.0
        '#
        '########################################

        init:   windo& = WINDOW(7)

        '* Here we search for the end of the data chain.
        '* The 'parent' field of the first element is zero.

        WHILE found% = 0
            parent.windo& = PEEKL(windo&+66)
            IF parent.windo&= 0 THEN
                found% = 1
            ELSE
                windo& = parent.windo&
            END IF
        WEND
        found% = 0

        '* Windo& contains the address of the window
        '* Data block of the first window in the Data
        '* chain. Now we read through the chain, until 
        '* the 'child' field equals zero.

                                PAGE 103

----------------------------------------------------------------------------

        WHILE found% = 0
            counter% = counter%+1
            PRINT counter%;
            PRINT ". Window:"
            PRINT "Address of data structure: ";windo&

        '* now we provide the name of the window found at offset +32

            PRINT "Name of Window :            ";
            windo.name& = PEEKL(windo&+32)
            WHILE done% = 0
                gef$ = CHR$(PEEK(windo.name&))
                IF gef$ = CHR$(0) THEN
                    done% = 1
                    PRINT
                ELSE
                    PRINT gef%;
                    windo.name& = windo.name&+1
                END IF
            WEND
            PRINT
            done% = 0
            child.windo& = PEEKL(windo&+70)
            IF child.windo&= 0 THEN
                found% = 1
            ELSE
                windo& = child.windo&
            END IF
        WEND

Using these methods you have complete control of all the intuition managed
windows. You can write into other windows, change their names etc.. We will
present more programs further on that demonstrate this.


OFFSET 74,78,79,80 AND 81: THE SPRITE IMAGE.

It is possible for every window to have it's own mouse pointer. This offset
has the address pointer to the data for the new pointer's sprite image, the
height and width (maximum 16 pixels). Changing the value of this offset
doesn't accomplish anything. To set up your custom pointer, use SETPOINTER
via intuition. We show an example of how to do this at the end of the
chapter.


OFFSET 82,86,90 AND 94: IDCMP FLAGS AND MESSAGE PORTS.

IDCMP stands for INTUITION DIRECT COMMUNICATION MESSAGE PORT. Intuition
communicates through this channel with other tasks such as BASIC. This is
not important to you as a BASIC programmer since Intuition receives the
messages from BASIC and processes them automatically.

                                PAGE 104

------------------------------------------------------------------------------

OFFSET 98 AND 99: WINDOW COLOURS.

The window determines it's two colours from these two byte fields where the
colour registers are stored. You can change the window colours by poking
new values here. As before, intuition does not make the changes until a
window refresh is prompted (and window action such as dragging or sizing).


OFFSET 100: THE CHECK MARK IMAGE.

This offset contains the address of a small graphic image. You have
probably seen a menu option that sets a specific menu option on and marks
it with a check mark. The default value of this offset is zero for the
standard check mark image.


OFFSET 104: THE SCREEN TITLE.

A screen, that contains your window, can have different names. The screen
name depends on which window is selected (=active). Each window can give
the screen a different name. This offset holds the address pointer of the
name text.


OFFSET 108,110,112 AND 114: GIMMEZEROZERO PARAMETERS.

These fields are used only for a GimmeZeroZero window. GZZ-MouseX and
GZZ-MouseY contain relative values to offsets 12 and 14. They specify the
coordinates of the mouse pointer relative to the drawing plane, not to the
window. The zero coordinate is the upper left hand corner of the window
contents, not the upper left hand corner of the window border.

GZZ-width and GZZ-height contain values relative to offset fields 8 and 10.
The width and height of the window contents without the border are stored
here.


OFFSET 116 AND 120: OPTIONAL POINTERS.

These two pointers are used to link data blocks of different types with the
standard structure. The first pointer is reserved for Intuition, the second
is available for the user.

                                PAGE 105

-----------------------------------------------------------------------------

3.3 FUNCTIONS OF THE INTUITION LIBRARY.

Now that we understand how intuition manages window we can look at the
intuition library. The following routines of the intuition library are
responsible for windows:

        SetPointer()
        ClearPointer()
        MoveWindow()
        SizeWindow()
        WindowLimits()
        WindowToBack()
        WindowToFront()

                ------------------------------------------------

3.3.1  A PERSONALISED MOUSE POINTER.

The SetPointer function makes it possible for you to create your own
personalised mouse pointer for your window. As soon as your window is
active the normal pointer will be replaced by yours.


This function requires six parameters:

        SetPointer(window,image,height,width,xOff,yOff)
        Window: Address of window data structure of that window.
        image : Address of sprite image block.
        height: Height of the sprite.
        width : Width of sprite (max.16)
        xOff  : Marks the "hot spot"
        yOff  : Marks the "hot spot"

The following is an example program which shows how to change the mouse
pointer.

        '######################################
        '#
        '# section: 3.3.1
        '# Program: SetPointer-ClearPointer.
        '# Date   : 04/05/87
        '# Author : tob
        '# Version: 1.0
        '#
        '#######################################

                                PAGE 106

----------------------------------------------------------------------------

        ' The Amiga standard mouse pointer is
        ' replaced by a user-defined pointer.

        PRINT "Searching for .bmap file...."

        'INTUITION-Library
        'SetPointer()
        'ClearPointer()
        LIBRARY "intuition.library"

        init:   image$=""
                sprite.height% = 14
                sprite.width% = 16
                sprite.xOff% = -7
                sprite.yOff% = -6

        image:  '* REad sprite data image.
                RESTORE sprite.data
                FOR loop% = 0 TO 31
                    READ info&
                    hi% = INT(info&/256)
                    lo% = info& - (256*hi%)
                    image$ = image$+CHR$(hi%)+CHR$(lo%)
                NEXT loop

        setpoint:  '* Build new image.
                   CALL SetPointer(WINDOW(7),SADD(image$),sprite.height%,
                        sprite.width%,sprite.xOff%,sprite.yOff%)
        maindemo:  '* Demonstration of the new pointer.
                   CLS
                   PRINT "Any key to exit."
                   PRINT "Left Mouse button to draw."

                   '* Draw with pattern.
                   area.pat%(0) = &h1111
                   area.pat%(1) = &h2222
                   area.pat%(2) = &h4444
                   area.pat%(3) = &h8888
                   PATTERN , area.pat%
                   COLOR 2,3

                   WHILE INKEY$=""
                      state% = MOUSE(0)
                      IF state%<0 THEN
                        mouseOldX% = mouseX%
                        mouseOldY% = mouseY%
                        mouseX% = MOUSE(1)
                        mouseY% = MOUSE(2)
                        IF lplot% = 0 THEN
                            lplot% = 1


                                PAGE 107

----------------------------------------------------------------------------

                            PSET(mouseX%,mouseY%)
                        ELSE
                          LINE(mouseOldX%,mouseOldY%)-(mouseX%,mouseY%),1,bf
                        END IF
                      ELSE
                        lplot% = 0
                      END IF
                   WEND

                   COLOR 1,0

        endprog:   '* End demo and restore old pointer.
                   CALL ClearPointer(WINDOW(7))
                   LIBRARY CLOSE
                   END

        sprite.data:    DATA 0,0   
                        DATA 256,256
                        DATA 256,256
                        DATA 256,256
                        DATA 896,0
                        DATA 3168,0
                        DATA 12312,0
                        DATA 256,49414
                        DATA 256,49414
                        DATA 12312,0
                        DATA 3168,0
                        DATA 896,0
                        DATA 256,256
                        DATA 256,256
                        DATA 256,256
                        DATA 0,0

PROGRAM DESCRIPTION:

Our new mouse pointer should be 16 pixels wide and 14 pixels high. The "hot
spot", the sensitive pixel of the pointer, is seven pixels to the right and
six pixels below the upper left hand corner of the sprite.

The program routine IMAGE defines the shape of the new pointer. The data
for the shape is stored in the section called SPRITE.DATA. Each row of a
sprite can be a maximum of 16 pixels wide. The data block is composed of
two 16 bit values per sprite row. Since our sample sprite is 14 rows high
there has to be 14*2 = 28 data elements (plus two zeros at the beginning
and emd to switch of DMA). For every possible pixel of the sprite there are
two bits. If neither bit is set the pixel will be transparent. The
remaining three combinations determine which of the three possible colours
the pixel will be.

The sprite data is stored in the string variable IMAGE$. To do this the
16bit values are first converted to two 8 bit values (lo and hi byte).

Finally we call SetPointer to activate the new pointer.

At the end of the program we use ClearPointer to restore the normal
pointer.

                                PAGE 108

----------------------------------------------------------------------------

3.3.2  MOVING WINDOWS MADE EASY.

Instead of using the mouse to drag windows around the screen, you can
program Intuition to do the same thing. You can use the intuition routine
"MoveWindow" which requires three parameters:

        MoveWindow(window,deltaX,deltaY)

        window: Address of the window data structure            
        deltaX: Number of pixels to move the window to the right.
                (left = negative)
        deltaY: Same in vertical direction.

These routines do not check your parameters for valid coordinates. If your
delta values set coordinates outside the screen, Intuition will try to move
your window off the monitor. Of course, this will not work. To prevent this
from happening we have added a small error check routine to the next
program. This routine will check your input with the data in the window
data structure (Section 2.2).

This program is a SUB named Move.

        '##############################
        '#
        '# Section: 3.3.2
        '# Program: Window Move.
        '# Date   : 04/10/87
        '# Author : tob
        '# Version: 1.0
        '#
        '###############################

        'Intuition can move selected windows under
        ' program control. This program demonstrates
        ' the WindowMove() command (including
        ' error checking.

        PRINT "Searching for .bmap file .... "

        'INTUITION-library
        'MoveWindow()

        LIBRARY "intuition.library"

                                PAGE 109

----------------------------------------------------------------------------

        demo:   CLS
                WINDOW 2,"Test Window",(10,10)-(400,100),16
                WINDOW OUTPUT 2

                PRINT "Original Position. Please Press a Key"
                WHILE INKEY$="": WEND

                Move 10,20  '10 right,20 down
                PRINT "New position! Press a Key."
                WHILE INKEY$ = "":WEND

                Move -10,-20 ' 10 left, 20 up
                PRINT "Returned!!"

                FOR t = 1 TO 3000: NEXT t

                Move 10000,10000
                ' Nothing happened thanks to the error check.

                WINDOW CLOSE 2
                LIBRARY CLOSE

        SUB Move(x%,y%) STATIC

                win&    = WINDOW(7)
                screen.width%   = 640
                screen.height%  = 200 'PAL systems can use 256 here.
                windo.x%        = PEEKW(win&+4)
                windo.y%        = PEEKW(win&+6)
                windo.width     = PEEKW(win&+8)
                windo.height%   = PEEKW(win&+10)
                min.x%          = windo.x%*(-1)
                min.y%          = windo.y%*(-1)
                max.x%          = screen.width%-windo.width%-windo.x%
                max.y%          = screen.height%-windo.height%-windo.y%
                IF x%<min.x% OR x%>max.x% THEN x% = 0
                IF y%<min.y% OR y%>max.y% THEN y% = 0
                CALL MoveWindow(win&,x%,y%)
        END SUB

                ---------------------------------------------

3.3.3 SETTING WINDOW LIMITS.

All windows that can be sized have a minimum and maximum size. The
Intuition routine WindowLimits sets the limits according to the input
values. The data fields at offset 16 (see section 2.2) are directly
manipulated by WindowLimits. This routine also checks for valid arguments.
When all parameters are OK, WindowLimits returns a TRUE (=1), if not, it
returns a FALSE (=0).

                                PAGE 110

------------------------------------------------------------------------------

WindowLimits requires 5 arguments and returns a result:

result% = WindowLimits%(window,minX,minY,maxX,maxY)

        result% = 1= all OK
                  0= Minimum size greater than maximim size etc.

        minX,minY:  Minimum size of window.
        maxX,maxY:  Maximum sixe of window.

A short example:

        REM 3.3.3 Window Limits.
        DECLARE FUNCTION WindowLimits% LIBRARY
        LIBRARY "intuition.library"
        minX%=5
        minY%=5
        maxX%=640
        maxY%=200
        res%=WindowLimits(WINDOW(7),minX%,minY%,maxX%,maxY%)

        IF res% = 0 THEN
                PRINT "Something is incorrect ......."
        END IF

        LIBRARY CLOSE
        END

                ---------------------------------------------

3.3.4 SIZING WINDOWS.

The Intuition function SizeWindow is used to shrink or enlarge a window.
SizeWindow requires three arguments:

        SizeWindow(window,deltaX,deltaY)

        window: Address of the window data structure.
        deltaX: Number of pixels to enlarge the window horizontally 
                (negative = shrink)
        deltaY: Same action, only vertically.

This routine does not check for incorrect parameters. If your delta values
make the window smaller than is possible or bigger than the screen, you
will encounter a system crash. To prevent this, the next program has a
routine the recognises false values and makes them safe. This SUB is named
Size:

                                PAGE 111

------------------------------------------------------------------------------

        '############################################
        '#
        '# Section: 3.3.4
        '# Program: Window Limits.
        '# Date   : 04/10/87
        '# Author : tob.
        '# Version: 1.0
        '#
        '#############################################

        'Demonstrate setting a window's maximum and
        'and minimum settings.

        PRINT "Searching for .bmap file ......"

        'INTUITION-library
        'WindowLimits

        DECLARE FUNCTION WindowLimits% LIBRARY

        LIBRARY "intuition.library"

        demo:   CLS         
                WINDOW 2,"Test Window",(10,10)-(400,100),16
                WINDOW OUTPUT 2

                '* Set window limits.
                r% = WindowLimits%(WINDOW(7),0,0,600,200)
                IF r% = 0 THEN ERROR 255

                PRINT "Original Size - Please press a key .... "
                WHILE INKEY$ = "": WEND

                Size 60,40      '60 right, 40 down
                PRINT "New size - press a key ......"
                WHILE INKEY$ = "":WEND

                Size -60,-40 ' 60 left, 40 up
                PRINT "Restored!"

                '* Wait
                FOR t=1 TO 3000: NEXT t

                '* Invalid arguments caught here
                Size 10000,10000 ' Error
                ' nothing happened thanks to the error check

                WINDOW CLOSE 2
                LIBRARY CLOSE

        SUB Size(x%,y%) STATIC
                
                win& =          WINDOW(7)
                windo.width%    = PEEKW(win& + 8)
                windo.height%   = PEEKW(win& + 10)
                windo.minX%     = PEEKW(win& + 16)
                windo.minY%     = PEEKW(win& + 18)
                windo.maxX%     = PEEKW(win& + 20)
                windo.maxY%     = PEEKW(win& + 22)
                min.x%          = windo.minX%-windo.width%
                min.y%          = windo.minY%-windo.height%
                max.x%          = windo.maxX%-windo.width%
                max.y%          = windo.maxY%-windo.height%
                IF x%<min.x% OR x%>max.x% THEN x%=0
                IF y%<min.y% OR y%>max.y% THEN y%=0
                CALL SizeWindow(win&,x%,y%)
        END SUB

                                PAGE 112

----------------------------------------------------------------------------

3.3.5 WINDOWTOFRONT AND WINDOWTOBACK.

A window can be moved to the background or foreground in relation to other
windows. These operations are normally performed with the mouse. However,
there are two intuition functions that can perform the same operation from
a program, WindowToFront and WindowToBack.

Here is a small demonstration:

        LIBRARY "intuition.library"

        FOR loop%= 1 TO 10
            CALL WindowToBack(WINDOW(7))
            PRINT "Behind!"
            FOR t = 1 TO 2000: NEXT t
            CALL WindowToFront(WINDOW(7))
            PRINT "In front!"
            FOR t = 1 TO 2000: NEXT t
        NEXT loop%
        END

                                PAGE 113

----------------------------------------------------------------------------

3.4 THE INTUITION SCREEN.

Intuition also manages screens. An intuition screen data structure is
similar to those of intuition windows. The pointer to the screen data is
located at offset 46 in the window data structure. To obtain the base
address of your output window use the following:

        screen& = PEEKL(WINDOW(7)+46)

To calculate the address of an individual data field you add the offset to
the base address. The data structure is as follows:

Data structure Screen/Intuition/342 bytes.

Offset  Type    Description.
------- ------- ---------------------------------------
+000    Long    Pointer to the next screen.
+004    Long    Pointer to the first window in this screen.
+008    Word    X coordinate of upper left corner.
+010    Word    Y coordinate of upper left corner.
+012    Word    Width of the screen.
+014    Word    Height of the screen.
+016    Word    Y coordinate of mouse pointer.
+018    Word    X coordinate of mouse pointer.
+020    Word    Flags
                Bit 0  : 1 = Workbench screen.
                Bit 0-3: 1 = Custom screen.
                Bit 4  : 1 = Showtitle.
                Bit 5  : 1 = Screen beeps now.
                Bit 6  : 1 = Custom bit-map.
+022    Long    Pointer to screen name text.
+026    Long    Pointer to standard title text.
+030    Byte    TitleBar height.
+031    Byte    Vertical limit of titlebar.
+032    Byte    Horizontal limit of titlebar.
+033    Byte    Vertical limit of menus.
+034    Byte    Horizontal limit of menus.
+035    Byte    Top window border.
+036    Byte    Left window border.
+037    Byte    Right window border.
+038    Byte    Bottom window border.
+039    Byte    Unused.
+040    Long    Pointer to standard font TextAttr
+044     --     Viewport of screen.
+084     --     Rastport of screen.
+184     --     Bit-map of screen.
+224     --     LAyerInfo of screen.
+326    Long    Pointer to first screen gadget.
+330    Byte    DetailPen.
+331    Byte    BlockPen.
+332    Word    Backup register for Beep(), stores col0
+334    Long    Pointer to external data.
+338    Long    Pointer to user data.

You probably noticed that the window and screen data structures are quite
similar, even though some fields are new. Again, we will explain each field
individually.

                                PAGE 114

----------------------------------------------------------------------------

3.4.1 SCREEN STRUCTURE.


OFFSET 0: NEXT SCREEN.

Screens are also organised by Intuition in the form of a data chain. When
there are other screens in a chain with your screen, the address of the
next screen's data block is at this offset.


OFFSET 4: FIRST WINDOW.

Remember the data chain used by windows: two fields, the father and child,
provide the address of the previous and next windows. By using these you
can move back and forth through the chain from one window to another.
however, this method has a small flaw. In order to go through the entire
chain, you have to find the beginning of the chain first. The active window
you access is not necessarily the first window in the chain.

If you are interested only in a window in a specific screen, there is an
easier method you can use. This field contains the address of the first
window data block. The address of the next window structure is in offset+0
of the window data structure.

        windo& = WINDOW(7)
        scr& = PEEKL(windo&+46)
        searcher&=scr&+4
        WHILE flag% = 0
            searcher& = PEEKL(searcher&)
            IF searcher& = 0 THEN
                flag% = 1
            ELSE
                counter%=counter%+1
                PRINT "Window";counter%;
                PRINT " Data block address : ";
                PRINT searcher&
            END IF
        WEND
        END

NOTE: Although this method is easier to program, it only accesses those
windows in the output window of the current screen.

                                PAGE 115

----------------------------------------------------------------------------

OFFSET 8, 10, 12 AND 14: SCREEN DIMENSIONS.

Like the window structure, there offsets contain the coordinates of the
upper left hand corner of the screen and the height and width of the
screen. The corner coordinate is relative to the top corner of the
display. The current versions of the Amiga(500-2000) do not allow
horizontal shifting of the screen. Offset field +8 is available for future
compatibility.


OFFSET 16 AND 18: THE MOUSE COORDINATES.

Here you find the X and Y coordinates of the mouse pointer relative to the
upper left hand corner of the screen. During vertical screen movements the
Y value can vary a bit.


OFFSET 20: FLAGS.

The bit descriptions a self-explanatory. Show title means that the screen's
title text is visible. A custom bit-map is suitable when you are generating
a new screen that has its own drawing plane.


OFFSET 22 AND 26: THE NAME OF THE SCREEN.

This offset contains the address of either the name string of this screen
or a standard text string which is taken as default from a window when a
name string is not specified.


OFFSET 30-39: DEFAULT PARAMETERS.

These bytes contain various standard parameters, such as the dimensions
of the title bar etc.. All windows in this screen default to these
dimensions automatically.


OFFSET 40: THE STANDARD CHARACTER SET.

Whenever a window is opened in your screen, it has a standard character set
(a predetermined font). The address of this font is stored here.

We will be discussing character sets in more detail later.

                                PAGE 116

----------------------------------------------------------------------------

OFFSET 44 : THE VIEWPORT.

This is another new term we will be discussing in more detail later. In
relation to the data structure of the screen, the ViewPort is NOT a
pointer. At offset 44, it is the actual ViewPort of the screen. ViewPort,
which is a small data structure 40 bytes long, is an interface to the Amiga
graphic hardware (the COPPER graphic coprocessor).


OFFSET 84: THE RASTPORT.

This offset is not a pointer either but the actual RastPort. You received
an introduction to the RastPort in the window data structure. Since both
screen and windows are drawing planes, the screen also has a RastPort.


OFFSET 184: THE BIT-MAP.

This is a new data structure which is 40 bytes long. Bit-map is the
interface between the screen and the memory it occupies, called
"bit-planes".


OFFSET 234:THE LAYERINFO.

This is the last internal data structure of the screen. It is the core of
thw windowing system (the layers). This will be discussed in detail later.


OFFSET 326: POINTER TO SCREEN GADGETS.

Screens also recognise gadgets that move them to the background or bring
them to the foreground. This field is specifically for internal system use.


OFFSET 330 AND 331: THE SCREEN COLOURS.

Changing the screen colour values that are stored here works the same way
as for windows. The new colours take effect as soon as the screen is
refreshed, such as when you use a menu etc...


OFFSET 332: BACKUP-REGISTER.

Intuition stores the colour from register 0 here when the screen is flashed
or beeped. The following will beep the screen:

        PRINT CHR$(7)


OFFSET 334 AND 338: EXTERNAL AND USER DATA.

These allow the possibility to link other data blocks with the standard
structure.

                                PAGE 117

----------------------------------------------------------------------------

3.4.2 THE INTUITION FUNCTIONS FOR SCREEN HANDLING.

Below are the routines from the intuition library used for screen handling:

        MoveScreen()
        ScreenToBack()
        ScreenToFront()
        WBenchToBack()
        WBenchToFront()

To make things easier we have written three SUBs that use all of these
routines. They are named ScrollScreen, ScreenHere and ScreenBye.

ScrollScreen requires the number of pixels that the screen should scroll
down in the current output window (a negative value scrolls it up).
ScreenBye sends the screen behind all current screens and ScreenHere brings
the screen to the foreground.

Here are the SUBs in a small demonstration program:

        '#####################################
        '#
        '# Section: 3.4.2
        '# Program: Screen Control.
        '# Date   : 01/04/87
        '# Author : tob
        '# Version: 1.0
        '#
        '######################################

        ' Program controlled screen handling.

        PRINT "Searching for .BMAP file ........."

        'INTUITION-library
        'MoveScreen()
        'ScreenToFront()
        'ScreenToBack()

        LIBRARY "intuition.library"

        init:   CLS
                SCREEN 1,320,200,1,1
                WINDOW 2,"Hello1",,,1

        main:   '* Screen scrolling.
                PRINT "This is the second screen! "
                
                                
                                PAGE 118

----------------------------------------------------------------------------

        '* Screen 1 down.       
        WINDOW OUTPUT 2
        FOR loop% = 255 TO 0 STEP -1
            ScrollScreen(1)
        NEXT loop%

        '* Screen 0 Down.
        WINDOW OUTPUT 1
        FOR loop% = 255 TO 0 STEP -1
            ScrollScreen(1)
        NEXT loop%

        '* Screen 1 up.
        WINDOW OUTPUT 2
        FOR loop% = 0 TO 255
            ScrollScreen(-1)
        NEXT loop%

        '* Screen 0 up.
        WINDOW OUTPUT 1
        ScreenHere
        FOR loop% = 0 TO 255
            ScrollScreen(-1)
        NEXT loop%
        
        '* Swapping.
        FOR t% = 1 TO 3000:NEXT t%
        ScreenBye
        FOR t% = 1 TO 3000:NEXT t%
        ScreenHere
        FOR t% = 1 TO 3000:NEXT t%
        
        '* Closing.
        WINDOW CLOSE 2
        SCREEN CLOSE 1

        endprog:        LIBRARY CLOSE
                        END

        SUB ScrollScreen(pixel%) STATIC
                screenAddress&=PEEKL(WINDOW(7)+46)
                CALL MoveScreen(screenAddress&,0,pixel%)
        END SUB

        SUB ScreenHere STATIC
                screenAddress& = PEEKL(WINDOW(7)+46)
                CALL ScreenToFront(screenAddress&)
        END SUB

        SUB ScreenBye STATIC
                screenAddress& = PEEKL(WINDOW(7)+46)
                CALL ScreenToBack(screenAddress&)
        END SUB

                                PAGE 119

----------------------------------------------------------------------------

3.5 INTUITION AND THE REST OF THE WORLD.

So far you have been introduced to the data structure of "windows" and
"screens". It is now time to for review amd show you the connections
between these two data blocks. The following figure symbolises a window
data structure to other components:

                                        |           |
                                        |           |
        ________________________________|___________|_____
       |                                |           |     |
       |                              Screen     Father   |
       |                                                  |
       |            W I N D O W                         __|____ next
       |                                                  |     window
       |        |                               |         |
       |        |                               |         |
       |________|_______________________________|_________|
                |                               |
             RastPort                        Child Window.
        

The "screen" structure can be displayed using a similar figure:


        ____|__________________________________________
       |    |                                          |
       |  Next Screen                                  |
       |                                    1. window  |        
    ------- ViewPort    S C R E E N             ---------- 
       |                                               |
       |                                               |        
       |    |           |                              |
       |    |           |                              |
       |____|___________|______________________________|
            |           |
          BitMap      RastPort

                                PAGE 120

----------------------------------------------------------------------------

The next figure shows the system connection with a screen and a window:

NOTE: THE CHARACTER "+" REPRESENTS A DOWN ARROW.


        _________________________
       |                         |
       |                         |
     __|      S C R E E N        |<--------------------------------
    |  |                         |                                 |
    |  |                         |--------------------------       |
    |  |                         |                         |       |
    |  |_________________________|                         |       |
    |       |      |                                       |       |
    |       |      |                    ___________________+_______|__|_
    +       +      +                   |                              | |
 ViewPort  BitMap RastPort             |                                |
                                       |           W I N D O W        ----
                                       |                                |
                                       |                                |
                                       |___|__________________________|_|
                                           |                          | 
                                           +
                                        RastPort

We are not finished yet. You still need an understanding of the RastPort,
ViewPort and BitMap structures. Next we will take a closer look at the
RastPort.

                                PAGE 121

----------------------------------------------------------------------------

3.6 THE RASTPORT.

With this data block, we get even closer to the basic elements of Amiga
graphics, the so called "graphic primitives". We'll leave intuition to go
deeper into the Amiga system architecture. We'll now explore the graphic
libraries.

The RastPort, which contains the data that controls how a drawing takes
place, manages a drawing plane. The starting address of the data block for
an actual window is always in the variable WINDOW(8). This address can be
read directly from the window data structure.

        PRINT WINDOW(8) 
        PRINT PEEKL(WINDOW(7)+50)

The RastPort structure is constructred as follows:

Data Structure: RastPort/Graphics/100 Bytes.

Offset  Type    Description.            
------- ------- ------------------------------------------------------
+000    Long    Pointer to the layer structure.
+004    Long    Pointer to the Bit-map structure.
+008    Long    Pointer to the AreaFill pattern.
+012    Long    Pointer to the TmpRas structure.
+016    Long    Pointer to the AreaInfo structure.
+020    Long    Pointer to the GelsInfo structure.
+024    Byte    Mask: Writemask for this raster.
+025    Byte    Foreground colour.
+026    Byte    Background colour.
+027    Byte    AreaFill outline colour.
+028    Byte    Drawing mode:
                        JAM1            = 0
                        JAM2            = 1
                        COMPLEMENT      = 2
                        INVERSVID       = 4
+029    Byte    AreaPtSz: 2^n Words for AreaFill pattern.
+030    Byte    Unused.
+031    Byte    Line draw pattern preshift.
+032    Word    various control bits.
                FIRST DOT       = 1 : Draw first pixel?
                ONE DOT         = 2 : one dot mode for lines.
                DBUFFER         = 4 : Double buffered set.
+034    Word    LinePtrn: 16 bits for line pattern.
+036    Word    X coordinate of graphic cursor.

                                PAGE 122

----------------------------------------------------------------------------

+038    Word    Y coordinate of graphic cursor.
+040    ----    8*1 byte minterms.
+048    Word    Cursor Width.
+050    Word    Cursor Height.
+052    Long    Pointer to character set.
+056    Byte    Character set mode (bold, italics etc...)
+057    Byte    textspecific flags.
+058    Word    Height of characterset.
+060    Word    Average character width.
+062    Word    Text height without underline.
+064    Word    Character spacing.
+066    Long    Pointer to user data.
+070    Word    Reserved (7x)
+084    Long    Reserved (2x)
+092    Byte    Reserved (8x)

                ------------------------------------------

3.6.1 THE RASTPORT STRUCTURE.

The following explains the RastPort structure by offset the same manner we
did for windows and screens:

OFFSET 0 : THE LAYER.

The Amiga uses layers to keep each drawing plane separate from the other
planes. These layers are actually the principle elements of each Intuition
window. You might think layers are very complicated and, compared to
windows, relatively useless. However, layers are important and a closer
look (as seen in a later chapter) will prove that they are really a
storehouse of graphic possibilities.


OFFSET 4: THE BITMAP.

You have already learned about the Bitmap, which is a pointer to the
bit-map structure. With this pointer you have indirect access to the screen
address through the RastPort:

        scr& = PEEKL(WINDOW(8)+4)-184

The bit-map is the intersection between the data structure and the RAM
banks where the window and screen contents are stored.

                                PAGE 123

----------------------------------------------------------------------------

OFFSET 8 : POINTER TO THE AREAFILL PATTERN.

You have seen how to fill areas with a single colour or with a pattern. If
you use a pattern, then that pattern has to be stored somewhere in memory.
This offset contains the address pointer to where the pattern is stored.

We will provide more information and examples after the offset
explanations. One of our subjects will show you how to use multi-colour
patterns of up to 32 colours.


OFFSET 12: THE TmpRas.

TmpRas stands for Temporary Raster. This is a pointer to an area of free
RAM used for certain operations. Whenever you use the fill commands like
PAINT or LINE BF, this RAM is used as a temporary holding area for the
entire object being filled.


OFFSET 16: AREA INFO.

This pointer is for a data structure used when drawing polygon shapes.
There is not much use for this from BASIC, but we will discuss it later.


OFFSET 20: GELSINFO.

Gels are Graphic Elements, such as sprites and Bobs (Blitter Objects), and
also the complete automatic Amiga animation system. Before this system can
be activated the GelsInfo structure has to be defined. This structure
contains some very important parameters.


OFFSET 24: WRITEMASK.

This variable allows individual bit-planes of the drawing plane to fade.
The default value is normally 255. All bits are set which means that all
available bit-planes are used. The POKE,

        POKE WINDOW(8) + 24,0

makes all bit-planes inactive and nothing more will be drawn on the
screen. You can also select specific bit planes to be active or inactive.


OFFSET 25,26 AND 27: DRAWING COLOUR.

These registers determine the drawing colours. The first contains the
number of the colour register for the drawing colour. The second has the
background and the third the AreaOutlineMode.

                                PAGE 124

------------------------------------------------------------------------------

OFFSET 28: DRAWING MODE.

The Amiga has four basic drawing modes that you can use. They are:

        JAM1            = 0
        JAM2            = 1
        COMPLEMENT      = 2
        INVERSEVID      = 4

The normal drawing mode is JAM2. This means that the foreground colour is
used to draw in the drawing plane and the rest will be in the background
colour. THe following example will make this clear:

        (Enter these examples in Direct Mode!)
        LINE (0,0)-(100,100),2,bf
        LOCATE 1,1:PRINT "hello!"

Thw white text appears on a blue background. A hole is made in the original
black background.

JAM 1 is different. The foreground colour is used to draw, but the
background is not changed.
        
        LINE (0,0)-(100,100),2,bf
        POKE WINDOW(8)+28,0
        LOCATE 1,1:PRINT "hello"
        POKE WINDOW(8)+28,1

COMPLEMENT complements the graphic with the background: Where ever a pixel
is set, it will be erased and just the opposite for unset pixels:

        LINE (0,0)-(100,100),2,bf
        POKE WINDOW(8)+28,2
        LINE(50,50)-(150,150),3,bf
        POKE WINDOW(8)+28,1

INVERSEVID inverts a graphicL background and foreground are exchanged. It
looks like this:

        POKE WINDOW(8)+28,4
        PRINT "Inverse!"
        POKE WINDOW(8)+28,1

These pokes work great in direct mode. However, they do not work in a
program. Nothing will happen.

The routine SetDrMd in the graphic library sets the desired mode safely and
reliably.

                                PAGE 125

----------------------------------------------------------------------------

        LIBRARY "graphic.library"
        CALL SetDrMd(WINDOW(8),mode%)

        mode% = 0 - 255

Various modes may be combined, only JAM1 and JAM2 work against each other.


OFFSET 29: AreaPtSz.

Whenever you work with patterns, you must specify how high the pattern will
be. Patterns can only be defined using powers of two (1,2,4,8,....). This
field stored the power of two.

Using a special programming method, you can use this register to activate
the mutli-colour pattern mode. This allows you to create patterns with up
to 32 colours. ( There will be more on this in the next section).


OFFSET 30,31 AND 32. FOR SYSTEM USE.

OFFSET 34: LINE PATTERN.

Patterns are not only for areas, but for lines also. The method is easy: 16
pixels in a row can be set or unset. The amiga then uses this Sample
pattern to draw lines. Take the following line pattern for example:

        *****.*.*****.*.

A dash dot dash dot line.

First you determine the bit values of the line:

bit& = 2^15+2^14+2^13+2^12+2^11+2^9+2^7+2^6+2^5+2^4+2^3+2^1

Now the value is stored to this register:

        POKEW WINDOW(8)+34,bit&

A test:

        LINE (10,10)-(600,10)

AS you can see it works.


OFFSET 36 AND 38: COORDINATES OF THE GRAPHIC CURSOR.

These two fields are extremely important. Text on the Amiga is nothing more
than text shaded graphics. Because of this, text can be placed in any
position on the screen. The following example demonstrates this:

        WHILE INKEY$ = ""
           x% = RND(1)*600
           y% = RND(1)*160
           POKEW WINDOW(8)+36,x%
           POKEW WINDOW(8)+38,y%
           PRINT "Commodore Amiga!"
        WEND

                                PAGE 126

----------------------------------------------------------------------------

OFFSET 40-51: MINTERMS, INTERNAL USAGE.

OFFSET 52: THE CHARACTER SET.

Just as in the screen structure this is a pointer to the currently active
font. The character set determines what your text looks like. We will
return to this subject later.


OFFSET 56: ACTUAL TEXT STYLE.

The Amiga can display a font in various forms on the screen:
        
        normal          = 0
        underlined      = Bit 0 set.
        bold            = Bit 1 set.
        italics         = Bit 2 set.

The last three modes can be combined to form different combinations.


OFFSET 57: TEXT FLAGS, INTERNAL USAGE.


OFFSET 58: TEXT HEIGHT.

This field contains the height of the currently active font. This value is
used to average the line height to calculate the correct line spacing.

There is nothing to prevent you from setting you own line spacing. It can
be even closer together than normal:

        POKEW WINDOW(8)+58,5

or further apart:

        POKEW WINDOW(8)+58,12


OFFSET 60: CHARACTER WIDTH.

This register contains the average width of the font. Since the Amiga also
supports proportional fonts (characters of different widths), you can set
the average width in this register.

                                PAGE 127

----------------------------------------------------------------------------

OFFSET 62: TEXT HEIGHT WITHOUT UNDERLINE.


OFFSET 64: CHARACTER SPACING.

The following routine allows you to vary the spacing between individual
characters. The default for this field is zero. Storing larger values here
will spread the characters over a larger area as in the following example:

        text$ = "Hello World!"
        text%=LEN(text$)

        FOR loop% = 1 TO 40
            POKEW WINDOW(8)+36,280-(loop%*text%*.5)
            '(centering)
            POKEW WINDOW(8)+38,90
            POKEW WINDOW(8)+64,loop%
            PRINT text$
        NEXT loop%

        FOR loop% = 39 TO 0 STEP -1
            POKEW WINDOW(8)+36,280-(loop%*text%*.5)
            POKEW WINDOW(8)+38,90
            POKEW WINDOW(8)+64,loop%
            PRINT text%
        NEXT loop%

        END


OFFSET 66: USER DATA.

This is a pointer to more data that can be linked to this structure.


OFFSET 70 to END - Reserved Data Fields.

                                PAGE 128

---------------------------------------------------------------------------- 

3.7 GRAPHIC PRIMITIVES.

The RastPort provides us with the graphic primitives, which is the lowest
software controlled entry address to the graphic planes. First we will try
out a few of the possibilities of the RastPort that we have been
discussing.

                ----------------------------------------------

3.7.1 MULTICOLOUR PATTERNS.

At the beginning if the book we introduced you to the PATTERN statement.
Instead of having plain areas, you can use this statement to fill any
desired area with a pattern of your own design. 

        CIRCLE (310,100),100
        PAINT (310,100),2,1

We can also display patterned areas:

        DIM area.pat%(3)
        area.pat%(0)=&HFFFF
        area.pat%(1)=&HCCCC
        area.pat%(2)=&HCCCC
        area.pat%(3)=&HFFFF

        CIRCLE (310,100),100
        PATTERN ,area.pat%
        PAINT (310,100),3,1

You can see that this works, filling the circle with dotted orange pattern.
Up to now the patterns have been limited to one colour.

We have put together a complete pattern package that will enable you to
design and create your patterns and add more colour to them.

You know from the previous chapter that a pattern has to be stored in a
specific memory area. The height of the pattern is stored in the RastPort
field at Offset 29, as a power of two. Since we know the basics of
patterns, we can now write a small pattern SUB program to activate the
multicolour mode. This mode is switched on whenever the power at offset 29
is negative (a power of 256).

                                PAGE 129

-----------------------------------------------------------------------------

The following program manages patterns without the PATTERN statement. It is
composed of these six routines:

1.      InitPattern(howmany)%

This routine initialises our new pattern system. You pass the parameter for
how many lines high your example pattern is to be.

The routine calculates the required memory and calls GetMemory. The
starting address of the new buffer is form&.


2.      SetPat(number%,pat$)

This new command allows you to easily enter the individual lines of your
pattern in a binary representation: An A equals an unset pixel and a B
equals a set pixel. The number% variable passes the row number of your
pattern and pat$ passes the actual bit pattern. Make sure that pat$ always
contains 16 characters. For a solid line pat$ would look like this:

                     "BBBBBBBBBBBBBBBB"


3.      MonoPattern.

This routine is called without any arguments and activates the pattern
system. Both RastPort addresses are initialised to their correct values in
this routine.


4.      EndPattern.

This routine is also called without any arguments. If tells the Amiga that
your example pattern will no longer be used. The memory used for your
pattern is released back to the system. You should call EndPattern at the
end of your program to release all memory back to the system.


5.      GetMemory(size&).

This is an all purpose memory get routine. Whenever you need memory,
GetMemory gets it for you. You specify an & variable containing the amount
of memory you need in bytes.


6.      

To reserve an area of 1245 bytes:

	DECLARE FUNCTION Allocmem& LIBRARY
	LIBRARY "exec.library"

	mymem& = 1245
	GetMemory mymem&
	PRINT "Starting address: ";mymem&

NOTE: If a value of zero is returned for the starting address the memory
allocation did not work. You did not receive a memory area and cannot use
FreeMemory to return it.


6. FreeMemory(add&)

When you no longer require the memory that you have reserved you return it 
to the system with FreeMemory. A call to this routine looks like this:

	DECLARE FUNCTION AllocMem& LIBRARY
	LIBRARY "exec.library"

	form&=100 '100 bytes please!
	GetMemory form&

	(....)

	FreeMemory form& 'memory released.
	LIBRARY CLOSE

These six routines make working with patterns remarkably easy. Here are the
routines along with a small demonstration program.

	'###################################
	'#
	'# Section : 3.7.1a
	'# Program : Mono-pattern Module.
	'# Date    : 12/27/86
	'# Author  : tob
	'# Version : 1.0
	'#
	'#####################################

	'easy definition of modules using 
	'binary character strings.

	PRINT "Searching for .bmap file ....."

	'Exec library
	DECLARE FUNCTION AllocMem& LIBRARY

				PAGE 131

----------------------------------------------------------------------------

	'FREEMEM

	LIBRARY "exec.library"

	init:	'Activate system.
		CLS
		InitPattern 4

		'Set pattern.
		SetPat 0,"BBBBBBBBBBBBBBBB"
		SetPat 1,"BAAAAAAAAAAAAAAB"
		SetPat 2,"BAAAABBBBBBAAAAB"
		SetPat 3,"BAAAABBBBBBAAAAB"

		'Enable new pattern
		MonoPattern

		'Display Pattern on screen
		LINE (10,10)-(100,100),1,bf
		CIRCLE (300,100),100
		PAINT (300,100),2,1

		'Switch system back off
		EndPattern

	endprog: LIBRARY CLOSE
		 END

	SUB InitPattern(howmany%) STATIC
		SHARED form&,plane1%,plane2%,kolor%

		'* is it a power of 2 ??
		IF LOG(howmany%)/LOG(2)<>INT(LOG(howmany%)/LOG(2) THEN
		    PRINT "2^x! Power of two for InitPattern! 1,2,4,8,16.."
		    ERROR 17
		END IF

		'Read PArameters.
		planes% = PEEK(PEEKL(WINDOW(8)+4)+5)	
		DIM SHARED p&(howmany%*planes%)
		plane1% = planes%
		plane2% = howmany%
		kolor% = 2^plane1%-1

		'Definition pattern Buffer allocate.
		form& = howmany%*2*planes%
		GetMemory form&
	END SUB

	SUB SetPat(number%,pat$) STATIC
		SHARED form&,plane1%,plane2%

		'Too many rows????
		IF number%>=plane2% THEN
		    PRINT "More rows than you can define with InitPattern!"
		    EndPattern
		    ERROR 175
		END IF

				PAGE 132

----------------------------------------------------------------------------

		'* Error handling. Limit string to 16 bytes.
		IF LEN(pat$)<16 THEN
		    pat$=pat$+STRING(16-LEN(pat$),"A")
		END IF

		'Read Definition pattern
		FOR loop1% = 0 TO 15
		    check$ = UCASE$(MID$(pat$,loop1%+1,1)
		    col% = ASC(check$)-65
		    IF col%>=2^plane1% OR col%<0 THEN col% = 0
		    FOR loop2% = col% TO 0 STEP -1
			IF col% >= 2^loop2% THEN
			    col% = = col%-2^loop2%
			    p&(number%+loop2%*plane2%) =
			       p&(number%+loop2%*plane2%)+2^(15-loop1%)
			END IF
		    NEXT loop2%
		NEXT loop1%

		'* Write value to buffer
		FOR loop3% = 0 TO plane2%*plane1%
		    POKEW form&+2*loop3%,p&(loop3%)
		NEXT loop3%
	    END SUB

	    SUB MonoPattern STATIC
		SHARED form&,plane2%
		planes% = LOG(planes2%)/LOG(2)
		POKEL WINDOW(8)+8,form&
		POKEL WINDOW(8)+29,planes%
	    END SUB

	    SUB EndPattern STATIC
	 	SHARED form&

		'Pattern off and release memory.
		POKEL WINDOW(8)+8,0
		POKE WINDOW(8)+29,0
		FreeMemory form&
	    END SUB

	    SUB GetMemory(size&) STATIC
		mem.opt& = 2^0+2^1+2^16
		RealSize& = size&+4
		size& = AllocMem&(RealSize&,opt&)
		IF size& = 0 THEN ERROR 255
		POKEL size&,RealSize&
		size& = size& + 4
	    END SUB

				PAGE 133

-----------------------------------------------------------------------------
	
	SUB FreeMemory(add&) STATIC
		add& = add& - 4
		RealSize& = PEEKL(add&)
		CALL FreeMem(add&,RealSize)
	END SUB

So far our SUB programs do not provide colour patterns. To fix this we will 
add the routine ColorPattern to our program. If replaces MonoPattern and 
activated the multicolor system. Depending on your screen depth, you can
use up to 32 colors in your patterns. Additional characters are available now
for defining your patterns:

	Color 1    A Color Register 0 (background)	
	Color 2	   B Color Register 1 
	Color 3	   C Color Register 2
	Color 4	   D Color Register 3
	(for the workbench screen)

The following program demonstrates multi-colour patterns.

	'############################
	'#
	'# Section: 3.7.1b
	'# Program: Mono &Colour pattern.
	'# Date   : 12/27/86
	'# Author : tob
	'# Version: 1.0
	'#
	'##############################
	

	'Makes "multi-colour" patterns possible.
	'Via RastPort manipulation.

	PRINT "Searching for .bmap file ......."

	'EXEC library
	'DECLARE FUNCTION AllocMem& LIBRARY
	'FreeMem()

	LIBRARY "exec.library"
	
	init:	CLS
		rows%=8
		InitPattern rows%
		'         0123456789ABCDEF'
		SetPat 0,"DCDAAAAAAABBAAAA"
		SetPat 1,"DCDAAAAAABBBBAAA"
		SetPat 2,"DCDAAAAABAABBAAA"
		SetPat 3,"DCDAAAABAAAABBAA"
		SetPat 4,"DCDAAABBBBBBBBBA"
		SetPat 5,"DCDAABAAAAAAABBA"
		SetPat 6,"DCDBBBBAAAAABBBB"
		SetPat 7,"CCCCCCCCCCCCCCCC"

				PAGE 134

----------------------------------------------------------------------------

	drawing:PRINT TAB(7);"MONO";TAB(36);"COLOR!"

		MonoPattern
		CIRCLE (60,60),60
		PAINT (60,60),kolor%,1

		ColorPattern
		CIRCLE (310,100),100
		PAINT (310,100),kolor%,1

	endprog:EndPattern
		LIBRARY CLOSE
		END

	SUB ColorPattern STATIC
		SHARED form&,plane2%
		planes% = LOG(plane2%)/LOG(2)
		POKEL WINDOW(8)+8,form&
		POKE WINDOW(8)+29,256-planes%
	END SUB

	SUB InitPattern(howmany%) STATIC
		SHARED form&,plane1%,plane2%,kolor%

		'Is it a power of two ???
		IF LOG(howmany%)/LOG(2)<>INT(LOG(howmany%)/LOG(2)) THEN
		    PRINT "2^x! A power of two for initpattern! 1,2,4,8,16"
		    ERROR 17
		END IF

		'* Read parameters.
		planes% = PEEK(PEEKL(WINDOW(8)+4)+5)
		DIM SHARED p&(howmany%*planes%)
		plane1% = planes%
		plane2% = howmany%
		kolor% = 2^plane1%-1

		'* Reserve definition pattern buffer.
		form& = howmany%*2*planes%
		GetMemory form&
	END SUB

	SUB SetPat(number%,pat$) STATIC
		SHARED form&,plane1%,plane2%

		'Too many rows?
		IF number%>=plane2% THEN
		    PRINT "More rows than can be defined with InitPattern!"
		    EndPattern
		    ERROR 17
		END IF

				PAGE 135

------------------------------------------------------------------------------

		'* Error-handling: Limit string to 16 bytes,
		IF LEN(pat$)<16 THEN
		    pat$=pat$+STRING$(16-LEN(pat$),"A")
		END IF

		'* Read Pattern Definition.
		FOR loop1% = 0 TO 15
		    check$ = UCASE$(MID$(pat$,loop1%+1,1))
		    col% = ASC(check$)-65
		    IF col%>=2^plane1% OR col1%<0 THEN col% = 0
		    FOR loop2% = col% TO 0 STEP -1
			IF col%>=2^loop2% THEN
			    col% = col%-2^loop2%
			    p&(number%+loop2%*plane2%) =
			       p&(numer%,+loop2%*plane2%)+2^(15-loop1%)
			END IF
		    NEXT loop2%
		NEXT loop1%

		'* Write value to buffer.
		FOR loop3% = 0 TO plane2%*plane1%
		    POKEW form&+2*loop3%,p&(loop3%)
		NEXT loop3%
	END SUB
	
	SUB MonoPattern STATIC
		SHARED form&,plane2%
		planes% = LOG(plane2%)/LOG(2)
		POKEL WINDOW(8)+8, form&
		POKE WINDOW(8)+29, planes%
	END SUB

	SUB EndPattern STATIC
		SHARED form&

		'*Pattern off and release memory.
		POKEL WINDOW(8)+8,0	
		POKEW WINDOW(8)+29,0	
		FreeMemory form&
	END SUB

	SUB GetMemory(size&) STATIC
		mem.opt& = 2^0+2^1+2^16
		RealSize&= size&+4
		size& = AllocMem&(RealSize&,opt&)
		IF size& = 0 THEN ERROR 255
		POKEL size&,RealSize&
		size& = size&+4
	END SUB

	SUB FreeMemory(add&) STATIC
		add& = add&-4
		RealSize& = PEEKL(add&)
		Call FreeMem(add&,RealSize&)
	END SUB

				PAGE 136

----------------------------------------------------------------------------

If the four workbench screens are not enough, you can create your own 
screens with more than 2 bit-planes. The following program does just this.
After the initialisation you will see, as a fill pattern, a familiar logo
in 11 colors. If you hold down the left mouse button you can draw using this
pattern.


	'############################
	'#
	'# Section: 3.7.1c
	'# Program: Multi-Colour-Pattern
	'# Date   : 12/27/86
	'# Author : tob
	'# Version: 1.0
	'#
	'##############################
	
	'Demonstrates the use of a multi-colour pattern with 
	' up to 16 Colors (Screen Depth = 4), ; up to 32 colours
	' possible.
	'Color value: A=0 to Z=25, Colors 26-32 = chr$(91)-chr$(97)
	' On "out of heap space" close other window!

	PRINT "Searching for .bmap file ......."

	'EXEC library
	'DECLARE FUNCTION AllocMem& LIBRARY
	'FreeMem()

	LIBRARY "exec.library"
	
	init:	SCREEN 1,640,200,4,2
		WINDOW 1,"Hello!",,,1		

		LOCATE 4,15
		PRINT "** Patience ! **"

		rows%=8
		InitPattern rows%
		'         0123456789ABCDEF'
		SetPat 0,"AAAAAAAAAAABBABB"
		SetPat 1,"AAAAAAAAAABBABBA"
		SetPat 2,"AAAAAAAAACCACCAA"
		SetPat 3,"AAAAAAAADDADDAAA"
		SetPat 4,"FFAFFAAEEAEEAAAA"
		SetPat 5,"AGGAGGHHAHHAAAAA"
		SetPat 6,"AAKKAIIAIIAAAAAA"
		SetPat 7,"AAAJJJJJJAAAAAAA"

				PAGE 137

----------------------------------------------------------------------------

	patcol:	'* Colour choices for the pattern.
		PALETTE 0,0,0,0		'A
		PALETTE 1,.9,.3,.4	'B
		PALETTE 2,.8,.5,.4	'C
		PALETTE	3,.8,.6,0	'D
		PALETTE	4,1,.8,0	'E
		PALETTE 5,0,0,.6	'F
		PALETTE 6,0,.3,.6	'G
		PALETTE 7,.7,.9,0	'H
		PALETTE 8,.3,.9,0	'I
		PALETTE 9,0,.5,0	'J
		PALETTE 10,0,.3,0!	'K


	drawing:ColorPattern
		LOCATE (3,10)

		PRINT "Press Left mouse button to draw"
		PRINT TAB(10);"Touch left screen border to exit."	
		CIRCLE (310,100),100
		PAINT (310,100),kolor%,1


	mousecontr:test% = MOUSE(0)
		WHILE MOUSE(1)<>0
		    x%=MOUSE(1)
		    y%=MOUSE(2)
		    IF test%<>0 THEN
			LINE (x%,y%)-(x%+10,y%+5),kolor%,bf
		    END IF
		    test% = MOUSE(0)
		WEND


	endprog:EndPattern
		WINDOW 1,"Demo Over !!!",,,-1
		LIBRARY CLOSE
		END


	SUB ColorPattern STATIC
		SHARED form&,plane2%
		planes% = LOG(plane2%)/LOG(2)
		POKEL WINDOW(8)+8,form&
		POKE WINDOW(8)+29,256-planes%
	END SUB

	SUB InitPattern(howmany%) STATIC
		SHARED form&,plane1%,plane2%,kolor%

		'Is it a power of two ???
		IF LOG(howmany%)/LOG(2)<>INT(LOG(howmany%)/LOG(2)) THEN
		    PRINT "2^x! A power of two for initpattern! 1,2,4,8,16"
		    ERROR 17
		END IF

				PAGE 138

----------------------------------------------------------------------------

		'* Read parameters.
		planes% = PEEK(PEEKL(WINDOW(8)+4)+5)
		DIM SHARED p&(howmany%*planes%)
		plane1% = planes%
		plane2% = howmany%
		kolor% = 2^plane1%-1

		'* Reserve definition pattern buffer.
		form& = howmany%*2*planes%
		GetMemory form&
	END SUB

	SUB SetPat(number%,pat$) STATIC
		SHARED form&,plane1%,plane2%

		'Too many rows?
		IF number%>=plane2% THEN
		    PRINT "More rows than can be defined with InitPattern!"
		    EndPattern
		    ERROR 17
		END IF


		'* Error-handling: Limit string to 16 bytes,
		IF LEN(pat$)<16 THEN
		    pat$=pat$+STRING$(16-LEN(pat$),"A")
		END IF

		'* Read Pattern Definition.
		FOR loop1% = 0 TO 15
		    check$ = UCASE$(MID$(pat$,loop1%+1,1))
		    col% = ASC(check$)-65
		    IF col%>=2^plane1% OR col1%<0 THEN col% = 0
		    FOR loop2% = col% TO 0 STEP -1
			IF col%>=2^loop2% THEN
			    col% = col%-2^loop2%
			    p&(number%+loop2%*plane2%) =
			       p&(numer%,+loop2%*plane2%)+2^(15-loop1%)
			END IF
		    NEXT loop2%
		NEXT loop1%

		'* Write value to buffer.
		FOR loop3% = 0 TO plane2%*plane1%
		    POKEW form&+2*loop3%,p&(loop3%)
		NEXT loop3%
	END SUB
	
	SUB MonoPattern STATIC
		SHARED form&,plane2%
		planes% = LOG(plane2%)/LOG(2)
		POKEL WINDOW(8)+8, form&
		POKE WINDOW(8)+29, planes%
	END SUB


				PAGE 139

----------------------------------------------------------------------------

	SUB EndPattern STATIC
		SHARED form&

		'*Pattern off and release memory.
		POKEL WINDOW(8)+8,0	
		POKEW WINDOW(8)+29,0	
		FreeMemory form&
	END SUB

	SUB GetMemory(size&) STATIC
		mem.opt& = 2^0+2^1+2^16
		RealSize&= size&+4
		size& = AllocMem&(RealSize&,opt&)
		IF size& = 0 THEN ERROR 255
		POKEL size&,RealSize&
		size& = size&+4
	END SUB

	SUB FreeMemory(add&) STATIC
		add& = add&-4
		RealSize& = PEEKL(add&)
		Call FreeMem(add&,RealSize&)
	END SUB

		----------------------------------------------------

3.7.2 SHADOWS USING CURSOR POSITIONING.

The multi-coloured patterns in the last section were created by skillfully
manipulating the rastports. With some creativity you can do a lot more with 
these data structures. To demonstrate this we will show you what can be done
with a little help from offset fields 28,36 and 38.

These fields manage:

Offset	Type	Description
------- ------- ---------------------------------------
+028	Byte	Drawing modes:
		JAM1		= 0
		JAM2		= 1
		COMPLEMENT	= 2
	 	INVERSE VID	= 4

+036	Word	Coordinate of graphic cursor.
+038	Word	Coordinate of graphic cursor.

With these offsets we will create a shadowed text effect. You may have seen 
this method on television, which has used it for a long time. First the 
text is printed in black, then the text is printed again in white over the 
black but slightly offset. This creates a shadow effect that makes the text
visibly stand out. It doesnt matter if the background is dark or light, the
contrast is still visible.

				PAGE 140

----------------------------------------------------------------------------

We will use three routines from the graphic library to create our effect:

	SetDrMd()
	Text()
	Move()

The first routine, SetDrMd(), sets the drawing mode and directly affects 
RastPort offset 28, (see section 3.6.1). The text routine Text(), which
was discussed in chapter 2, prints text on the screen. The move routine 
Move(), puts the graphic cursor at a selected position and affects Rastport
offsets 36 and 38. Instead of using the Move() routine, you could poke the
values into the memory offsets.

Our routine is named "shadows" and it requires two arguments:

	Shadow text$,mode%

	text$:	The text that is to be displayed.
	mode%:	0 = PRINT text$
		1 = PRINT text$;

	Here is the program:

	'#########################################	
	'#
	'# Section : 3.7.2
	'# Program : Shadow Print.
	'# Datum   : 12/25/86
	'# Author  : tob
	'# Version : 1.0
	'#
	'###########################################

	PRINT "Searching for .bmap file ....."

	'GRAPHICS-Library
	'Text()
	'Move()
	'SetDrMd()

	LIBRARY "graphics.library"

	main: 	'* Contrast color
		PALETTE 0,.5,.5,.5
		CLS
		LOCATE 5,1
		PRINT "This is normal text without contrast."
		PRINT "Not very exciting ....."		

				PAGE 141

-----------------------------------------------------------------------------

		PRINT 
		Shadow "Shadow print is just a fast as print !",0
		Shadow "It works due to the actions of the ",0
		Shadow "Text() function of the Graphic-Library",0
		PRINT
		Shadow "The text effectively appears to float",0
		Shadow "in FRONT of the screen.",0

	endprog: LIBRARY CLOSE
		 END

	SUB Shadow(Text$,mode%) STATIC

		'* Lock in parameters.
		textlen% = LEN(Text$)
		depth% = 2
		cx% = PEEKW(WINDOW(8)+36)
		cy% = PEEKW(WINDOW(8)+38)

		'* Draw shadows.
		COLOR 2,0
		CALL Move(WINDOW(8),cx%+depth%,cy%+depth%)
		CALL Text(WINDOW(8),SADD(Text$),textlen%)

		'* Draw JAM1 and Foreground.
		CALL SetDrMd(WINDOW(8),0)
		COLOR 0M2
		CALL Move(WINDOW(8),cX%,cY%)
		CALL Text(WINDOW(8),SADD(Text$),textlen%)

		'* CR as desired.
		IF mode% = 0 THEN
			PRINT
		END IF

		'* And again with JAM2 and finish.
		CALL SetDrMd(WINDOW(8),1)
	END SUB

During the drawing process it is necessary to switch the drawing mode from
JAM2 to JAM1. Otherwise the white text would completely cover the black 
text.

We use the Text() function instead of the PRINT statement to gain more speed
. Text() is more than 3 times faster than PRINT. This is why our shadow
text is displayed faster than the normal text. To see the difference just
switch the lines around:

	CALL Text(WINDOW(8),SADD(text$),textlen%)

for the line:
		
	PRINT text$

The difference in speed is enormous.

		----------------------------------------------

3.7.3 OUTLINE PRINT - A SPECIAL FLAIR.

This type of text displays only the silhouette of the characters. It 
quickly catches the eye and is especially useful for creating titles.

You can access this mode by using the following technique. The text is 
output using the drawing mode JAM1 and, while being displayed, is moved
one pixel in all directions. The result is a smeared character. Now the 
text is output again in the original position using the background color.
The final result is a silhouette of a character.

Here is a routine named OUTLINE which is very similar to the previous 
shadow routine.


	'#########################################	
	'#
	'# Section : 3.7.3
	'# Program : Outlne Print.
	'# Datum   : 12/25/86
	'# Author  : tob
	'# Version : 1.0
	'#
	'###########################################

	PRINT "Searching for .bmap file ....."

	'GRAPHICS-Library
	'Text()
	'Move()
	'SetDrMd()

	LIBRARY "graphics.library"

	main: 	CLS
		LOCATE 5,1
		Outline " OUTLINE PRINT stands out and catches the eye!",0
		Outline " Although the drawing process is complicated, ",0
		Outline "it is extremely fast due to the Text() function",0
		Outline "Outline will also work with other character sets",0

	endprog: LIBRARY CLOSE
		 END

				PAGE 144

----------------------------------------------------------------------------

	SUB Outline(Text$,mode%) STATIC

		'* Lock in parameters.
		textlen% = LEN(Text$)
		cx% = PEEKW(WINDOW(8)+36)
		cy% = PEEKW(WINDOW(8)+38)

		'* JAM1 and smear text.
		'* A loop is faster and more effective.
		CALL SetDrMd(WINDOW(8),0)
		CALL Move(WINDOW(8),cx%+1,cy%)
		CALL Text(WINDOW(8),SADD(Text$),textlen%)
		CALL Move(WINDOW(8),cx%-1,cy%)
		CALL Text(WINDOW(8),SADD(text$),textlen%)
		CALL Move(WINDOW(8),cx%,cy%+1)
		CALL Text(WINDOW(8),SADD(Text$),textlen%)
		CALL Move(WINDOW(8),cx%,cy%-1)
		CALL Text(WINDOW(8),SADD(text$),textlen%)		
		CALL Move(WINDOW(8),cx%-1,cy%-1)
		CALL Text(WINDOW(8),SADD(Text$),textlen%)
		CALL Move(WINDOW(8),cx%+1,cy%+1)
		CALL Text(WINDOW(8),SADD(text$),textlen%)
		CALL Move(WINDOW(8),cx%+1,cy%-1)
		CALL Text(WINDOW(8),SADD(Text$),textlen%)
		CALL Move(WINDOW(8),cx%-1,cy%+1)
		CALL Text(WINDOW(8),SADD(text$),textlen%)

		'* Background colour and hollow text.
		COLOR 0,0
		CALL Move(WINDOW(8),cx%,cy%)
		CALL Text(WINDOW(8),SADD(text$),textlen%)

		'* Reset Modes and colour, CR as needed
		COLOR 1,0
		IF mode%=0 THEN
			PRINT
		END IF
		CALL SetDrMd(WINDOW(8),1)
	END SUB

		--------------------------------------------------

3.7.4 TEXT STYLES

The four different text styles of the Amiga can be program controlled. The 
value stored at RastPort offset 56 controls how the Amiga displays the text.

				PAGE 144

----------------------------------------------------------------------------

		A.) normal
		B.) BOLD
		C.) underlined.
		D.) Italics.

In addition to these, you can combine the styles. These are basically two
ways to switch between these styles:

A.) Direct RastPort Manipulation.

    With this method you POKE directly to the RastPort to switch. It works
    like this:

		normal% = 0
		underline% = 2^0
		bold% = 2^1
		italic% = 2^2

		POKE WINDOW(8)+56,underline%
		PRINT "Underlined text"

		POKE WINDOW(8)+56,bold%
		PRINT "Bold Text"

		POKE WINDOW(8)+56,italic%+underline%
		PRINT "Combined: Italic and Underlined"

		POKE WINDOW(8)+56,normal%

b.) Via graphic libraries:

The library has two functions that handle text styles:

	AskSoftStyle() and SetSoftStyle()

The principle is similar. Again the four types are available and can be 
mixed. The call to SetSoftStyle requires a third parameter:

	newStyle% = SetSoftStyle%(RastPort,mode,enable)

	RastPort :	Address of RastPort.
	mode	 :	The desired style.
	enable   :	The available styles.

If is possible that a font won't be compatible with a specific style and 
therefore, will not be legible. To prevent this, the graphic library 
provides the enable field. The AskSoftStyle function checks a mask that 
returns all the legal styles available for the current font. This value
is then returned to SetSoftStyle. Here is a sample program:

				PAGE 145

----------------------------------------------------------------------------

	'##################################
	'#
	'# Section : 3.7.4
	'# Program : SoftStyle.
	'# Date    : 12/20/86
	'# Author  : tob
	'# Version : 1.0
	'#
	'####################################

	' Demonstrates the use of different text styles
	' named 'softstyles' that are software controlled.

	PRINT "Searching for .bmap file .........."

	'GRAPHICS LIBRARY
	DECLARE FUNCTION AskSoftStyle& LIBRARY
	DECLARE FUNCTION SetSoftStyle& LIBRARY
	'SetDrMd

	LIBRARY "graphics.library"

	init:	normal = 0
		underline = 2^0
		bold = 2^1
		italic = 2^2
		CLS

	main: '* JAM1 for legible slanted text.
		CALL SetDrMd(WINDOW(8),0)
		LOCATE 4,1
		SetStyle underline+bold
		PRINT TAB(8);"ALGORITHM GENERATED TEXT STYLES"
		PRINT
		SetStyle normal
		PRINT "The Amiga can do a lot the the existing fonts."
		PRINT "without a ";
		SetStyle underline
		PRINT "Definition Change";
		SetStyle normal
		PRINT "You can use these styles:"
		PRINT
		SetStyle bold
		PRINT "BOLD Print"
		SetStyle italic
		PRINT "ITALIC Print"
		SetStyle underline
		PRINT "UNDERLINED text"
		SetStyle underline+italic
		PRINT "and MIXED."
		PRINT
		SetStyle normal
		PRINT "These tricks let you display text professionally."

				PAGE 146

----------------------------------------------------------------------------

		CALL SetDrMd(WINDOW(8),1)

		LIBRARY CLOSE
		END

	SUB SetStlye(mode) STATIC
		'0   = normal
		'2^0 = underline
		'2^1 = bold
		'2^2 = italic
		mode%=CINT(mode)

		'* Check font and if possible set new style.
		enable%   = AskSoftStyle&(WINDOW(8))
		newstyle% = SetSoftStyle&(WINDOW(8),mode%,enable%)
	END SUB

You probably noticed that the italic print in the first example was 
somewhat deformed but in the above example the italics looked much better.
The reason for this is that italics only work correctly in JAM1 mode. When
characters are slanted, the right side of each character extends slightly 
into the next character's position. If the normal JAM2 mode is active,
this overlap is covered by the background colour making the character look
chopped off.

				PAGE 147

----------------------------------------------------------------------------

3.8 THE RASTPORT AND THE GRAPHIC SYSTEM.

We'll now look at the RastPort an relation to the graphic system if the 
Amiga. Youll see that the RastPort becomes a component of windows and 
screens.

		__________________________________
	       |                                  |
 	       |     R  A  S  T  P  O  R  T       |
      Bitmap --|---                               |
	       |                        |         |
	       |________________________|_________|
					|
					Layer

With this we can represent the entire system much better. Below we have 
added a RastPort to the figure from Section 3.5:

               __________________________
              |                          |
       _______|____ S  C  R  E  E  N   __|_________________  
      |       |	                         |                 |
      |       |	          	       __|___________      |
   Viewport.  |___|_____|________________|           |     |
		  |     |		          ___|_____|_______|__ 
		  |     |     _____               |		   |  |
		  |     |____|     |	          |    W I N D O W    |
                  |      ____| R P |              |                ---|---
		  |     |    |_____|	          |                   |
		  |     |                         |   |            |  |
					          |___|____________|__|
						      |            |
						   ___|___
					          |       |
					 BitMap<--|  R P  |
					          |_______|
						       |
						       |

We still need information about ViewPort, Bit-Map and Layers. However, the 
picture we are building of the Amiga operating system is becoming much 
clearer. Our next subject is the bit-map data structure.

				PAGE 148

----------------------------------------------------------------------------

3.9 THE BIT-MAP STRUCTURE.

Through this structure we gain access to the RAM banks where the screen 
contents are stored. This data structure is 40 bytes long:

Offset	Type	Description.
------- ------- -----------------------------------
+000	Word	Bytes per display line.
+002	Word	Number of display lines.
+004	Byte	System flag (unused)
+005	Byte	Number of bit-planes (depth)
+006 	Word	Unused.
+008	Long	Pointer to 1st bitplane.
+012	Long	Pointer to 2nd bitplane.
+016	Long	Pointer to 3rd bitplane.
+020	Long	Pointer to 4th bitplane.
+024	Long	Pointer to 5th bitplane.
+028	Long	Pointer to 6th bitplane.
+032	Long	Pointer to 7th bitplane.
+036	Long	Pointer to 8th bitplane.

You obtain the starting address of the data structure like this:

	bitmap& = PEEKL(WINDOW(8)+4)

The first two fields contain the screen measurements stored by the 
bit-planes:

	bitmap& = PEEKL(WINDOW(8)+4)
	x%=PEEKW(bitmap&)*8
	y%=PEEKW(bitmap&+2)
	PRINT "Extent : horiz. ";x%;
	PRINT "vert. ";y%

The fourt field contains the number of used bit-planes. Presently you can
only have up to six active bit-planes. The pointers for planes seven and
eight are for future expansion compatibility of the Amiga.

				PAGE 149

----------------------------------------------------------------------------

                       CHAPTER 4 - THE VIEWPORT
 
 
We have now covered almost all of the graphic hardware. The ViewPort which
consists of a data block of 40 bytes, represents the most elementary 
display of the Amiga.
 
Data Structure - Viewport/graphics/40 bytes.
 
Offset  Type    Description.
------- ------- ------------------------------------------
+000    Long    Pointer to next viewport.
+004    Long    Pointer to ColorMap.
+008    Long    DspIns: Copper list from Make View.
+012    Long    SprIns: Copper list for sprites.
+016    Long    ClrIns: Copper list for sprites.
+020    Long    UCopIns: User copper list.
+024    Word    Width of display
+026    Word    Height of display.
+028    Word    X Offset from (0,0) of bit-plane.
+030    Word    Y Offset from (0,0) of bit-plane.
+032    Word    ViewPort mode:
                    Bit 1  :  1 = GENLOCK VIDEO.
                    Bit 2  :  1 = INTERLACE.
                    Bit 6  :  1 = PFBA
                    Bit 7  :  1 = EXTRA HALFBRITE
                    Bit 8  :  1 = GENLOCK VIDEO.
                    Bit 10 :  1 = DUALPF
                    Bit 11 :  1 = HAM
                    Bit 13 :  1 = VP_HIDE.
                    Bit 14 :  1 = SPRITES.
                    Bit 15 :  1 = HIRES.
+034    Word    reserved.
+036    Long    Pointer to RasInfo structure.
 
Before we cover the offset description, we must explain the importance of
a ViewPort.
 
A ViewPort is a data structure in RAM which represents a part of what you 
see on the screen. If you take a close look at the screen structure in
section 3.4 you will see that the ViewPort is part of this structure. The
reason for this is that an Intuition screen is really a ViewPort with 
accessories. So the heart of every screen is a ViewPort.
 
                                PAGE 151
 
---------------------------------------------------------------------------------
 
A display consists of one or more ViewPorts. The following diagram 
illustrates this :
 
 
    ********************************************************************
    *                                                                  *
    *    --------------------------                                    *
    *   |                          |                                   *
    *   |                          |                                   *
    *   |       VIEWPORT 1         |                                   *
    *   |                          |                                   *
    *   |__________________________|                                   *
    *                                                                  *
    *      ______________________________________________              *
    *     |                                              |             *
    *     |                                              |             *
    *     |                                              |             *
    *     |               VIEWPORT 2                     |             *
    *     |                                              |             *
    *     |                                              |             *
    *     |______________________________________________|             *
    *                                                                  *
    *                                    ___________________________   *
    *                                   |                           |  *
    *                                   |         VIEWPORT 3        |  *
    *                                   |                           |  *
    *                                   |___________________________|  *
    *                                                                  *
    ********************************************************************
 
ViewPorts have the following restrictions : 1.) it is not possible to place
viewports next to each other. 2.) A ViewPort cannot overlap another 
ViewPort. 3.) there must be at least one pixel row betwen them.
 
Each ViewPort can have it's own graphic attributes like colour and 
bit-plane. Also, the ViewPort is further divided among several areas called
windows. However, windows do not have the same limitations as ViewPorts and
they can overlap each other.
 
Now we will present a detailed description of the data structure.
 
                                PAGE 152
 
-----------------------------------------------------------------------------
 
 
4.1 THE VIEWPORT DATA STRUCTURE.
 
OFFSET 0 : NEXT VIEWPORT.
 
A display can consist of one or more ViewPorts connected in a chain. This
field points to the next ViewPort of a display. If there are no further 
ViewPorts, this field equals zero.
 
OFFSET 4: COLOUR MAP.
 
Every ViewPort can define it's own colour. This offset points to a data
structure called "colormap" which stores the RGB value if this colour.
Depending on how many bit-planes are available, a ViewPort can use up to 32
individual colours (without using special modes).
 
OFFSET 8, 12, 16 AND 20: COPPER LIST.
 
The Copper, which is one of three Amiga graphic coprocessors, controls the
entire display, manipulates registers, moves sprites and programs the 
blitter (the copy processor). A special programming language designed 
exclusively for the Copper consists of three commands. This field of the 
ViewPort structure contains the copper command list which the Copper uses
to build a display. The first list determines how to link the other three
lists and use them to display the ViewPort.
 
OFFSET 24 AND 26: WIDTH AND HEIGHT.
 
These two offsets contain the width and height of the display section 
controlled by this ViewPort.
 
OFFSET 28 AND 30: BITMAP OFFSET.
 
At this offset we find the coordinates of the upper left hand corner of the
ViewPort relative to the complete display. These values are used to position
the ViewPort. DyOffset can vary between -16 and +200 (interlace -32 to +400)
DxOffset can vary between -16 and +352 (in hires -32 to +704).
 
OFFSET 32: THE VIEWPORT MODES.
 
The amiga has many different graphic modes. The most well known are hi-res
(640 pixels horizontal) and interlace (400 pixels vertically). This 
field contains a value for the current mode. 
 
 
                                PAGE 153
 
-----------------------------------------------------------------------------
 
OFFSET 36: THE RASINFO BLOCK.
 
Every ViewPort has at least one RasInfo data structure connected to it. We 
will discuss this further on. 
 
                                 PAGE 154
 
-----------------------------------------------------------------------------
 
4.2 THE GRAPHIC MODES OF THE AMIGA.
 
The amiga has the following nine special graphic modes :
 
        Genlock Video.
        Interlace.
        PFBA.
        Extra halfbrite.
        DUALPF
        HAM
        VP-Hide
        SPrites
        Hi-res
 
You should already be familiar with the hi-res and interlace modes supported
by AmigaBASIC. The AmigaBASIC SCREEN statement can specify screens from 
lo-res (normal 320 pixels wide), hi-res (640 pixels wide) to interlace 
(400 instead of 200 pixels high).
 
If the ViewPort will contain sprites or Vsprites, you must set the sprite 
flag (this is normally true).
 
VP-Hide is set whenver this ViewPort is covered by other ViewPorts (for
example, a screen covers another screen). The other viewport is not 
displayed.
 
Genlock Video means that instead of the background colour, an external
video signal, like a video recorder or camera, provides the background.
You need a genlock interface to use this mode.
 
DUALPF stands for "dual playfield". This mode allows you to display two
different planes in one ViewPort. The background of the top plane becomes
transparent to show the plane underneath.
 
PFBA works with the dual playfield mode. It determines the video priority 
of the two planes.
 
HAM stands for Hold and Modify. This mode allows you to display all 4096
colours of the Amiga on the screen at the same time. However, this display
mode is very difficult to program. More on this subject shortly.
 
Extra halfbrite is a new graphic mode that allows you to display up to 64
colors at the same time instead of the normal 32.
 
                                PAGE 155
 
-----------------------------------------------------------------------------
 
4.2.1 THE HALFBRITE MODE.
 
Extra halfbrite is one of the special graphic modes not supported by the 
BASIC SCREEN statement. It is therefore impossible to create a screen in 
this mode using SCREEN.
 
It is possible to convert an existing screen to a halfbrite screen. Before 
we show you how to do this we are going to explain the halfbrite technique.
 
Normally the Amiga can only display up to 32 colors at one time. This is 
because of two factors: 1.) The number of available colours is determined
by the number of bit-planes (5, 2^5=32)and 2). The Amiga has 32 colour 
registers to store colour values that were defined using the AmigaBASIC 
PALETTE statement.
 
When the halfbrite mode is active, you have six bit-planes available and the
number of available colours increases accordingly from 2^5=32 to 2^6=64.
However, since there are only 32 colour registers, there isnt space for the
other 32 colours. To  solve this problem we use the 32 registers twice. We
obtain colours 0 to 31 directly from registers 0 to 31. Colours 32 to 63 
are also obtained from registers 0 to 31 but the RGB values in the registers
are shifted one bit to the right.
 
However, this causes three effects: 1.) The extra 32 halfbrite colours 
cannot be freely defined because they rely on the values of the first 32
colours. 2.) the extra colours are copies of the existing colours but are
darker (therefore the name halfbrite), and 3.) if the first 32 colours are
very dark there will be little visible difference between them and the 
second 32 colors.
 
Although these limits may sound troublesome, the halfbrite mode is still 
reqarding because you can have an extra 32 slightly darker variations of 
your first 32 colours to work with.
 
Since we cannot normally active the halfbrite mode with BASIC, we are going
to create a screen with a depth of five bit-planes. From the information
in the previous chapters, we know the Amiga graphics system fairly well by
now. Therefore, it should not be difficult to set up a sixth bit-plane in
the bit-map structure of the screen. Finally, set the halfbrite flags in 
the ViewPort. (There is just one small problem that we will cover shortly).
 
To mke our screen a reality, we have to access two system libraries :
We need the following functions :
 
        RemakeDisplay()
        AllocMem()
        FreeMem()
 
                                PAGE 156
 
-----------------------------------------------------------------------------
 
 
Our program, the halfbrite activator, follows. In addition to the 
demonstration program there are two SUB programs, HalfBriteOn and 
HalfBriteOff. Neither SUB requires any arguments.
 
        '#####################################
        '#
        '# Section : 4.2.1
        '# Program : Halfbrite Activator.
        '# Date    : 01/17/87
        '# Author  : tob
        '# Version : 1.1
        '#
        '#######################################
        '
        ' Activates the Amiga special graphic mode "halfbrite"
        ' Not normally available in BASIC. With 6 bit-planes
        ' there are a total of 64 different colours available.
        ' We will explain the functions and the most effective
        ' programming methods for this mode in this book. NOTE :
        ' This mode only functions in LoRes mode.
 
        PRINT "Searching for .bmap file ..... "
 
        'EXEC-Library
        DECLARE FUNCTION AllocMem& LIBRARY
        'FreeMem
        'INTUITION-LIBRARY
        'RemakeDisplay()
        
        LIBRARY "intuition.library"
        LIBRARY "exec.library"
 
        main:
            loRes            = 1
            screen.nr%       = 1
            screen.x%        = 320
            screen.y%        = 200
            screen.depth%    = 5 '5 planes required'
            screen.resolution% = loRes
            SCREEN screen.nr%,screen.x%,screen.y%,screen.depth%,
screen.resolution%
 
            'Open a window in the new screen.
            windo.nr%          = 1
            windo.name$        = "Halfbrite!"
            WINDOW windo.nr%,windo.name$,,,screen.nr%
 
 
                                PAGE 157
 
-----------------------------------------------------------------------------
 
        demo: 'Activate Halfbrite
            HalfBriteOn
 
            PRINT TAB(10);"The HalfBrite Mode!"
             
            'The original colours.
            LOCATE 3,2:COLOR 1,0
 
            PRINT "A ";
            FOR loop%=0 TO 31
                COLOR 0,loop%
                PRINT " ";
            NEXT loop%
 
            '*  ... and the halfbrite colours.
            PRINT "B ";
            FOR loop% = 32 TO 63
                COLOR 0,loop%
                PRINT " ";
            NEXT loop%
 
            LINE (22,15)-(280,32),1,b
            LOCATE 7,2:COLOR 1,0
            PRINT "A: The 32 original colours, stored"
            PRINT "   in the hardware colour registers."
 
            LOCATE 10,2
            PRINT "B: The additional 32 HalfBrite "
            PRINT "   colours, corresponding to the "
            PRINT "   original colours at half intensity"
 
            LOCATE 14,2
            PRINT " The blinking sample shows when the"
            PRINT " Colour register of the original colour"
            PRINT " is changed, the HalfBrite colour is"
            PRINT " changed accordingly."
 
            LOCATE 19,4
            PRINT "Press the left mouse button"
 
            WHILE check% = 0
                check% = MOUSE(0)
                PALETTE 30,.7,.2,.9
                FOR t = 1 TO 500 : NEXT t
                PALETTE 30,.3,.8,.1
                FOR t = 1 TO 500 : NEXT t
            WEND
 
            FOR loop% = 0 TO 31
                COLOR loop%,loop%+32
                LOCATE 20,1
                PRINT "TEST COLOUR ";loop%
                PRINT "Text Colour            - Original colour"
                PRINT "Background Colour      - Halfbrite colour"
                FOR t = 1 TO 500: NEXT t
            NEXT loop%
            CLS
            COLOR 1,0
 
 
                                PAGE 158
 
---------------------------------------------------------------------------
 
        endprog:   ' Halfbrite off and close screen. '
            HalfBriteOff
            WINDOW windo.nr%,windo.name$,,,-1
            SCREEN CLOSE screen.nr%
            PRINT "End of DEMO !"
            LIBRARY CLOSE
            END
 
        SUB HalfBriteOn STATIC
            SHARED screen.mode%
            SHARED screen.viewport&
 
            ' Define variables.
            MEM.CHIP    = 2^1
            MEM.CLEAR   = 2^16
            memory.option& = MEM.CHIP + MEM.CLEAR
            window.base&   = WINDOW(7)
            screen.base&   = PEEKL(window.base&+46)
            screen.bitmap& = screen.base&+184
            screen.viewport&=screen.base& + 44
            screen.rastport&=screen.base& + 84
            screen.width%   = PEEKW(screen.bitmap&)
            screen.height%  = PEEKW(screen.bitmap&+2)
            screen.size&    = screen.width%*screen.height%
            screen.depth%   = PEEK(screen.bitmap&+5)
            screen.mode%    = PEEKW(screen.viewport&+32)
 
            '* SCREEN already has 6 bitplanes ????
            IF screen.depth%>5  THEN screen.depth%=2^8
 
            '* add missing Bitplanes.
            FOR loop1% = screen.depth%+1 TO 6
                plane&(loop1%)   = AllocMem&(screen.size&,memory.options&)
                IF plane&(loop1%) = 0 THEN
                    FOR loop2% = screen.depth%+1 TO loop1%-1
                        CALL FreeMem(plane&(loop2%),screen.size&)
                    NEXT loop2%
                    ERROR 7
                END IF
                POKEL screen.bitmap&+4+4*loop1%,plane&(loop1%)
            NEXT loop1%
            POKE screen.bitmap&+5,6
 
            'Halfbrite on
            POKEW screen.viewport&+32,(screen.mode% OR 2^7)
            CALL RemakeDisplay
        END SUB
 
        SUB HalfBriteOff STATIC
            SHARED screen.mode%
            SHARED screen.viewport&
 
            'Reset Halfbrite Flag
            POKEW screen.viewport&+32,screen.mode%
            CALL RemakeDisplay
        END SUB
 
                                PAGE 159
 
-----------------------------------------------------------------------------
 
Working with the halfbrite program :
 
After you call the SUB "HalfBriteOn" you will have 64 different colours
available. You can freely define the first 32 colours using the BASIC 
PALETTE statement:
 
        PALETTE register, reg, green, blue
 
        register : 0,31
        red,green,blue : 0.0 - 1.0
 
Colours 32 to 63 are defined at the same time except they are half as 
bright.
 
With the COLOR statement you can select any colour from 0 TO 63, draw, 
print text and fill. But you should remember that for AmigaBASIC, the 
screen still only has five bit-planes. When BASIC scrolls the screen (when
you write text in the last row) only five planes will scroll; the sixth
plane stays in place. To avoid this problem do not print to the last screen
line.
 
When you no longer need the HalfBrite mode you can deactivate it by using
the SUB "HalfBriteOff".
 
At the beginning of this section we mentioned a problem involving changes 
to the HalfBrite flag in the ViewPort. Setting this flag does not do 
anything. It doesn't matter what type of manipulation you perform in the 
ViewPort, nothing is changed in the display. 
 
This happens because the display is only changed by the hardware registers.
Since ViewPort is a data block in RAM and not a hardware register, the 
display isn't changed. In order to affect the display. the information
in ViewPort about how the display is formed must first be sent to the 
Copper. This is because the Copper controls and programs the hardware.
 
We make ViewPort changes effective when we call the Intuition function
"RemakeDisplay". This function creates a new Copper list and reflects the 
change in the ViewPort structure. Finally, this list is sent to the 
Copper.
 
                                PAGE 160
 
-----------------------------------------------------------------------------
 
4.2.2 THE HOLD AND MODIFY MODE : 4096 COLOURS.
 
The Hold and Modify mode (abbr. HAM) is also not supported by AmigaBASIC.
You cannot access it by using the SCREEN statement.
 
We can activate this mode for a screen that already exists. Before we do 
this, let's take a look at the principles for using this mode.
 
When the HAM mode is active, you can display up to 4096 colours at the 
same time. If we follow the normal rules for displaying 4096 colours, we 
would require 12 bit-planes. This would require a large amount of memory 
(1 bit-plane = 64000 bytes in lo-res, 12 bit-planes = 768000 bytes!). Also
the Amiga's DMA (Direct Memory Access) is not fast enough to retrieve and 
build a new screen every 1/60th of a second from 12 different RAM areas. 
Obviously, we need a special procedure.
 
Actually, HAM works with only 6 bit-planes just as the halfbrite mode. The 
first 16 colours are the exact colours that were defined for the first 16
colour registers. All other colours are determined by the HAM principle.
They use the colour of the pixel to the left and modify the RGB value.
 
Before we undertake the complex arrangement of a HAM graphic, we need to 
activate the mode. This is very similar to the halfbrite mode. We create
a sixth bit-plane, add it to the bit-map and then set the HAM flag in the
ViewPort. A call to RemakeDisplay switches the display to HAM. Again, there
are two SUB programs, HAMon and HAMoff.
 
        '#####################################
        '#
        '# Section : 4.2.2
        '# Program : HAM activator.
        '# Date    : 02/16/87
        '# Author  : tob
        '# Version : 1.4
        '#
        '#######################################
        '
        ' Activates the Amiga special graphic mode "HAM" (Hold 
        ' And Modify) not normally availble to BASIC. Provides 
        ' up to 4096 colours at the same time (with 6
        'bit-planes. NOTE : only functions in lores mode.
 
        PRINT "Searching for .bmap file ..... "
 
                                PAGE 161
 
-----------------------------------------------------------------------------
 
        'EXEC-Library
        DECLARE FUNCTION AllocMem& LIBRARY
        'FreeMem
        'INTUITION-LIBRARY
        'RemakeDisplay()
        
        LIBRARY "intuition.library"
        LIBRARY "exec.library"
 
        main:
            loRes            = 1
            screen.nr%       = 1
            screen.x%        = 320
            screen.y%        = 200
            screen.depth%    = 5 '5 planes required'
            screen.resolution% = loRes
            SCREEN screen.nr%,screen.x%,screen.y%,screen.depth%,
screen.resolution%
 
            'Open a window in the new screen.
            windo.nr%          = 1
            windo.name$        = "HAM! 4096 colours available.!"
            WINDOW windo.nr%,windo.name$,,,screen.nr%
 
        demo: 'Activate HAM
            HAMon
 
            PRINT TAB(7);"256 of 4096 colours"
             
            s = 10                ' box size
            x = 40                ' Position of upper
            y = 20                ' left corner of demo.
            PALETTE 3,0,0,0       ' FRAME COLOUR.
            PALETTE 4,.5,0,.5     ' DARK PURPLE.
            PALETTE 5,1,0,1       ' LIGHT PURPLE.
            PALETTE 6,1,0,0       ' LIGHT RED.
            PALETTE 7,0,0,1       ' LIGHT BLUE.
 
            'SET ORIENTATION MARKS.
            LINE (5,y)-(5+8,y+8),4,bf
            LINE (240,y)-(240+8,y+8),7,bf
            LINE (5,166)-(5+8,166+8),6,bf
            LINE (240,166)-(240+8,166+8),5,bf
 
            ' DRAW FRAME.
            LINE (x-1,y-1)-(x+17*s+1,y+16*s+1),3,b
 
            ' Draw first 256 HAM colours.
            FOR loop% = 0 TO 15
                LINE (x,loop%*s+y)-(s+x,loop%*s+s+y),32+loop%,bf
                FOR loop2% = 0 TO 15
                    LINE (s+loop2%*s+x,loop%*s+y)-(2*s+loop2%*s+x,
loop%*s+s+y),loop2%+16,bf
                NEXT loop2%
            NEXT loop%
 
                                PAGE 162
 
-----------------------------------------------------------------------------
 
        '* Raise Green Level.
        FOR loop2% = 0 TO 15
            PALETTE 3,0,loop2%*(1/15),0
            LOCATE 10,28
            PRINT "Green Level: "
            PRINT TAB(31) loop2%
            FOR t = 1 TO 3000: NEXT t
        NEXT loop2%
 
        LOCATE 2,7
        PRINT "Please Press a Key ! "
        WHILE INKEY$ = "": WEND
 
        endprog:   ' HAM off and close screen. '
            HAMOff
            WINDOW windo.nr%,windo.name$,,,-1
            SCREEN CLOSE screen.nr%
            PRINT "End of DEMO !"
            LIBRARY CLOSE
            END
 
        SUB HAMOn STATIC
            SHARED screen.mode%
            SHARED screen.viewport&
 
            ' Define variables.
            MEM.CHIP    = 2^1
            MEM.CLEAR   = 2^16
            memory.option& = MEM.CHIP + MEM.CLEAR
            window.base&   = WINDOW(7)
            screen.base&   = PEEKL(window.base&+46)
            screen.bitmap& = screen.base&+184
            screen.viewport&=screen.base& + 44
            screen.rastport&=screen.base& + 84
            screen.width%   = PEEKW(screen.bitmap&)
            screen.height%  = PEEKW(screen.bitmap&+2)
            screen.size&    = screen.width%*screen.height%
            screen.depth%   = PEEK(screen.bitmap&+5)
            screen.mode%    = PEEKW(screen.viewport&+32)
 
            '* SCREEN already has 6 bitplanes ????
            IF screen.depth%>5  THEN screen.depth%=2^8
 
            '* add missing Bitplanes.
            FOR loop1% = screen.depth%+1 TO 6
                plane&(loop1%)   = AllocMem&(screen.size&,memory.options&)
                IF plane&(loop1%) = 0 THEN
                    FOR loop2% = screen.depth%+1 TO loop1%-1
                        CALL FreeMem(plane&(loop2%),screen.size&)
                    NEXT loop2%
                    ERROR 7
                END IF
                POKEL screen.bitmap&+4+4*loop1%,plane&(loop1%)
 
                                page 163
 
-----------------------------------------------------------------------------

            NEXT loop1%
            POKE screen.bitmap&+5,6
 
            'HAM on
            POKEW screen.viewport&+32,(screen.mode% OR 2^11)
            CALL RemakeDisplay
        END SUB
 
        SUB HAMOff STATIC
            SHARED screen.mode%
            SHARED screen.viewport&
 
            'Reset HAM Flag
            POKEW screen.viewport&+32,screen.mode%
            CALL RemakeDisplay
        END SUB
 
 
After you start this program you will see a field of 256 colours that were
created by using only red and blue. In the top left hand corner is a dark
purple colour and in the lower right hand corner, a light purple colour.
Light red is in the lower left hand corner and light blue is in the upper
right hand corner.
 
Now we blend a green slowly and evenly with other colours to display all 
4096.
 
This mass of colours looks very impressive but programming them is not easy.
But, as you will see, it is not too complicated.
 
First, lets define the difference between real colours and HAM colours. Real
colors, the colours 0-15, actually display the values in colour registers
0-15. These colours are permanent and can only be changed with the 
PALETTE statement. The HAM colours, 16-63 are different because they are 
always affected by their neighbouring colour to the left. A HAM colour takes
the colour of the pixel to the left and modifies the RGB components. Which
of the three components that is changed depends on the HAM colour itself.
 
        Color 0           - 15         Real Colour.
        Color 16+0        - 16+15      HAM type 1.
        Color 32+0        - 32+15      HAM type 2.
        Color 48+0        - 48+15      HAM type 3.
 
HAM colour type 1 takes the neighbouring colour and changes the blue 
component. The blue component of the HAM colour corresponds to a value 
higher than 16. The HAM colour 16+12=28 uses the neighbouring colour
and makes a value of 12 for blue.
 
                                PAGE 164
 
-----------------------------------------------------------------------------
 
HAM colour type 2 takes the nieghbouring colour and modifies the red 
component. The HAM colour 32+8 = 40 takes the nighbouring colour and makes
a value of 8 in the red component.
 
HAM colour type 3 performs exactly the same function for colours 48 and up,
changing the green component.
 
In our example program we created a black frame making red, green and 
blue = 0. Directly to the right of the frame we drew with a HAM colour
of type 2. This colour checks the pixel colour to the left, the black 
frame and uses the same color. Reg,Green and Blue are still zero. The Blue
field is set by the HAM colour itself. This blue value increases in a loop
that changes every screen row.
 
Directly to the right of this HAM colour we drew 16 HAM colours of type 1.
These add in a red value of one.
 
This creates the colourpattern. The red intensity increases to the right
and the blue intensity increases downward.
 
Now we change the colour of the frme by making the previously black frame 
greener with the PALETTE command. The green value of the frame passes 
immediately to the HAM colours. The entire colour graphic effect results
from an increasing green intensity.
 
                                PAGE 165 

-----------------------------------------------------------------------------
 
4.3 THE VIEWPORT IN THE SYSTEM.
 
We now have a clearer picture of the amiga system. You shouldbe familiar 
with two components; the bit-map and the ViewPort. Both are easily 
illustrated.                
                        	
					__________________________
				       |                          |
			               |          BitMap          |   
				       |                          |
                                       |_____________|_|_|_|_|_|__|
		 ______________           |   |      | | | | | | bitplanes
		|              | _________|   |                  (max 8)
		| bitplane 1   |              |         
                |______________|              |   
                                              |  
 	         ______________		      |  
		|              | _____________|  
                | bitplane 2   |
                |______________|                        next viewport
                
					_____________________|____
				       |                     |    |
				       |     ViewPort             |
				   ----|			  |-----
		          Color map    |__________________________|Rasinfo


 
Now the system connection with these components.
 

		__|_____________
               |                | 
               |  Screen        |<----------------
	    ___|                |                 |  
           |   |                |------           |
           |   |________________|      |          |
           |       |    |   ____       |          |
           |       |    |__|    |   ___|__________|__|__
           |       |     __|R P |  |                 |  |
           |       |__  |  |____|  |   Window          -|---
           |          | |          |_________________|__|
           |          | |              |             |
     ______|____|__   | |              |
    |           |  |  | |              |
    | ViewPort     |  | |              |
 ---|              |- | |              |
    |______________|  | |              |
                      | |              |
		______|_|_____      ___|___
	       |              |    |       |
               |  BitMap      | <--| R P   |
	       |______________|    |_______|

 
                                PAGE 166
 
-----------------------------------------------------------------------------
 
The most elemental part if a display, the ViewPort, is controlled by 
Intuition with the help of a screen. The screen and window are displayed
through a private RastPort in a shared video RAM, the bit-planes.
 
We still hane not explained the Layer, Colormap and RasInfo components. 
 
Before we continue our study of the graphics system, we have one more point
to discuss. There is an additional data structure called VIEW that seems to 
appear out of nowhere. 
 
                                PAGE 167
        
-----------------------------------------------------------------------------

4.4 VIEW: THE GRAPHIC BRAIN.
 
It is not surprising that the address of View, or even it's name has not
appeared yet. View is the contact point between the graphic software and
the graphic hardware of the Amiga. It is where everything begins. You can 
obtain the address of View by calling an Intuition function name 
ViewAddress. 
 
        DECLARE FUNCTION ViewAddress& LIBRARY
        LIBRARY "intuition.library"
 
        view& = ViewAddress&
 
NOTE : Remember that the Intuition routine ViewPortAddress provides you 
with the address of the ViewPort where your actual output window is 
located:        
        
        DECLARE FUNTION ViewPortAddress& LIBRARY
        LIBRARY "intuition.library"
        
        vp& = ViewPortAddress&(WINDOW(7))
 
Here is the View data structure :
 
Data structure : View/graphics/18 bytes.
 
Offset  Type    Description
------- ------- -------------------------------------------------
+000    Long    Pointer to the first ViewPort.
+004    Long    LongFrame Copper List.
+008    Long    ShortFrame Copper List.
+012    Word    DyOffset
+014    Word    DxOffset
+016    Word    Mode
 
Although View doesn't seem like an essential part of the graphics system,
the entire display (including all screens) is dependant on it. A detailed
description of the data fields follows :
 
OFFSET 0 : NEXT VIEWPORT
 
This offset contains the address pointer to the first ViewPort structure
of the display. From that structure you can obtain the addresses of further
ViewPorts, if there are any.
        
                                PAGE 168
        
---------------------------------------------------------------------------
 
OFFSET 4 AND 8 : COPPER LISTS.
 
We have dealt with Copper lists before when discussing the ViewPorts. Just 
as the Copper list of the ViewPorts is responsible for the drawing region
of the ViewPort, the Copper list controls the entire display (or in other
words ; all the ViewPorts). A normal display requires only the LongFrame
list. The second Copper list is only necessary when using the Interlace
mode.
 
The rest of the fields are self explanatory since they have exactly the 
same funtions as the same name fields in the ViewPort.
 
Now that we've added View to our explanation of the graphics system, we
have covered the most important components. The connection between 
hardware and intuition is complete.
 

		__|_____________
               |                | 
               |  Screen        |<----------------
	    ___|                |                 |  
           |   |                |------           |
           |   |________________|      |          |
           |       |    |   ____       |          |
           |       |    |__|    |   ___|__________|__|__
           |       |     __|R P |  |                 |  |
           |       |__  |  |____|  |   Window          -|---
           |          | |          |_________________|__|
           |          | |              |             |
     ______|____|__   | |              |
    |           |  |  | |              |
    | ViewPort     |  | |              |
 ---|              |- | |              |
    |______________|  | |              |
       |              | |              |
  _____|____	______|_|_____      ___|___
 |          |  |              |    |       |
 |  View    |  |  BitMap      | <--| R P   |
 |__________|  |______________|    |_______|
       |         | | | | | |         |
       |			     |
  _____|_______________		     |
 | Instructions Copper |	     |
 |_____________________|	     |
       | 			     |
 ______|_____________________________|____
|__________________			  |
|		   |			  |
|    COPPER        |----> Blitter         |
|		   |      other special   |
|		   |----> CoProcessors    |
|__________________|______________________| 
 
                                PAGE 169
 
-----------------------------------------------------------------------------
 
Before we continue with the graphic system, we need to test our model of
the system. Since we have now advanced far enough, we can create our
own display. There are several functions from the graphic libraries that
we need.
 
        InitView()
        InitVPort()
        GetColorMap()
        InitBitMap()
        AllocRaster()
        LoadRGB4()
        MakeVPort()
        MrgCop()
        LoadView()
        FreeRaster()
        FreeColorMap()
        FreeVPortCopLists()
        FreeCprList()
 
In the following program we are going to demostrate all the steps required
to create a simple display using a ViewPort. Use our program as a model 
that shows the correct programming methods. Since copper programming is the
subject of the next chapter this program is a good practising excercise.
        
        
        '################################################
        '# 
        '# Section : 4.4
        '# Program : Graphic Primitive Display.
        '# Date    : 01/01/87
        '# Author  : tob
        '# Version : 1.0
        '#
        '#################################################
        
        'Demonstrates the creation of a graphiv display on the Amiga
        'using the "graphic primitives", the base commands of the 
        'Graphic Library. This screen is Hires with one bitplane.        
        'The contents of the first bit-plane of this screen is copied
        'to the new display.
        
        PRINT "Searching for .bmap file .... "
        
        'GRAPHICS library
        DECLARE FUNCTION AllocRaster& LIBRARY
        DECLARE FUNCTION GetColorMap& LIBRARY
        
        
                                PAGE 170
 
-----------------------------------------------------------------------------
 
        'FreeRaster()
        'FreeColorMap()
        'FreeVPortCopLists()
        'FreeCprList()
        'InitView()
        'InitVPort()
        'InitBitMap()
        'LoadRGB4()
        'MakeVPort()
        'MrgCop()
        'LoadView()
        
        'EXEC library
        DECLARE FUNCTION AllocMem& LIBRARY
        'FreeMem()
        
        'INTUITION library
        DECLARE FUNCTION ViewAddress& LIBRARY
         
        LIBRARY "exec.library"
        LIBRARY "graphic.library"
        LIBRARY "intuition.library"
 
        init:  'Define screen parameters.
            wide% = 640
            height% = 200
            depth%  = 1
            o.bitplane1& = PEEKL(PEEKL(WINDOW(8)+4)+8)
        
            'Store our view pointer to enable us to 
            'return to it later.
            oldview& = ViewAddress&
 
            'Reserve memory for required structures.
            ' View - Brain of Displays.
            view&    = 18
            GetMemory view&
        
            ' ViewPort - Our Screen.
            viewport& = 40
            GetMemory viewport&
        
            ' BitMap - Manager of bit-planes.
            bitmap&   = 40
            GetMemory bitmap&
        
            ' RasInfo - Information about the ViewPort.
            RasInfo&  = 12
            GetMemory RasInfo&
 
            'Prepare View and ViewPort for use.
            CALL InitView(view&)
            CALL InitVPort(viewport&)
 
            'Hi-res.
            hires& = &H8000
            POKEW viewport&+32+hires&
 
            'Place ViewPort is View.
            POKEL view&,viewport&
 
                                PAGE 171
 
-----------------------------------------------------------------------------
       
            'Setup Color Table.
            colroMap& = GetColorMap&(2)
            If colorMap& = 0 THEN RETURN
                        
            'Fill ViewPort with our Parameters.
            POKEW viewport&+24,wide%
            POKEW viewport&+26,height%
        
            'Place RasInfo in ViewPort
            POKEL viewport&+36,RasInfo&
            
            'Place color table in the ViewPort.
            POKEL viewport&+4,colorMap&
        
            'Fill bitmap structure with our Parameters.
            CALL InitBitMap(bitmap&,depth%,wide%,height%)
            
            'Get a bitplane.
            plane&   = AllocRaster&(wide%,height%)
            IF plane& = 0 THEN ERROR 7
        
            'Place bitplane in Bitmap.
            POKEL bitmap&+8,plane&
        
            'Place bitmap in RasInfo
            POKEL RasInfo&+4,bitmap&
        
            'Define colours.
            red$         = CHR$(15)+CHR$(0)
            black$       = CHR$(0) +CHR$(0)
            colortable$  = red$ + black$
        
            'Load colours into colour table.
            CALL LoadRGB4(viewport&,SADD(colortable$),2)
        
            'Constuct Copper instruction List.
            CALL MakeVPort(view&,viewport&)
            CALL MrCop(view&)
        
            ' Load new display into copper.
            CALL LoadView(view&)
            
            'Play with the Display
            BEEP
            size& = wide% * height% / 8
        
            FOR loop& = 0 TO size&-1
                POKE plane&+loop&,PEEK(o.bitplane1&+loop&)
            NEXT loop&
            BEEP
            
            'Restore Old Copper List.
            CALL LoadView(oldview&)
            
                                PAGE 172
        
-----------------------------------------------------------------------------
        
            'Cleanup: Return Memory for bit plane.
            CALL FreeRaster(plane&,wide%,height%)
            ' Release Color Table
            CALL FreeColorMap(colormap&)
            ' Release Interim ViewPort lists.
            CALL FreeVPortCopLists(viewport&)
            ' Release Copper Instruction List.
            copperlist& = PEEKL(view&+4)
            CALL FreeCprList(copperlist&)
            
            ' Release Structure Memory.
            FreeMemory view&
            FreeMemory viewport&
            FreeMemory RasInfo&
            FreeMemory bitmap&
        
            ' AND THAT'S  IT ...
            LIBRARY CLOSE
            END
            
        SUB GetMemory(size&) STATIC
            opt&         = 2^0+2^1+2^16
            RealSize&    = size& + 4
            size&        = AllocMem&(RealSize&, opt&)
            IF size&     = 0 THEN ERROR 255
            POKEL size&,RealSize&
            size& = size&+4
        END SUB
        
        SUB FreeMemory(add&) STATIC
            add&       = add&-4
            RealSize& = PEEKL(add&)
            CALL FreeMem(add&,RealSize&)
        END SUB
        
        
THE PROGRAM.
------------
 
The first step in our program is to choose what kind of display we want
to create (how wide and how high). Our choice is a high-res screen with 
a standard resolution of 640*200 pixels and a depth of one bitplane.
        
To be able to return to our original display we must store the addresses
of our structure in several variables. The intuition function 
ViewAddress provides the requierd pointers.
        
To create our display we use the following structures:
        
        View (18 bytes)
        ViewPort (40 bytes)
        BitMap (40 bytes)
        RasInfo (12 bytes)
        
The View structure forms the brain of our future display. There is only
one active view and from this view you can have any number of ViewPort
branches.
                                
                                PAGE 173
        
-----------------------------------------------------------------------------
        
View and ViewPort must be created ready to use. InitView fills the View
structure with the standard values, which automatically sets the View
structure to appear about a half inch from the edge of the screen. 
InitVPort does the same thing with the ViewPort. It is normally set for
lo-res and the pointer for the next ViewPort is set to zero because
usually there are no additional ViewPorts.
        
Now we have to make a connection between View and ViewPort. To do this, we
use the first field of the View structure to store the address of the first
(and only) ViewPort structure.
        
Next we must have a colour table that will later be used by our screen.
GetColorMap will take care of this. 
        
Then we store the resolution for our ViewPort and the RasInfo block is 
placed in the ViewPort. Now we make the Bit-Map structure ready for use
by using InitBitMap(). We write the address of our bitplane into the
Bit-map structure.
        
Next we write the address of the Bitmap into the RasInfo structure. Then
we use LoadRGB4 to store the colours to the ViewPort.
        
Now that all the required data has been stored, our display is ready to
use. The Amiga creates the instructions for the graphic processor from
our information with the following steps : 1.) the function MakeVPort
creates the Copper list from the data in the viewports and writes the 
pointer for this list into the ViewPort, and 2.) the function MrgCop 
integrates the instructions of our ViewPort with those of all the displays
(we have only one ViewPort).
        
The completed Copper list is stored in View. A list of copper commands has
been created from the data and will be used for our display. We just have 
to send the commands to the copper and our new display will appear. This 
action is performed by LoadView and immediately we see our bright red
display.        
        
To show you that this is a fully functional display, we copy the first 
bit-plane of the workbench screen to it. This takes a few moments.
        
Everything worked, but now we want to get back to the original display. 
Since we stored the address for our old View, we shouldn't have any 
problems. We can use LoadView to send the old copper lists to the Copper
and return to the original.        
        
Althouh the demonstration is over, we still need to "cleanup" because
the display has used up a lot of memory that we will want to release again.
                        
                                PAGE 174
        
----------------------------------------------------------------------------
        
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
        
-----------------------------------------------------------------------------
        
4.6 THE LAYERS: SOUL OF THE WINDOWS.
        
We will continue building our picture of the graphics system. In the
RastPort structure there is a pointer to the LAYERS. Layers refer to the
independant system components of the operating system that are controlled
through the layer libraries.
        
To discover what layers are, take a look at your Amiga monitor. You 
probably cannot see the layers because of all the windows. Actually, every
window is a layer.
        
Just as the screen is simply another ViewPort, a window is just another
layer. A layer handles most of the work required to create windows. One 
problem which always occurs when a computer works with windows is that
everything you see on screen, including the screen background and windows,
is stored in the bit-planes of the bitmap. An ideal exampl of this problem
is a display that contains the screen background and many window fragments.
These windows can overlap, can be covered completely by others or can be
displayed by themselves. As soon as one window overlaps another, this must
be recorded because the overlapped portion consists of two windows divided
within the same bit-map. The layers ensure that the covered window section
is saved to another area of memory. Whenever the covered window, (or a 
portion of it) becomes visible again, the layers copy the uncovered piece
back into the screen bitmap.
        
Before we discuss this theory in more detail we are going to trap and 
display a layer for you. The following small program performs this
operation.
        
        
        '##########################################
        '#
        '# Section: 4.6
        '# Program: A layer.
        '# Date   : 01/05/87
        '# Author : tob
        '# Version: 1.0
        '#
        '###########################################
        
        ' A simple layer - the basis of every window is 
        ' generated.
        
        PRINT "Searching for .bmap files.............."
        
                                PAGE 188
        
-----------------------------------------------------------------------------
        
        'LAYERS-library
        DECLARE FUNCTION CreateUpFrontLayer& LIBRARY
        'DeleteLayer()
        'MoveLayer()
        
        'GRAPHICS-library
        'Text()
        'Move()
        
        LIBRARY "graphics.library"
        LIBRARY "layers.library"
        
        initpars:            
            CLS
            scrAdd&               = PEEKL(WINDOW(7)+46)
            screenLayerInfo&       = scrAdd&+224
            screenBitMap&         = scrAdd&+184
            x0%                   = 10
            y0%                   = 20
            x1%                   = 400
            y1%                   = 80
            typ%                   = 1
        
        thatYou:     'can also see it
            CLS
            LINE (1,1)-(600,180),2,bf
            
        LayerHer:
            layer& = CreateUpFrontLayer(screenLayerInfo&,screenBitMap&,
 x0%,y0%,x1%,y1%,typ%,0)
        
        whatToDo:
            layerRast& = PEEKL(layer&+12)
            text$ = "This is the soul of a window: A Layer!"
            CALL Move(layerRast&,3,8)
            CALL Text(layerRast&,SADD(text$),LEN(text$))
        
        moveit:        
            dx%   = 2
            dy%   = 1
            FOR loop1% = 1 TO 30
                CALL MoveLayer(screenLayerInfo&,layer&,dx%,dy%)
            NEXT loop1%
        
        wiatlp:
            LOCATE 1,1
            5
            PRINT "Press any key to End"
            WHILE in$= ""
                in$ = INKEY$
            WEND
        
        removeIt:
            CALL DeleteLayer(screenLayerInfo&, layer&)
            
        thatsIt:
            LIBRARY CLOSE
            END
        
                                PAGE 189
        
-----------------------------------------------------------------------------
        
As you can see, our small layer acts much like a large window. When you 
move the mouse pointer over the layer and click the left mouse button, the
layer is activated and the window ripples. In order for the layer to be 
a complete window, it would need the frame, the gadgets and a menu.
        
When you press a key the layer completely dissappears.
        
To create the above program, we used functions from both the graphic and
layers libraries. However, the layers library is more important in this
application. The layers function, CreateUpFrontLayer, which generates our
layer, requires eight arguments and returns the start address of the layer
block to the BASIC program.
        
        layer&=CreateUpFrontLayer&(layerInfo&,bitmap&,x0%,y0%,x1%,y1%,
   typ%,sbitmap&)
        
        layer&     : The address of our new layer data block.
        layerInfo& : The address of the structure LayerInfo.
        bitmap&    : The address of the bit-map where the new layer is
                     to be produced.
        x0%,y0%    : Coordinates of the upper left hand corner of the 
                     layer.
        x1%,y1%    : Coordinates of the lower right hand corner.
        
The LayerInfo structure address and the bitmap structure address are found
in our well known screen structure (Section 3.6). By using the functions
text and move from the graphic library (see section 3.6.1), we can display
text through this RastPort.        
        
After studying the layer we close the layer again by using DeleteLayer.
        
Now we can take a look at the Layer's data structure. Just like every 
window, the layers also have this structure. It is constructed like 
this :
        
                                PAGE 190
        
-----------------------------------------------------------------------------
        
Data Structure/Layer/layers/192 bytes.
        
Offset  Type    Description.
------- ------- -------------------------------------------------------
+000    Long    Pointer to layer in foreground.
+004    Long    Pointer to layer in Background.
+008    Long    Pointer to first ClipRect.
+012    Long    Pointer to the first rastport of this layer.
+016     --     Rectangle structure, the limits of the layer.
                +016   Word   MinX
                +018   Word   MinY
                +020   Word   MaxX
                +022   Word   MaxY
+024    Byte    Lock
+025    Byte    LockCount
+026    Byte    LayerLockCount
+027    Byte    Reserved.
+028    Word    Reserved
+030    Word    Layer Flags.
+032    Long    Pointer to superbitmap, when available.
+036    Long    SuperClipRect
+040    Long    Pointer to Window
+044    Word    ScrollX
+046    Word    ScrollY
+048     --     Message Port "Lock Port"
+082     --     Message "LockMessage"
+102     --     Message Port "ReplyPort"
+136     --     Message " 1 LockMessage"
+156    Long    Pointer to first rectangle of DamageList
+160    Long    Pointer to ClipRects
+164    Long    Pointer to LayerInfo structure
+168    Long    Pointer to Task with actual lock
+172    Long    Pointer to SuperSaveClipRects
+176    Long    Pointer to CR ClipRects
+180    Long    Pointer to CR2 CLipRects
+184    Long    Pointer to CRNEW ClipRects
+188    Long    System use.
        
                --------------------------------------------
        
4.6.1 THE LAYER DATA STRUCTURE.
        
The data structure we just introduced requires further explanation.
We will examine it field by field with the same format we have been using.
        
To obtain the starting address for the layer of your actual output window
use the following:
        
                                PAGE 191
        
-----------------------------------------------------------------------------
        
        layer& = PEEKL(WINDOW(8))
        
The startin address of the layer data structure you have created is 
automatically returned by the appropriate layer functions. Later we will
come back to this subject.
        
OFFSET 0 AND 4: POINTER TO OTHER LAYERS.
        
This pointer contains the startin address of the layer data block for a 
layer that is behind or in front of your layer. The same relationship
applies to layers as to windows; you can move from one layer to all other
layers in the system.
        
OFFSET 8: FIRST CLIPRECT
        
ClipRect is another data structure which ddescribes a current rectangular
pic of a layer. This pointer is to the first ClipRect structure of this 
layer, from which you can obtain the next and the following ClipRect
address. This chain of ClipRects describes the visible portion of this
layer.
        
OFFSET 12: THE RASTPORT
        
This offset contains the starting address of the RastPort for this layer.
Most functions of the graphic library require the RastPort address with 
which they will be working.
        
Since every Intuition window has a layer, it also has its own Layer 
RastPort. This RastPort is identical with the RastPort of the window data
structure:
        
        RastPort1& = PEEKL(WINDOW(7)+50)
        RastPort2& = WINDOW(8)
        layer& = PEEKL(WINDOW(8))
        RastPort3& = PEEKL(layer&+12)
        PRINT RastPort1&
        PRINT RastPort2&
        PRINT RastPort3&
        
The starting addresses returned for the RastPorts are the same.
        
        
OFFSET 16, 18, 20, and 22: BOUNDS
        
The X and Y values stored here set the layer limits. Any drawing function
that uses coordinates is clipped off if it passes outside there boundaries.
Let's first determine the limits of our own layers:
        
        windo& = WINDOW(7)
        RastPort& = WINDOW(8)
        layer& = PEEKL(RastPort&)
        
        
                                PAGE 192
        
-----------------------------------------------------------------------------
        
        x0% = PEEKW(layer&+16)
        y0% = PEEKW(layer&+18)
        x1% = PEEKW(layer&+20)
        y1% = PEEKW(layer&+22)
        
        PRINT x0%,y0%
        PRINT x1%,y1%
        
        END
        
The result is the coordinates of the upper left hand and the lower right
hand corners of our drawing plane.
        
Naturally, you could use this method to define your own drawing plane.
Everything outside of this area would be clipped off.
        
        REM 4.6.1 Offsets 16-22 Example B
        
        PRINT "Searching for .bmap file..."
        
        init:
            '* Address of the data structures
            CLS
            windo&    = WINDOW(7)
            RastPort& = WINDOW(8)
            layer&    = PEEKL(RastPort&)
        
            '* Current Valid Limits.
            x0%       = PEEKW(layer&+16)
            y0%       = PEEKW(layer&+18)
            x1%       = PEEKW(layer&+20)
            y1%       = PEEKW(layer&+22)
        
            scrWidth% = x1% - x0%
            scrHeight% = y1% - y0%
            
            main: '* DEMO
            LINE (x0%,y0%)-(x1%,y1%),2,bf
            
            'Set new limits.
            nx0% = x0% + .25*scrWidth%
            nx1% = x1% - .25*scrWidth%
            ny0% = y0% + .25*scrHeight%
            ny1% = y1% - .25*scrHeight%
            
            POKEW layer&+16,nx0%
            POKEW layer&+18,ny0%
            POKEW layer&+20,nx1%
            POKEW layer&+22,ny1%
            
            ' It look like This:
            FOR test% = 0 TO 40
                PRINT STRING$(50,"*")
            NEXT test%
            
            CLS
            
                                PAGE 193
        
-----------------------------------------------------------------------------
        
            PRINT "Enter CONT!"
        
            STOP
            
            '* Restore original limits.
            POKEW layer&+16,x0%
            POKEW layer&+18,y0%
            POKEW layer&+20,x1%
            POKEW layer&+22,y1%
        END
        
OFFSET 24,25 AND 26: LOCK FIELDS.
        
The Amiga is a multi-tasking computer, which means that many programs can 
be running at the same time. So, it is possible for several programs to 
to attempt to access the same layer at the same time. These conflicting
access attempts would cause the program to abort. To prevent this from 
happening there are the layer functions, LockLayer and UnLockLayer. Through
these functions the tasks have unlimited access to the layers. As long as 
a task utilises Lock, another task cannot change the contents of the 
layer data structure.
        
These fields control the lock technique. The first field determines whether
this layer is currently locked. The second is a counter for the program 
that is now using the layer. The third is a counter that keeps track of
other tasks attempting access to the layer.
        
        
OFFSET 30: FLAGS.
        
There are various layer types that we will discuss shortly. This field
contains an identity flag for this layer:
        
        Bit 0 : 1 = LayerSimple
        Bit 1 : 1 = LayerSmart
        Bit 2 : 1 = Layersuper
        Bit 6 : 1 = Layerbackdrop
        Bit 7 : 1 = Layerrefresh
        
        
OFFSET 32 : SUPERBITMAP
        
A layer has its own drawing plane and bitmap when it is in the layersuper
mode. The pointer to these is stored in this offset. We will explain this
in detail later.
        
        
OFFSET 36: SUPERCLIPRECT
        
When they are used, the ClipRects for the superbitmap are here (see offset 
8.)
        
                                PAGE 194
        
-----------------------------------------------------------------------------
        
OFFSET 40: WINDOW
        
Normally layers are linked with Intuition windows. When this happens,
this pointer contains the address of the corresponding window data 
structure.
        
This field is extremely important when you wnat to integrate layers with 
existing windows. We are going to cover this in more detail shortly.
        
        
OFFSET 44 AND 46 : SCOLLING
        
The referenced drawing line for a layer of type layersuper can be much
larger than the layer limit parameters. You can then use the layer like
a peephole that moves around a giant graphic. More on this later.
        
        
OFFSETS 48 - 136 : MESSAGES AND MESSAGE PORTS.
        
Messages and message ports are handled by the EXEC.library. Different 
tasks can communicate with each other through the message and message 
ports, which are similar to a mailbox and transmitter. Messages are their
letters. The reply port is the mailbox and the other message port sends the
message.
        
        
OFFSET 156: DAMAGE LIST
        
We mentioned before that layers are responsible for restoring covered 
portions of windows once they are no longer covered. Because of this, we
have a damage list which consists of a chain of data structures called
"regions".  These regions represent the rectangular portions of a layer.
The damage list contains all the damaged portions of its own window
(or layer) that is overlapped by other windows (or layers).
        
The remaining offset fields contain system information that BASIC cannot
use.
        
                                PAGE 195
        
-----------------------------------------------------------------------------
			    Now load part 3.
-----------------------------------------------------------------------------

