@DATABASE HowToCode7
@NODE MAIN "HowToCode: AGA Chipset"
@toc howtocode:howtocode/MAIN

                The AGA Chipset (Amiga 1200/4000)
                ---------------------------------

**** WARNING ****

AGA Registers are temporary. They will change. Do not rely
on this documentation. No programs written with this information
can be officially endorsed or supported by Commodore. If this
bothers you then stop reading now.

Future Amigas will *NOT* support *ANY* of the new AGA registers.
If you want your product to work on the next generation
of Amigas then either:

a) Program for ECS only (*MOST* ECS will be supported. Don't rely
on Productivity or SuperHires mode via hardware though!)

b) Program your displays via the OS, either using graphics.library
(views) or intuition.library (screens). If you use the OS then any
UserCopperList code you add must *ONLY* be for ECS level instructions
or lower (so, sorry, no 24-bit rainbows).

I have decided to include this material as there are still reasons
for people to program AGA hardware, especially demo coders. PLEASE
do not let me down by using this information to write commercial
software. If this happens I will have to remove the AGA docs from
HowToCode.

And as soon as Commodore provide a suitable way for all programmers
to access the power of the A1200/4000 chipset in a supportable
way, this file will be removed and replaced with one that
tells you how to code properly. But in the meantime......

  1 @{" How do I tell what chipset I am using? " link whatchips}
  2 @{" Programming the AGA hardware " link agahardware}
  3 @{" Monitor type problems " link monitorproblems}
  4 @{" Resetting sprites on AGA machines " link resetsprites}


@endnode

@node whatchips "How do I tell what chipset I am using?

How do I tell what chipset I am using?
--------------------------------------

Do *NOT* check library revision numbers, V39 OS can and does
run on standard & ECS chipset machines (My Amiga 3000
is currently running V39).

This code is a much better check for AGA than in howtocode4!!!!!


GFXB_AA_ALICE   equ 2
gb_ChipRevBits0 equ $ec

; Call with a6 containing GfxBase from opened graphics.library

   btst  #GFXB_AA_ALICE,gb_ChipRevBits0(a6)
   bne.s is_aa

This will not work unless the V39 SetPatch command has been
executed. If you *must* use trackloader demos then
execute the graphics.library function

   @{" SetChipRev(chipset) " link setchiprev}


This is a V39 function (No Kickstart 3.0? Then you haven't got
AGA!).

You can set the chipset you require with the following parameters:

   Normal = $00
   ECS    = $03       (Only on ECS or higher)
   AGA    = $0f       (Only on AGA chipset machines)
   Best   = $ffffffff (This gives best possible on machine)


This is called in the system by SetPatch.

The code in howtocode4 also had major problems when being
run on non ECS machines (without Super Denise or Lisa), as the
register was undefined under the original (A) chipset, and
would return garbage, sometimes triggering a false AGA-present
response.

@endnode

@node agahardware "Programming the AGA hardware"

Programming AGA hardware
------------------------

  1 @{" Bitplanes " link bitplanes}
  2 @{" Colours " link colours}
  3 @{" Sprites " link sprites}
  4 @{" Alignment Restrictions " link alignment}
  5 @{" The Magic FMode Register " link fmode}
  6 @{" Fetch Modes Required for Displays [table] " link fetchmode}
  7 @{" Smoother hardware scrolling " link scrolling}
  8 @{" Ham-8 Mode " link ham8}

@endnode

@node bitplanes "Bitplanes:"

Bitplanes:
---------

Set bits 0 to 7 bitplanes as before in BPLCON0 (for 0 to 7 bitplanes)

For 8 bitplanes you should set bit 4 (BPU3) of BPLCON0
bits 12 to 14 (BPU0 to BPU2) should be zero.

Using 64-colour mode (NOT extra halfbrite) requires setting the
KILLEHB (bit 9) in BPLCON2.

Super Hires can be enabled by bit 6 (SHRES) of BPLCON0

@endnode

@node colours "Colour Registers:"

Colour Registers
----------------

There are now 256 24-bit colour registers, all accessed through the original
32 12-bit colour registers. If you suspect this sounds like it could
be messy, then you're right, it is!

AGA works with 8 differents palettes of 32 colors each, re-using
colour registers from COLOR00 to COLOR31

You can choose the palette you want to access via bits 13 to 15 of
register BPLCON3.

