
                           Direct Memory Access

Although  there  are  a  lot  of useful functions inside retina.library, it
might  be  of interest to directly access the graphics memory.  This is not
as  easy  as  it  is  with  basic  graphic  boards  which  map their memory
completely  in the Amiga address range.  The Retina graphics memory address
is  outside the 32 bit adress range of a 680x0 processor.  To enable direct
cpu  read  or  write  accesses  a  64  KByte segment may be selected.  This
segment may be accessed through a 64 KByte 'window' in the Amiga IO address
range.   Retina allocates 128 KByte of memory in the IO address range using
autoconfig,  64  KByte  to  control the hardware and 64 KByte to access the
graphics memory.

Please  note,  if  you  use  direct memory access on the Retina board, your
application  may break under future hardware revisions (no rumours please).
This  mainly  might  be  caused  by  different  memory alignment rules (see
below).   So  think about it seriously, maybe using the normal functions in
retina.library is sufficient.


                     The Retina memory alignment rules

All  allocated  memory blocks including a screens bitmap start at a 64 byte
boundary.   The  length  of  these  blocks always is an even multiple of 64
byte.

The  length  of  one line in a bitmap (_rs_Modulo) is an even multiple of 8
byte, no matter how many pixels are visible in this line.

The  length  of  a visible line is always an even multiple of 4 pixels.  If
your  screens  width  is  not  a multiple of 4, there are 1 to 3 additional
pixels at the right border active.  Do not write anything other than zeroes
to their memory address, otherwise random data becomes visible!


                            The Segment Pointer

There  is  a  hardware  internal  segment pointer.  It points to an address
inside  the  retina graphics memory.  This address is the starting address,
the 64 KByte window in Amiga memory points to.  The segment pointer can not
point  to  any  address,  it  must  be  an  even  multiple  of 64 byte.  In
retina.library  there  is  a  function  called Retina_SetSegmentPtr().  You
provide  the desired address in Retina memory to this function, it sets the
internal  segment  pointer  and  returns the corresponding address in Amiga
memory.

Retina_SetSegmentPtr()  frees the user from the limitations of the internal
segment  pointer  mentioned  above.   Using  Retina_SetSegmentPtr() you may
access any byte in the Retina graphics memory.


                            The Segment Length

Caused  by the limitations of the internal segment pointer mentioned above,
the  size  of the segment in Amiga memory may be some bytes smaller then 64
KByte!   Only  if the address provided to Retina_SetSegmentPtr() is an even
multiple  of  64,  you  may access the whole 65536 bytes of memory starting
with  the address returned by Retina_SetSegmentPtr().  For each byte beyond
a  64  byte  boundary  you  may  access one byte less!  For example, if the
address  provided  to  Retina_SetSegmentPtr()  would  be  67 you only could
access 65533 bytes of memory starting with the returned address.

If  you  first  set  the  segment pointer to the left, top edge of a screen
(_rs_BitMap)  you  may access exactly 65536 Bytes starting with the address
returned  by Retina_SetSegmentPtr().  Then you must set the segment pointer
again.   If  you always want to access 65536 Bytes in one segment, you must
be sure that the segment pointer always points to a 64 byte boundary!  This
is  the  case,  if  you  start  as  mentioned before and then increment the
pointer  by  a  multiple of 64.  You may NOT access the full 65536 bytes if
you  access the memory line by line (adding _rs_Modulo), because lines only
have  8  byte  align.   Because  lines  are  not so long, this should be no
limitation.


                            Screens and Memory

For  the Retina graphics memory retina.library uses memory handling as Exec
does  for  Amiga  memory.   You have to allocate memory before using it and
free  it if you do not need it any more.  Never access memory which has not
been allocated by you!

Normally  your  application will open a screen on Retina.  You may directly
access  its  memory.   Retina_OpenScreen()  returns  a  pointer to a struct
RetinaScreen.   There  you  find  a pointer called _rs_BitMap.  This is the
start  address  of  the  graphics  memory  used by this screen (it is not a
pointer  to  a  bitmap  structure).  It points to the top left pixel and is
aligned on a 64 byte boundary.

Besides    _rs_BitMap    there    are    two   other   important   entries:
_rs_BytesPerPixel  and  _rs_Modulo.   _rs_BytesPerPixel tells you, how many
bytes are used by one pixel.  _rs_Modulo tells you, how many bytes you have
to add to go one line down in memory.  To access a specific pixel:
    PixelAddress = _rs_BitMap + X * _rs_BytesPerPixel + Y * _rs_Modulo
    MemAddress = Retina_SetSegmentPtr(PixelAddress)
Now you may write to or read from MemAddress.

If  you  run  a  double  buffered  animation  using a Retina double bufferd
screen, _rs_BitMap always points to the currently invisible image, which is
that  one  you  have  to  modify.   There  should  be  no  need  to  access
_rs_DBufBitMap.

For  some  purpose you may use some Retina graphics memory beyond that used
by  a  screen.  Retina.library provides some functions to allocate and free
memory:    Retina_AllocVec(),  Retina_FreeVec(),  Retina_AllocBitMap()  and
Retina_FreeBitMap().  See retina.doc to learn how to use them.

You  can  access this allocated memory using Retina_SetSegmentPtr().  Don't
forget to free this memory if you do not need it any more.


                              Read and Write

If  you  want  to access the Retina memory directly you always MUST use the
start  address  returned  by  Retina_SetSegmentPtr(),  never  use  absolute
addressing!

For both, read and write, byte, word and longword accesses are allowed.  Of
course  only byte accesses may go to odd adresses.  Odd addresses in Retina
graphics memory will be odd addresses in the Amiga memory segment.

Data  caching  is  not  allowed  for  the Retina address range, neither the
hardware  control  area nor the memory segment.  Normally caching is turned
off for the IO memory, but there are some tools, which turn it on.

All  read/write  accesses  and  calls  to  Retina_SetSegmentPtr()  are only
allowed inside Retina_OwnRetina() and Retina_DisownRetina()!


                             Colors in Memory

Retina  can  handle screens with 4, 8, 15, 16 and 24 bit per pixel.  So you
can display 16, 256, 32768, 65536 or 16777216 colors.

 8 bit, 256 colors:
Each  pixel needs one byte of memory.  The value ranges from 0 upto 255 and
accesses one of 256 colors out of a palette of 16.7 million colors.

16 bit, 65536 colors, true color
Each pixel needs two bytes of memory (one word).  This word always is on an
even  address,  so  word  access  on  a  pixel is allowed.  Please note the
strange organisation of color bits in this word (pixel):

     Word-     1111110000000000
      Bits:    5432109876543210
     Color:    gggbbbbbrrrrrggg
Color Bits:    2104321043210543

24 bit, 16.7 M colors, true color
Each pixel needs three bytes of memory.  The first byte is blue, the second
byte  is  green and the third byte is red.  So it is BGR and not the common
RGB!


                                   Speed

For applications which have to be very fast, try to avoid unnecessary calls
to  Retina_SetSegmentPtr().   Although  this  function  is highly optimized
(only  19  assembly  commands)  it does need some time to execute.  This is
mainly caused by 7 accesses to Retina harware registers which are very slow
compared  to  32  bit memory accesses done by an '30 or '40 although Retina
provides a zero waitstates interface.

First calculate, how many lines you may access without violating the roules
listed above.
                    NumberOfLines = 65472 / _rs_Modulo
Start with one call to Retina_SetSegmentPtr().  Access NumberOfLines lines,
then call it again and so on until you ar done.

If  possible,  always  use word or long word accesses and try to avoid byte
read  or  writes.   A  word  transfer is at least twice as fast as two byte
accesses, a long access is faster than two word accesses!


                                  Example

The  following  assembly subroutine clears one pixel in a screen.  It works
fine on 8, 15/16 and 24 bit screens.

; A1: pointer to an open Retina screen
; D0: X
; D1: Y
ClrPixel:
        CALLRET   OwnRetina                 ;get Retina for direct access
        movea.l   _rs_BitMap(a1),a0         ;the screens memory
        mulu.w    _rs_BytesPerPixel(a1),d0  ;calculate the horizontal offset
        adda.l    d0,a0                     ;  and add it to the memory address
        mulu.w    _rs_Modulo(a1),d1         ;calculate the vertical offset
        adda.l    d1,a0                     ;  and add it to the memory address
        CALLRET   SetSegmentPtr             ;set the segment pointer
        movea.l   d0,a0                     ;get the address
        move.w    _rs_BytesPerPixel(a1),d0  ;bytes to clear
Loop:   clr.b     (a0)+                     ;  and clear one byte
        subq.w    #1,d0                     ;one byte cleared
        bne.s     Loop                      ;continue to clear the whole pixel
        CALLRET   DisownRetina              ;free Retina
        rts