BANK2    BANK1    BANK0
bit 15 | bit 14 | bit 13 | Selected palette
-------+--------+--------+------------------------------
   0   |    0   |    0   | Palette 0 (color 0 to 31)
   0   |    0   |    1   | Palette 1 (color 32 to 63)
   0   |    1   |    0   | Palette 2 (color 64 to 95)
   0   |    1   |    1   | Palette 3 (color 96 to 127)
   1   |    0   |    0   | Palette 4 (color 128 to 159)
   1   |    0   |    1   | Palette 5 (color 160 to 191)
   1   |    1   |    0   | Palette 6 (color 192 to 223)
   1   |    1   |    1   | Palette 7 (color 224 to 255)

To move a 24-bit colour value into a colour register requires
two writes to the register:

First clear bit 9 (LOCT) of BPLCON3
Move high nibbles of each colour component to colour registers

Then set bit 9 (LOCT) of BPLCON3
Move low nibbles of each colour components to colour registers

For example, to change colour zero to the colour $123456

   lea      (CUSTOM.L),a0
   move.w   #$0135,COLOR00(a0)
   move.w   #$0200,BPLCON3(a0)
   move.w   #$0245,COLOR00(a0)
   move.w   #$0000,BPLCON3(a0)

@endnode

@node sprites "AGA Sprites"

Sprites
-------

To  change  the  resolution  of the sprite, just use bit 7 and 6 of
register BPLCON3

bit 7 | bit 6 | Resolution
------+-------+-----------
  0   |   0   | ECS Defaults      (Lo-res/Hi-res = 140ns, Superhires = 70ns)
  0   |   1   | Always lowres     (140ns)
  0   |   1   | Always hireres    (70ns)
  1   |   1   | Always superhires (35ns)
--------------------------

For 32-bit and 64-bit wide sprites use bit 3 and 2 of register FMODE
($dff1fc) Sprite format (in particular the control words) vary for each
width.

bit 3 | bit 2 | Wide        | Control Words
------+-------+-------------+----------------------------------
  0   |   0   | 16 pixels   | 2 words (normal)
  1   |   0   | 32 pixels   | 2 longwords
  0   |   1   | 32 pixels   | 2 longwords
  1   |   1   | 64 pixels   | 2 double long words (4 longwords)
---------------------------------------------------------------
Wider sprites are not available under all conditions.


It  is possible to choose the color palette of the sprite.
This is done with bits 0 to 3 (even) and 4 to 7 (odd)
of register $010C.

bit 3 | bit 2 | bit 1 | bit 0 | Even sprites
bit 7 | bit 6 | bit 5 | bit 4 | Odd Sprites
------+-------+-------+-------+------------------------------------------
  0   |   0   |   0   |   0   | $0180/palette 0 (coulor 0)
  0   |   0   |   0   |   1   | $01A0/palette 0 (color 15)
  0   |   0   |   1   |   0   | $0180/palette 1 (color 31)
  0   |   0   |   1   |   1   | $01A0/palette 1 (color 47)
  0   |   1   |   0   |   0   | $0180/palette 2 (color 63)
  0   |   1   |   0   |   1   | $01A0/palette 2 (color 79)
  0   |   1   |   1   |   0   | $0180/palette 3 (color 95)
  0   |   1   |   1   |   1   | $01A0/palette 3 (color 111)
  1   |   0   |   0   |   0   | $0180/palette 4 (color 127)
  1   |   0   |   0   |   1   | $01A0/palette 4 (color 143)
  1   |   0   |   1   |   0   | $0180/palette 5 (color 159)
  1   |   0   |   1   |   1   | $01A0/palette 5 (color 175)
  1   |   1   |   0   |   0   | $0180/palette 6 (color 191)
  1   |   1   |   0   |   1   | $01A0/palette 6 (color 207)
  1   |   1   |   1   |   0   | $0180/palette 7 (color 223)
  1   |   1   |   1   |   1   | $01A0/palette 7 (color 239)
-------------------------------------------------------------------------

See @{" Resetting sprites " link resetsprites} for an OS legal method of setting
sprite resolution.

@endnode

@node alignment "Alignment Restrictions"

Alignment Restrictions
----------------------

Bitplanes, sprites and copperlists must be, under
certain circumstances, 64-bit aligned under AGA. Again to benefit from
maximum bandwitdh bitplanes should also only be multiples of 64-bits wide,
so if you want an extra area on the side of your screen for smooth blitter
scrolling it must be *8 bytes* wide, not two as normal.

This also raises another problem. You can no longer use
@{" AllocMem() " link allocmem} to allocate bitplane/sprite memory directly.

Either use AllocMem(sizeofplanes+8) and calculate how many
bytes you have to skip at the front to give 64-bit alignment
(remember this assumes either you allocate each bitplane
individually or make sure the bitplane size is also an
exact multiple of 64-bits), or you can use the new V39
function @{" AllocBitMap() " link allocbitmap}.

@{" The Magic FMode Requester " link fmode}
@endnode
@node fmode "The Magic FMode Register"

The Magic FMode Register
------------------------
If you set your 1200/4000 to a hiresmode (such as 1280x512 Superhires
256 colours) and disassemble the copperlist, you find fun things
happen to the FMODE register ($dff1fc). The FMODE register determines
the amount of words transferred between chipram and the Lisa chip
in each data fetch (I think)....

$dff1fc bits 0 and 1 value

$00 - Normal (word aligned bitmaps) - for standard ECS modes
      and up to 8 bitplanes 320x256

$01 - Double (longword aligned bitmaps) - for 640x256 modes in
      more than 16 colours

$10 - Double (longword aligned bitmaps) - Same effect, for 640x256 modes
      but different things happen... Not sure why!

$11 - Quadruple [x4] (64-bit aligned bitmaps) - for 1280x256 modes...

@{" Fetch Modes Required for Displays [table] " link fetchmode}

@endnode
@node fetchmode "Fetch Modes Required for Displays [table]"

Fetch Mode Required for Displays
--------------------------------

*ALL* ECS and lower screenmodes require only 1x datafetch. All modes
run *FASTER* with at least 2x bandwidth, so try and use 2x bandwitdh
if possible.

                    Planes    Colours         Fetchmode

LORES (320x256)
                    6         64                  1
                    7         128                 1
                    8         256                 1
                    8         HAM-8               1

HIRES (640x256)     5         32                  2
                    6         64                  2
                    7         128                 2
                    8         256                 2
                    8         HAM-8               2

SUPER-HIRES         1         2                   1
(1280x256)          2         4                   1
                    3         8                   2
                    4         16                  2
                    5         32                  4
                    6         64                  4
                    7         128                 4
                    8         256                 4
                    8         HAM-8               4

PRODUCTIVITY        1         2                   1
(640x480,etc)       2         4                   1
                    3         8                   2
                    4         16                  2
                    5         32                  4
                    6         64                  4
                    7         128                 4
                    8         256                 4
                    8         HAM-8               4

This table only shows the minimum required fetchmode for each screen.
You should always try and set the fetchmode as high as possible (if
you are 64-bit aligned and wide, then $11, if 32-bit aligned and wide
$01, etc...)

Bits 2 and 3 do the same for sprite width, as has been mentioned elsewhere...

Remember... To take advantage of the increased fetchmodes (which give
you more processor time to play with!) your bitmaps must be on 64-bit
boundaries and be multiples of 64-bits wide (8 bytes)

@endnode

@node scrolling "Smoother Hardware Scrolling"

Smoother Hardware Scrolling
-------------------------

Extra bits have been added to BPLCON1 to allow smoother hardware
scrolling and scrolling over a larger area.

Bits 8 (PF1H0) and 9 (PF1H1) are the new hi-resolution scroll bits for
playfield 0 and bits 12 (PF2H0) and 13 (PF2H1) are the new bits for
playfield 1.

Another two bits have been added for each bitplane at bits 10 (PF1H6)
and 11 (PF1H7) for playfield 1 and bits 14 (PF2H6) and 15 (PF2H7) to
increase the maximum scroll range from 16 lo-res pixels to 64 lo-res
pixels (or 256 superhires pixels).

Normal 0-16 positions therefore are normal, but it you want to
position your screen at a (super) hires position you need to set
the new bits, or if you require smooth hardware scrolling with either
2x or 4x @{" Fetch Mode " link fetchmode}.

@endnode

@node ham8 "What is Ham-8 format?"

What is HAM-8 Format?
---------------------

Ham8 mode is enabled when the HAM bit is set in BPLCON0 and 8 bitplanes
are specified.

Ham-8 uses *lower* two bits as the command (either
new register (%00), or alter Red, Green or Blue component, as in
standard HAM), and the *upper* 6 bits (planes 2 to 7) as the
register(0 to 63), or as an 6 bit hold-and-modify value to modify
the top 6 bits of an 8-bit colour component.

The lower two bits of the colour component are not altered, so
initial palettes have to be chosen carefuly (or use Art
Department Professional or anything that selects colours better)

@endnode

@node monitorproblems "Monitor type problems"

Monitor Problems
----------------

Unfortunately the A1200/AGA chipset does not have the deinterlacer
circuitry present in the Amiga 3000, but instead has new 'deinterlaced'
modes. This gives the A1200 the capability of running workbench (and
almost all OS legal software) the ability to run flicker free at high
resolution on a multiscan or Super VGA monitor.

Unlike the Amiga 3000 hardware it produces these flicker free modes
by generating a custom copperlist, so any programs that generate
their own copperlists will continue to run at the old flickery 15Khz
frequency unless they add their own deinterlace code.

This is a big problem for many A1200 owners as there are very few multiscan
monitors that support 15Khz displays now. Most multiscan monitors will
not display screen at less than 27Khz. People with A1200/4000 and this
kind of monitor *CANNOT* view any games or demos that write their own
copperlists.

Can you help them out? Unfortunately it's not easy. Deinterlacing is
done in AGA by doing two things.

Firstly different horizontal and vertical frequencies are set (These
are set to unusual values for anyone used to Amiga or PC displays!
For example, DblPal is set by default to 27Khz horizontal and 48Hz
vertical) It's important to realise that the vertical frequency
changes too!

Seondly, for non-interlaced screens, bitplane scandoubling is enabled (bit
BSCAN2 in FMODE) This repeats each scanline twice. A side effect of this is
that the bitplane modulos are unavailable for user control.

So... There are three options.

1. Write nasty copperlist code to work with both standard and
promoted displays (Not a good idea!)

2. Use the OS and set up your displays legally, asking the Display Database
for a screenmode that is available for the current monitor.

3. Give up, and say your demo requires a 15Khz monitor.

I think most people will go for option 3. The Commodore 1084/1085, Phillips
8833/8852 and the Commodore 1950/1960/1940/1942 monitors are all capable
of running 15Khz screens.

@endnode

@node allocmem "exec.library/AllocMem()"

AllocMem -- allocate memory given certain requirements

memoryBlock = AllocMem(byteSize, attributes)
    D0           -198      D0         D1

void *AllocMem(ULONG, ULONG);
@endnode


@node allocbitmap "graphics.library/AllocBitMap()"

AllocBitMap -- Allocate a bitmap and attach bitplanes to it. (V39)

bitmap=AllocBitMap(sizex,sizey,depth, flags, friend_bitmap)
          -918       d0    d1    d2     d3       a0

struct BitMap *AllocBitMap(ULONG,ULONG,ULONG,ULONG, struct BitMap *);

Allocates and initializes a bitmap structure. Allocates and initializes
bitplane data, and sets the bitmap's planes to point to it.

IN:
   sizex = the width (in pixels) for the bitmap data.

   sizey = the height (in pixels).

   depth = the number of bitplanes deep for the allocation.

   flags = BMF_CLEAR - Clear the bitmap.

           BMF_DISPLAYABLE - bitmap displayable on AGA machines in
           all modes.

           BMF_INTERLEAVED - bitplanes are interleaved

   friend_bitmap = pointer to another bitmap, or NULL. If this pointer
                   If present, bitmap will be allocated so blitting
                   between the two is simplified.

SEE ALSO
      @{" FreeBitMap() " link freebitmap}
@endnode

@node freebitmap "graphics.library/FreeBitMap()"

FreeBitMap -- free a bitmap created by AllocBitMap

FreeBitMap(bm)
  -924     a0

VOID FreeBitMap(struct BitMap *)

Frees bitmap and all associated bitplanes

IN:
   bm  =  A pointer to a BitMap.
@endnode

@node resetsprites "Resetting AGA sprite resolution"

This is a totally OS-legal way of resetting sprite resolution to 140ns
(ECS default). call FixSpritesSetup: *BEFORE* your @{" LoadView(NULL) " link howtocode:text/copper/loadview} in your
startup code, and ReturnSpritesToNormal: *BEFORE* the LoadView(wbview)
that returns workbench in your exit code:

Here is the assembler version of the code: See @{" startup.asm " link howtocode:source/startup.asm/MAIN}
for an integrated example of this code:

; Setup code - assumes V39 Kickstart or higher


FixSpritesSetup:
        move.l   _IntuitionBase,a6          ; open intuition.library first!
        lea      wbname,a0
        jsr      @{"_LVOLockPubScreen(a6)" link lockpubscreen}

        tst.l    d0                         ; Could I lock Workbench?
        beq.s    .error                     ; if not, error
        move.l   d0,wbscreen
        move.l   d0,a0

        move.l   sc_ViewPort+vp_ColorMap(a0),a0
        lea      taglist,a1
        move.l   _GfxBase,a6                ; open graphics.library first!
        jsr      @{"_LVOVideoControl(a6)" link videocontrol}       ;

        move.l   resolution,oldres          ; store old resolution

        move.l   #SPRITERESN_140NS,resolution
        move.l   #VTAG_SPRITERESN_SET,taglist

        move.l   wbscreen,a0
        move.l   sc_ViewPort+vp_ColorMap(a0),a0
        lea      taglist,a1
        jsr      @{"_LVOVideoControl(a6)" link videocontrol}       ; set sprites to lores

        move.l   wbscreen,a0
        move.l   _IntuitionBase,a6
        jsr      @{"_LVOMakeScreen(a6)" link makescreen}
        jsr      _LVORethinkDisplay(a6)     ; and rebuild system copperlists

; Sprites are now set back to 140ns in a system friendly manner!

.error
        rts

ReturnSpritesToNormal:
; If you mess with sprite resolution you must return resolution
; back to workbench standard on return! This code will do that...

        move.l   wbscreen,d0
        beq.s    .error
        move.l   d0,a0

        move.l   oldres,resolution          ; change taglist
        lea      taglist,a1
        move.l   sc_ViewPort+vp_ColorMap(a0),a0
        move.l   _GfxBase,a6
        jsr      @{"_LVOVideoControl(a6)" link videocontrol}       ; return sprites to normal.

        move.l   _IntuitionBase,a6
        move.l   wbscreen,a0
        jsr      @{"_LVOMakeScreen(a6)" link makescreen}         ; and rebuild screen

        move.l   wbscreen,a1
        sub.l    a0,a0
        jsr      @{"_LVOUnlockPubScreen(a6)" link unlockpubscreen}

.error
        rts


oldres          dc.l  0
wbscreen        dc.l  0

taglist         dc.l  VTAG_SPRITERESN_GET
resolution      dc.l  SPRITERESN_ECS
                dc.l  TAG_DONE,0

wbname          dc.b  "Workbench",0

@endnode

@node lockpubscreen "intuition.library/LocPubScreen()"

LockPubScreen -- Put a lock on a Public Screen.

screen = LockPubScreen( Name )
 D0          -510         A0

struct Screen *LockPubScreen( UBYTE * );

Prevents a public screen (or the Workbench) from closing.
@endnode

@node unlockpubscreen "intuition.library/UnlockPubScreen()"

UnlockPubScreen -- Remove lock from a Public Screen.

UnlockPubScreen( Name, [Screen] )
     -516          A0    A1

VOID UnlockPubScreen( UBYTE *, struct Screen * );

Releases a lock from @{" LockPubScreen() " link lockpubscreen}

IN:
   Usually Name = NULL and Screen = pointer returned by LockPubScreen()

@endnode

@node videocontrol "graphics.library/VideoControl()"

VideoControl -- Parse tags on viewport colormap.

err = VideoControl( cmap , tags )
d0         -708      a0    a1

ULONG VideoControl( struct ColorMap *, struct TagItem * );

Process the tag commands on the colormap.

IN:
   cm   = pointer to struct ColorMap
   tags = pointer to a table of videocontrol tagitems.

OUT:
   error = NULL if no error occured.

@endnode
@node setchiprev "graphics.library/SetChipRev()"

SetChipRev -- Enables Chip Set features

chipbits = SetChipRev(Rev)
   -888               d0

IN:
   Rev - Revision to be enabled ($ffffffff for best possible)

OUT:
   chipbits - State of chipset on exit.

Only call this routine once. It is called by the OS in SetPatch, but you
should use it if you are writing Non-DOS demos or games.

@endnode
