@DATABASE "Screens"
@AUTHOR   "Paul Manias"
@NODE     "Main" "Screens Documentation"

@{b}@{u}MODULE DOCUMENTATION@{uu}@{ub}
Name:      @{"SCREENS" LINK "Functions"}
Version:   1.0
Number:    MOD_SCREENS
Date:      March 1998
Author:    Paul Manias
Copyright: DreamWorld Productions, 1996-1998.  All rights reserved.

@{b}@{u}CHANGES VERSION 1.0@{uu}@{ub}
Added:   SetScrDimensions()
         SetScrOffsets()
         ReadySwitch()

Renamed: MoveBitmap() to SetBmpOffsets()

Edited:  ChangeColours()
         WaitSwitch()
         BlankColours()
         AllocVideoMem()
         ResetBitmap()
         SetBmpOffsets()
         WaitRastLine()
         Display Buffering.
         Video Locking.
         UpdatePalette()

Deleted: ResetBitmap()
         RemakeScreen()
         LockVideo()
         UnlockVideo()


@{b}@{u}CHANGES VERSION 0.9B@{uu}@{ub}
Added:   WaitSwitch()
         Display Buffering
         Video Locking

Renamed: MovePicture() to MoveBitmap()
         ResetPicture() to ResetBitmap()

Edited:  MoveBitmap()

Deleted: Removed all Sprite references and functions.  Sprites will not
         appear in V1.0.

         All of the raster functions have been removed, as there is now
         an OO Raster object.

@EndNode
---------------------------------------------------------------------------
@NODE "Functions" "Module: Screens"

 @{"INTRODUCTION" LINK "Introduction"}

 @{b}OBJECTS@{ub}
 @{"Raster" LINK "GMSDev:AutoDocs/Objects/Raster.guide/Description"}
 @{"Screen" LINK "GMSDev:AutoDocs/Objects/Screen.guide/Description"}

 @{b}THEORY@{ub}
 @{"Display Buffering" LINK "DisplayBuffering"}
 @{"Video Locking"     LINK "VideoLocking"}

 @{b}FUNCTIONS@{ub}
 @{"AllocVideoMem()"    LINK "AllocVideoMem()"}
 @{"BlankOn()"          LINK "BlankOn()"}
 @{"BlankOff()"         LINK "BlankOff()"}
 @{"FreeVideoMem()"     LINK "FreeVideoMem()"}
 @{"HideDisplay()"      LINK "HideDisplay()"}
 @{"ReadySwitch()"      LINK "ReadySwitch()"}
 @{"ReturnDisplay()"    LINK "ReturnDisplay()"}
 @{"SetBmpOffsets()"    LINK "SetBmpOffsets()"}
 @{"SetScrDimensions()" LINK "SetScrDimensions()"}
 @{"SetScrOffsets()"    LINK "SetScrOffsets()"}
 @{"SwapBuffers()"      LINK "SwapBuffers()"}
 @{"TakeDisplay()"      LINK "TakeDisplay()"}
 @{"WaitSwitch()"       LINK "WaitSwitch()"}
 @{"WaitAVBL()"         LINK "WaitAVBL()"}
 @{"WaitVBL()"          LINK "WaitVBL()"}
 @{"WaitRastLine()"     LINK "WaitRastLine()"}

 @{b}Colour Functions@{ub}
 @{"BlankColours()"    LINK "BlankColours()"}
 @{"ChangeColours()"   LINK "ChangeColours()"}
 @{"ColourMorph()"     LINK "ColourMorph()"}
 @{"ColourToPalette()" LINK "ColourToPalette()"}
 @{"PaletteMorph()"    LINK "PaletteMorph()"}
 @{"PaletteToColour()" LINK "PaletteToColour()"}
 @{"UpdateColour()"    LINK "UpdateColour()"}
 @{"UpdatePalette()"   LINK "UpdatePalette()"}

@EndNode
---------------------------------------------------------------------------
@NODE "Introduction" "Screens Module Overview"
@{b}
                          SCREEN SUPPORT OVERVIEW
@{ub}

The  Screens  module  was  the first module to be designed, and speed was a
major  factor  while  it was being programmed.  To keep it fast, the Screen
object  has  been kept highly simplified while not giving away any powerful
features.  One example of this power is that you can move the screen around
by  changing  its  coordinates,  and  even  dynamically alter its width and
height  without  any  adverse  affect  on  the  picture  display  (see  the
Redimension demo).

There  exists  a wide range of functions, including special effects such as
proportional  fading,  which  allows  you  to  add  some  very  smooth  and
impressive  touches  to your programs.  The Raster support provides an easy
to  use  gateway  to the copper chip.  Using the available commands you can
acheive affects like mirrors and smooth gradients of colour.

The  Screens  module is further supported in GMSPrefs, allowing the user to
select  his  preferred  screen  modes.  A powerful feature is being able to
select  the  screen  type,  so you can change the display type from ILBM to
Chunky  for  example.   This can give you a great speed up if your hardware
allows  you  to  use  such  modes and if the game would benefit from such a
change (eg 3D vectors).  It is even possible to do things such as upgrading
a  game  to  hi-res interlaced, or running in different video modes such as
DBLPAL.

@EndNode
---------------------------------------------------------------------------
@NODE "DisplayBuffering" "Screens: Display Buffering"
@{b}
                             DISPLAY BUFFERING
@{ub}


Display  buffering  is an important issue when you want to double buffer or
triple  buffer a screen.  The technique prevents flickering when drawing to
the  screen,  and  in  the  case  of  triple buffering it will speed up the
program loop.

There  are  different ways to achieve display buffering, I will explain two
of them:

@{u}Wait & Swap@{uu}
This  method  is  used  for  double  buffering  and  some  cases  of triple
buffering.  It involves waiting for the vertical blank after you have drawn
your  data,  then  calling SwapBuffers().  This will usually look something
like this:

  while (loop) {
     Move(Bob);             /* Move objects */
     Draw(Bob);             /* Draw objects to bitmap */
     WaitVBL();             /* Wait for a vertical blank */
     SwapBuffers(Screen);   /* Swap the display buffers */
  }

You can see many examples of this in the various demo source code.

@{u}Triple Buffering Method@{uu}
This  method  can  also  be  used  for  double  buffering,  but is provided
specifically  for  triple  buffering.  When the screen module is loaded, it
installs  a  special  vertical blank interrupt that lies in the background.
This  interrupt looks at the current screen and checks the Switch field for
TRUE.   If  set,  the  interrupt  will  switch the screen buffers while the
program is running.

At  this  stage  it  is important to know what the MemPtrX fields mean when
triple buffering:

  MemPtr1 - On display.
  MemPtr2 - Waiting for display/VBL ready.
  MemPtr3 - Being drawn to.

What this allows us to do is draw to the MemPtr3 buffer while the interrupt
takes  care  of  switching  the  MemPtr2 buffer to the display.  Here is an
example:

  Show(Screen);                     /* Display Screen */

  while (loop) {

    ReadySwitch(Screen);            /* Buffer #2 is ready to display */

      /* This section will draw to the buffer in Bitmap->Data (this is
      ** reflected as buffer #3 in the Screen).  Because a switch will
      ** probably happen in this area you can understand why you are not
      ** allowed to read from the MemPtrX fields in such an "unsafe" area.
      */

      Move(Bob);
      Draw(Bob);

      /* At this point we have to make sure that the display has been
      ** switched.  If this is the case then we are running too fast and
      ** will have to wait until a buffer becomes ready.
      */

    WaitSwitch(Screen);            /* Waits for the switch to occur */
  }

There are some extremely important things that you should take notice of in
this example:

  To tell the interrupt that you are ready to have the buffers flipped, you
  must call ReadySwitch().  This function will Lock() the Screen and
  between the ReadySwitch() and WaitSwitch() lines the buffers could be
  flipped at ANY MOMENT.  To prevent possible program confusion, the
  MemPtrX and Bitmap->Data fields will not be updated until WaitSwitch()
  is called at the end.

  Any call to ReadySwitch() must be accompanied with a call to WaitSwitch()
  once you have finished drawing.  Failing to call WaitSwitch() will most
  likely cause your program to crash.  The purpose of WaitSwitch() is to
  synchronise your Screen and Bitmap together, and update the MemPtr fields
  so that they reflect the current display state.

@EndNode
---------------------------------------------------------------------------
@NODE "VideoLocking" "Screens: Video Locking"
@{b}
                               VIDEO LOCKING
@{ub}


As  video  display  chips have progressed, they have required more and more
memory to hold display data.  This has gotten to the point where it is only
possible  to  hold  a  few  screens  in  video  memory at any one time.  To
illustrate,  a  640x512 true-colour screen requires 1280k (1.2Mb).  This is
before you even think of double-buffering the display!

Obviously we need to consider what to do when a number of applications want
to open screens, and what action we should take when memory runs low.  From
an  OS  point  of view, this is going to require a system that "shares" the
video memory between tasks.

In  MS Windows, this issue is addressed by providing only 1 screen display,
which  means  the  applications  all  have  to open windows that accept the
criteria  of the screen.  For example, if the screen is in 256 colours then
all  the  applications  will run in this mode, plus they have to accept the
width, height, palette and so on.  From a flexibility point of view this is
totally  inadequate,  as  the  user loses the right to choose a display for
each application.  On the other hand, it is a system that is really easy to
manage.

The  screens  module is different.  It is designed to allow applications to
open multiple screens, with one screen at the front of the display.  Now as
we  saw  in the opening paragraph, under this method it would not take long
before you completely ran out of video memory.  What is the solution?

The  only effective way to handle this is to allocate space in other areas,
and  move Bitmap data across to this space when a screen is not on display.
When  I  say "space in other areas", this could mean program/data memory or
at  worst-case,  the  hard-disk.   This provides a way of keeping the video
memory  free, and each application can continue to have the Screen benefits
(such as independent width, height, mode etc).

Now  this  "data moving" raises some important issues.  The biggest problem
being:   If  you read one of the MemPtrX fields and drew to it while at the
same  time  the  OS  moved the display area, you would end up writing to an
invalid  memory  area.  Even worse, lets say your display had been moved to
the  hard-disk,  in  which  case  it  is now impossible to read/write until
brought  back  into  memory!   So  how do you write directly to the display
without causing problems?

You  just  need  to  call Lock(Screen).  When the call returns, the MemPtrX
fields  will  not move until you call Unlock(Screen).  This way you can now
write to your display buffers without harming the OS or the user.  The good
news  is  that  so  long as you only use OS drawing functions, like Draw(),
Clear(),  DrawBob()  and so on, you DON'T need to worry about using Lock().
This  rule  only  applies  when  you  want  to write to the display buffers
directly  with  the CPU.  Also, note that the Screen->Bitmap->Data field is
only  a  reflection  of  the  MemPtrX  fields,  so it too is under the same
conditions.

For  more details, please read the documentation on the Screen object under
Lock().

@EndNode
---------------------------------------------------------------------------
@NODE "AllocVideoMem()" "Screens: AllocVideoMem()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     AllocVideoMem()
Short:    Allocate blitter memory.
Synopsis: APTR AllocVideoMem(LONG Size [d0], LONG Flags [d1])

@{b}@{u}DESCRIPTION@{uu}@{ub}
Allocates  a  block of memory suitable for the video display.  This type of
memory  is  also  compatible with the blitter module, i.e.  you can draw to
and from video ram.

The  memory  will be tracked as outlined in AllocMemBlock() if the user has
kept resource tracking on.

@{b}@{u}INPUTS@{uu}@{ub}
Size
  The Size of the memory to allocate.

Flags
  Special memory attributes as outlined in AllocMemBlock().

@{b}@{u}RESULT@{uu}@{ub}
Pointer  to  the  allocated memory.  All video memory is formatted with 0's
when allocated.  Returns NULL if error.

@{b}@{u}SEE ALSO@{uu}@{ub}
Kernel:  @{"AllocMemBlock()" LINK "GMSDev:AutoDocs/Kernel.guide/AllocMemBlock()"}
         @{"FreeMemBlock()" LINK "GMSDev:AutoDocs/Kernel.guide/FreeMemBlock()"}
Screens: @{"FreeVideoMem()" LINK "FreeVideoMem()"}

@EndNode
---------------------------------------------------------------------------
@NODE "BlankColours()" "Screens: BlankColours()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     BlankColours()
Short:    Drives all screen colours to zero (black).
Synopsis: void BlankColours(*Screen [a0])

@{b}@{u}DESCRIPTION@{uu}@{ub}
Drives  all  the colours in the Screen->Bitmap->Palette to zero, which will
give a black screen if the Screen has 2 - 256 colours.

If  the  Bitmap Type is one of the true colour group then this function may
appear  to  have  no effect, but the bitmap palette will still be driven to
zero.

@{b}@{u}INPUTS@{uu}@{ub}
Screen
  Pointer to an initialised Screen structure.

@{b}@{u}SEE ALSO@{uu}@{ub}
Screens: @{"BlankOn()" LINK "BlankOn()"}

@EndNode
---------------------------------------------------------------------------
@NODE "BlankOn()" "Screens: BlankOn()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     BlankOn()
Short:    Blanks out the entire display until BlankOff() is called.
Synopsis: void BlankOn(void)

@{b}@{u}DESCRIPTION@{uu}@{ub}
After  calling  this function the screen display will be completely blanked
out  until  BlankOff()  is  called.   For  the duration that the display is
blanked out, there will be no visible screen effects whatsoever.  Note that
Show(Screen)  is  completely  incapable of ending a screen blanking period,
but  once  the  screen  display  is returned any screen alterations will be
visible.

This  function  is  intended  for  making  a  clean  transition between two
screens, ie closing one screen then opening another.

@{b}@{u}SEE ALSO@{uu}@{ub}
Screens: @{"BlankOff()" LINK "BlankOff()"}

@EndNode
---------------------------------------------------------------------------
@NODE "BlankOff()" "Screens: BlankOff()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     BlankOff()
Short:    Gives back the display after BlankOn() was called.
Synopsis: void BlankOff(void)

@{b}@{u}DESCRIPTION@{uu}@{ub}
This  function  returns  the  screen  display after calling BlankOn().  Any
hidden  visual  changes  that occurred after the BlankOn() call will become
immediately visible after calling this function.

@{b}@{u}SEE ALSO@{uu}@{ub}
Screens: @{"BlankOn()" LINK "BlankOn()"}

@EndNode
---------------------------------------------------------------------------
@NODE "ChangeColours()" "Screens/ChangeColours"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:      ChangeColours()
Short:     Change a set of colours in a Screen's internal palette.
Synopsis:  void ChangeColours(*Screen [a0], LONG *Colours [a1],
            LONG StartColour [d0], LONG AmtColours [d1])

@{b}@{u}DESCRIPTION@{uu}@{ub}
This  function  changes  a  Screen's  palette values over a set range.  The
following example:

  Palette = { 0xffffff, 0xff0000, 0x00ff00, 0x0000ff };
  ChangeColours(Screen, &Palette, 0, 4);

Would  change  the  first  4 colours of the Screen to white, red, green and
blue.

As  a  result  of  calling this function, the Screen->Bitmap->Palette array
will be updated and the new colours will be visible on the display.

@{b}@{u}INPUTS@{uu}@{ub}
Screen
  Pointer to an initialised Screen structure.

Colours
  Pointer to an array of 24 bit colours.

StartColour
  The first colour to be affected by the change.  The lowest possible value
  is 0 (the background colour).

AmtColours
  The amount of colours to be affected by the change.  Must be at least 1.

@EndNode
----------------------------------------- ----------------------------------
@NODE "ColourMorph()" "Screens: ColourMorph()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     ColourMorph()
Short:    Fades a of set of colours into one colour value.
Synopsis: WORD ColourMorph(*Screen [a0], WORD FadeState [d0],
            WORD Speed [d1], LONG StartColour [d3], LONG AmtColours [d4],
            LONG SrcColour [d2], LONG DestColour [d5])

@{b}@{u}DESCRIPTION@{uu}@{ub}
Fades  a  Screen  from  one colour into another colour.  Once you call this
function,  you  have  to  keep on calling it until it gives you a result of
NULL.   This  allows you to put this function in a loop and do other things
while the fade is active.

This function uses a proportional fading algorithm to achieve its effect.

@{b}@{u}NOTE@{uu}@{ub}
All  fading  functions  ignore  the colour values that are kept internally.
This  will  cause  problems  for  you  if you do not know what your current
palette looks like when using these functions.

Screens with more than 256 colours are not affected by this function.

@{b}@{u}EXAMPLE@{uu}@{ub}

    FadeState = NULL;
    do {
       WaitVBL();
       FadeState = ColourMorph(Screen,FadeState,1,0,32,0xFF00AA,0xA7BC30);
    }
    while (FadeState != NULL)

@{b}@{u}INPUTS@{uu}@{ub}
Screen
  Pointer to an initialised Screen structure.

FadeState
  Initialise to zero, then keep sending the returned value back until you
  get a NULL in this field.

Speed
  The required speed for the fade.

SrcColour
  The colour that you are fading from, 0xRRGGBB format.

DestColour
  The colour that you are fading to, 0xRRGGBB format.

StartColour
  The colour to start fading from (0 ... AmtColours-1).

AmtColours
  The amount of colours to fade (1 ... MaximumColours).  You must never
  use a value of 0 here.

@{b}@{u}RESULT@{uu}@{ub}
Returns  NULL  if  the  fade  has  finished.   At  the end of the fade, the
Bitmap->Palette will be updated to reflect the correct colour values.

@{b}@{u}SEE ALSO@{uu}@{ub}
Screens: @{"ColourToPalette()" LINK "ColourToPalette()"}
         @{"PaletteMorph()" LINK "PaletteMorph()"}
         @{"PaletteToColour()" LINK "PaletteToColour()"}

@EndNode
---------------------------------------------------------------------------
@NODE "ColourToPalette()" "Screens: ColourToPalette()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:      ColourToPalette()
Short:     Fades a set of colours into a range of values.
Synopsis:  WORD ColourToPalette(*Screen [a0], WORD FadeState [d0],
             WORD Speed [d1], WORD StartColour [d3], WORD AmtColours [d4],
             APTR Palette [a1], LONG Colour [d2])

@{b}@{u}DESCRIPTION@{uu}@{ub}
This  function  will  fade  the Screen from a single colour into a palette.
Once  you call this function, you have to keep on calling it until it gives
you  a  result of NULL.  This allows you to put this function in a loop and
do other things while the fade is active.

This function uses the proportional fading algorithm to achieve its effect.

@{b}@{u}NOTE@{uu}@{ub}
All  fading  functions  ignore  the colour values that are kept internally.
This  will  cause  problems  for  you  if you do not know what your current
palette  looks like when using these functions.  Keep track of your current
palette values to help you with the fading functions.

Screens with more than 256 colours are not affected by this function.

@{b}@{u}INPUTS@{uu}@{ub}
Screen
  Pointer to an initialised Screen structure.

FadeState
  Initialise to zero, then keep sending the returned value back until you
  get a NULL in this field.

Speed
  The required speed for the fade.

Palette
  Pointer to the palette used as the source.

Colour
  The colour that you are fading from, 0xRRGGBB format.

StartColour
  The colour to start fading from (0 ... AmtColours-1).

AmtColours
  The amount of colours to fade (1 ... MaximumColours).  You must never
  use a value of 0 here.

@{b}@{u}RESULT@{uu}@{ub}
Returns  NULL  if  the  fade  has  finished.   At  the end of the fade, the
Bitmap->Palette will be updated to reflect the correct colour values.

@{b}@{u}SEE ALSO@{uu}@{ub}
Screens: @{"ColourMorph()" LINK "ColourMorph()"}
         @{"ColourToPalette()" LINK "ColourToPalette()"}
         @{"PaletteMorph()" LINK "PaletteMorph()"}

@EndNode
---------------------------------------------------------------------------
@NODE "FreeVideoMem()" "Screens: FreeVideoMem()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     FreeVideoMem()
Short:    Frees a memory block allocated from FreeVideoMem().
Synopsis: void FreeVideoMem(APTR MemBlock [d0])

@{b}@{u}DESCRIPTION@{uu}@{ub}
Frees a memory block allocated from AllocVideoMem().

@{b}@{u}INPUT@{uu}@{ub}
MemBlock - The memory block to be freed.

@{b}@{u}SEE ALSO@{uu}@{ub}
Kernel:  @{"AllocMemBlock()" LINK "GMSDev:AutoDocs/Kernel.guide/AllocMemBlock()"}
Screens: @{"AllocVideoMem()" LINK "AllocVideoMem()"}

@EndNode
---------------------------------------------------------------------------
@NODE "GetScrType()" "Screens: GetScrType()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     GetScrType()
Short:    Gets the default/user screen type.
Synopsis: LONG GetScrType(void)

@{b}@{u}DESCRIPTION@{uu}@{ub}
Returns  the  screen  type that is being used as the default in the screens
module.  This function is often used by other modules, since the ScrType is
a common field in structures not initialised by the Screens module.

@{b}@{u}RESULT@{uu}@{ub}
The default screen type (eg PLANAR).

@EndNode
---------------------------------------------------------------------------
@NODE "HideDisplay()" "Screens: HideDisplay()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     HideDisplay()
Short:    Hides the entire display from view.
Synopsis: *Screen = HideDisplay(void)

@{b}@{u}DESCRIPTION@{uu}@{ub}
This function is private and is for internal use only.

This  function will hide the GMS display from view.  This will cause the OS
viewport to be returned, but GMS will still be running "in the background".
If GMS is not running on top of another OS then the GMS DeskTop screen will
be displayed and the calling task will be put to the back.

If  no  GMS  screens  are  on  display then this function does nothing, and
returns a NULL value.

@{b}@{u}RESULT@{uu}@{ub}
Pointer  to  the  structure  of  the  Screen  that  has been hidden by this
function.  Otherwise NULL if no Screen was active.

@{b}@{u}SEE ALSO@{uu}@{ub}
Screens: @{"TakeDisplay()" LINK "TakeDisplay()"}

@EndNode
---------------------------------------------------------------------------
@NODE "PaletteMorph()" "Screens: PaletteMorph()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     PaletteMorph()
Short:    Fades a set of colours into a new set of values.
Synopsis: WORD PaletteMorph(*Screen [a0], WORD FadeState [d0],
            WORD Speed [d1], WORD StartColour [d3], WORD AmtColours [d4],
            LONG *SrcPalette [a1], APTR DestPalette [a2])

@{b}@{u}DESCRIPTION@{uu}@{ub}
This function will take the SrcPalette, and use it to fade to a new palette
as  given by DestPalette.  Once you call this function, you have to keep on
calling  it  until  it  gives you a result of NULL.  This allows you to put
this function in a loop and do other things while the fade is active.

This function uses a proportional fading algorithm to achieve its effect.

@{b}@{u}NOTE@{uu}@{ub}
All  fading  functions  ignore  the colour values that are kept internally.
This  will  cause  problems  for  you  if you do not know what your current
palette  looks  like  when  using  these  functions.   Keep  track  of your
palette's  values  and point to them in Screen->Bitmap->Palette if you find
that this problem is occurring for you.

Screens with more than 256 colours are not affected by this function.

@{b}@{u}INPUTS@{uu}@{ub}
Screen
  Pointer to an initialised Screen structure.

FadeState
  Initialise to zero, then keep sending the returned value back until you
  get a NULL in this field.

Speed
  The required speed for the fade.

SrcPalette
  Pointer to the palette used as the source.

DestPalette
  Pointer to the palette that you want to fade to.

StartColour
  The colour to start fading from (0 ... AmtColours-1).

AmtColours
  The amount of colours to fade (1 ...  MaximumColours).  You must never
  use a value of 0 here.

@{b}@{u}RESULT@{uu}@{ub}
Returns  NULL  if  the  fade  has  finished.   At  the end of the fade, the
Bitmap->Palette will be updated to reflect the correct colour values.

@{b}@{u}SEE ALSO@{uu}@{ub}
Screens: @{"ColourMorph()" LINK "ColourMorph()"}
         @{"ColourToPalette()" LINK "ColourToPalette()"}
         @{"PaletteToColour()" LINK "PaletteToColour()"}

@EndNode
---------------------------------------------------------------------------
@NODE "PaletteToColour()" "Screens: PaletteToColour()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:	  PaletteToColour()
Short:    Fades a set of colours into a specific colour value.
Synopsis: WORD PaletteToColour(*Screen [a0], WORD FadeState [d0],
            WORD Speed [d1], LONG StartColour [d3], LONG AmtColours [d4],
            APTR Palette [a1], LONG Colour [d2])

@{b}@{u}DESCRIPTION@{uu}@{ub}
This  function  will  fade  a  palette into a single colour value.  This is
useful  for  fading  the  screen  to black for example.  Once you call this
function,  you  have  to  keep on calling it until it gives you a result of
NULL.   This  allows you to put this function in a loop and do other things
while the fade is active.

This function uses a proportional fading algorithm to achieve its effect.

@{b}@{u}NOTE@{uu}@{ub}
All  fading  functions  ignore  the colour values that are kept internally.
This  will  cause  problems  for  you  if you do not know what your current
palette looks like when using these functions.

Screens with more than 256 colours are not affected by this function.

@{b}@{u}INPUTS@{uu}@{ub}
Screen
  Pointer to an initialised Screen structure.

FadeState
  Initialise to zero, then keep sending the returned value back until you
  get a NULL in this field.

Speed
  The required speed for the fade.

Palette
  Pointer to the palette used as the source.

Colour
  The colour you want to fade to, in 0xRRGGBB format.

StartColour
  The colour to start fading from (0 ... AmtColours-1).

AmtColours
  The amount of colours to fade (1 ... MaximumColours).  You must never
  use a value of 0 here.

@{b}@{u}RESULT@{uu}@{ub}
Returns  NULL  if  the  fade  has  finished.   At  the end of the fade, the
Bitmap->Palette will be updated to reflect the correct colour values.

@{b}@{u}SEE ALSO@{uu}@{ub}
Screens: @{"ColourMorph()" LINK "ColourMorph()"}
         @{"PaletteMorph()" LINK "PaletteMorph()"}
         @{"PaletteToColour()" LINK "PaletteToColour()"}

@EndNode
---------------------------------------------------------------------------
@NODE "ReadySwitch()" "Screens: ReadySwitch()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     ReadySwitch()
Short:    Tells the Screen that you are ready to have the buffers switched.
Synopsis: void ReadySwitch(*Screen [a0])

@{b}@{u}DESCRIPTION@{uu}@{ub}
This function is used in conjunction with WaitSwitch() to provide interrupt
driven  display buffering.  The ReadySwitch() function basically provides a
way of saying "I am ready to switch the buffers in my screen now".

If you have read the documentation on Display buffering, you will know that
there  is  an  interrupt  that  runs  in the background, waiting for switch
events  to  occur.   ReadySwitch()  will inform this interrupt that you are
ready  to switch the display buffers.  Out of necessity, this function will
also  Lock()  the  Screen  in  order  to  prevent  the  rest of the OS from
interfering with the display buffering process.

After  calling  ReadySwitch(),  you  MUST  call  WaitSwitch() when you have
completed  your next drawing cycle.  Failure to call WaitSwitch() is likely
to cause your program to crash.

@{b}@{u}NOTE@{uu}@{ub}
To  grasp  a  full  understanding  of how to use this function effectively,
please read the theory on Display Buffering.

@{b}@{u}INPUTS@{uu}@{ub}
Screen - Pointer to an initialised Screen.

@{b}@{u}SEE ALSO@{uu}@{ub}
Screens: @{"WaitSwitch()" LINK "WaitSwitch()"}
Theory:  @{"Display Buffering" LINK "DisplayBuffering"}

@EndNode
---------------------------------------------------------------------------
@NODE "RefreshScreen()" "Screens: RefreshScreen()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     RefreshScreen()
Short:    Updates the screen display.
Synopsis: void RefreshScreen(*Screen [a0]);

@{b}@{u}DESCRIPTION@{uu}@{ub}
When  running  in emulation mode, this function will refresh the display so
that  it  correctly  reflects  the bitmap data.  If the Screen is not being
emulated, this function will simply do nothing.

In   future  this  function  will  become  redundant,  once  the  emulation
interrupts are running.

@{b}@{u}INPUT@{uu}@{ub}
Screen - Pointer to an initialised Screen structure.

@{b}@{u}SEE ALSO@{uu}@{ub}
Screens: @{"WaitVBL()" LINK "WaitVBL()"}

@EndNode
---------------------------------------------------------------------------
@NODE "ReturnDisplay()" "Screens: ReturnDisplay()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     ReturnDisplay()
Short:    Private function.
Synopsis: Screen = ReturnDisplay(void);

@{b}@{u}DESCRIPTION@{uu}@{ub}
This function is private and is for internal use only.

It  returns the monitor display to whatever Operating System GMS is running
on.  This is a special function in the monitor drivers, and is reserved for
use in the screens module.

@{b}@{u}RESULT@{uu}@{ub}
Pointer to the Screen that was removed.

@{b}@{u}SEE ALSO@{uu}@{ub}
Screens: @{"TakeDisplay()" LINK "TakeDisplay()"}

@EndNode
---------------------------------------------------------------------------
@NODE "SetBmpOffsets()" "Screens: SetBmpOffsets()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     SetBmpOffsets()
Short:    Moves a Screen's Bitmap to specified X/Y values.
Synopsis: void SetBmpOffsets(*Screen [a0], WORD BmpXOffset [d0],
            WORD BmpYOffset [d1])

@{b}@{u}DESCRIPTION@{uu}@{ub}
This  routine  has  two  uses:   Moving  the  Bitmap to any position on the
display, and for Hardware Scrolling.

It  will  take  the BmpXOffset and BmpYOffset arguments and use them to set
the  new Bitmap position.  This function will execute at the same speed for
all offset values.

You  must  have  set  the  SCR_HSCROLL bit for horizontal scrolling and the
SCR_VSCROLL  bit  for  vertical scrolling if you wish to use this function.
If  you  set  the  SCR_HBUFFER flag in ScrAttrib then you can also use this
function  to  legally  hardware-scroll  up  to 50 screens in any horizontal
direction.  Do not draw graphics beyond these boundaries as you will damage
the system memory.  Note that the SCR_HBUFFER flag is also considered to be
'dangerous'  as  it  is  not  currently  known  how many graphics cards can
support this method.

If you want to do 'safe' hardware scrolling suitable for games that need to
scroll in any direction, initialise a Screen that has a Bitmap of twice the
size  of the Screen.  You can then scroll around in this area and create an
infinite scrolling map without needing the SCR_HBUFFER flag.

@{b}@{u}NOTES@{uu}@{ub}
If  the graphics hardware does not support hardware scrolling, this routine
will  probably  blit  the  entire bitmap to the new position.  This is very
slow  but is the only other option.  Fortunately good graphics cards do not
have this problem.

The  normal  execution  time  for  this  function  on  ECS/AGA  is just 0.7
rasterlines on an A1200+Fast.

@{b}@{u}INPUTS@{uu}@{ub}
Screen
  Pointer to an initialised Screen structure.

BmpXOffset
  The new X offset for the Bitmap.

BmpYOffset
  The new Y ofset for the Bitmap.

@EndNode
---------------------------------------------------------------------------
@NODE "SetScrDimensions()" "Screens: SetScrDimensions()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     SetScrDimensions()
Short:    Alter the width and height of a Screen.
Synopsis: void SetScrDimensions(*Screen [a0], WORD Width [d0],
            WORD Height [d1])

@{b}@{u}DESCRIPTION@{uu}@{ub}
You  can  use  this function to dynamically alter the Width and Height of a
Screen's  viewport.  

There  are  some  hardware  restriction involved in this - ie some graphics
cards only support standard modes like 680x400 etc.  In such cases your new
width  and  height settings will be automatically adjusted to something the
hardware can cope with.

@{b}@{u}INPUTS@{uu}@{ub}
Screen
  Pointer to an initialised Screen.

Width
  The new Screen Width, must be greater than zero.  Attempting to set
  extremely large widths, e.g.  1280 on an OCS machine will cause the value
  to be restricted back to something the hardware can handle (e.g.  640).
  Obviously there is also some dependency on resolution, LORES can handle
  no more than 352 pixels in width.

  Secondly, if the hardware can only handle Widths that are divisible by 16
  or 8, the width will be rounded to the best match.

Height
  The new Screen Height, must be greater than zero.  As with the Width
  argument, the height may be restricted where necessary.

@{b}@{u}SEE ALSO@{uu}@{ub}
Screens: @{"SetBmpOffsets()" LINK "SetBmpOffsets()"}
         @{"SetScrOffsets()" LINK "SetScrOffsets()"}

@EndNode
---------------------------------------------------------------------------
@NODE "SetScrOffsets()" "Screens: SetScrOffsets()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     SetScrOffsets()
Short:    Move a Screen to a different display position.
Synopsis: void SetScrOffsets(*Screen [a0], WORD XOffset [d0],
            WORD YOffset [d1])

@{b}@{u}DESCRIPTION@{uu}@{ub}
This  function  can  be  used to move a Screen to a different offset on the
display.   There  are  no restrictions and you may specify negative values.
If  you pass a value which is well out of displayable range, e.g 2000X, the
value will be limited to what the hardware can handle.

An  offset  of (0X,0Y) positions the Screen at the top left of the display,
which is the default.

@{b}@{u}NOTE@{uu}@{ub}
Some  graphics  hardware  may  not  support screen offsets.  If this is the
case, this function will do nothing.

@{b}@{u}INPUTS@{uu}@{ub}
Screen
  Pointer to an initialised Screen object.

XOffset
  The horizontal offset that you want to move the Screen to.

YOffset
  The vertical offset that you want to move the Screen to.

@{b}@{u}SEE ALSO@{uu}@{ub}
Screens: @{"SetBmpOffsets()" LINK "SetBmpOffsets()"}
         @{"SetScrDimensions()" LINK "SetScrDimensions()"}

@EndNode
---------------------------------------------------------------------------
@NODE "SwapBuffers()" "Screens: SwapBuffers()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     SwapBuffers()
Short:    Switch the screen display buffers.
Synopsis: void SwapBuffers(*Screen [a0])

@{b}@{u}DESCRIPTION@{uu}@{ub}
If  the screen is double buffered, this function swaps Screen->MemPtr1 with
Screen->MemPtr2,  and  activates  the  new bitmap data for the display.  If
triple buffered, then all three MemPtr's are switched.  Visually:

	@{b}BEFORE          AFTER@{ub}
	MemPtr1         MemPtr2
	MemPtr2  ---->  MemPtr3
	MemPtr3         MemPtr1

The  Screen->Bitmap->Data  field  will  be  updated  to reflect the current
drawable  address.   I.e.   if single buffered then Bitmap->Data = MemPtr1,
double buffered is MemPtr2, triple buffered is MemPtr3.

@{b}@{u}INPUT@{uu}@{ub}
Screen
  Pointer to an initialised Screen structure.

@{b}@{u}SEE ALSO@{uu}@{ub}
Theory: @{"Display Buffering" LINK "DisplayBuffering"}

@EndNode
---------------------------------------------------------------------------
@NODE "TakeDisplay()" "Screens: TakeDisplay()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     TakeDisplay()
Short:    Private function.
Synopsis: LONG TakeDisplay(*Screen [a0])

@{b}@{u}DESCRIPTION@{uu}@{ub}
Takes  the  display from the Operating System that GMS is running on.  This
is  a  special  function in the monitor drivers, and is reserved for use in
the screens module.

@{b}@{u}INPUTS@{uu}@{ub}
Screen
  Pointer to an initialised Screen structure.

@{b}@{u}RESULT@{uu}@{ub}
Returns ERR_OK if successful.

@{b}@{u}SEE ALSO@{uu}@{ub}
Screens: @{"ReturnDisplay()" LINK "ReturnDisplay()"}

@EndNode
---------------------------------------------------------------------------
@NODE "UpdateColour()" "Screens: UpdateColour()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     UpdateColour()
Short:    Updates a 24 bit $RRGGBB value in a Screen palette.
Synopsis: void UpdateRGB(*Screen [a0], LONG Colour [d0], LONG RRGGBB [d1])

@{b}@{u}DESCRIPTION@{uu}@{ub}
This  function  updates  a  single colour value in a Screen's palette.  The
change  is  immediately visible following the next vertical blank, although
RGB  based  Screens (such as TRUECOLOUR), will not show any visible changes
after calling this function.

@{b}@{u}INPUTS@{uu}@{ub}
Screen
  Pointer to an initialised Screen object.

Colour
  The colour number to update, between 0 and Screen->AmtColours.

RRGGBB
  The new colour value in standard 0xRRGGBB format.

@{b}@{u}SEE ALSO@{uu}@{ub}
Screens: @{"UpdatePalette()" LINK "UpdatePalette()"}

@EndNode
---------------------------------------------------------------------------
@NODE "UpdatePalette()" "Screens: UpdatePalette()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     UpdatePalette()
Short:    Updates an entire Screen palette to new colour values.
Synopsis: void UpdatePalette(*Screen [a0])

@{b}@{u}DESCRIPTION@{uu}@{ub}
Normally when you write changes to the Screen->Bitmap->Palette array, there
will  be no visible effect on the display for Types of 256 colours or less.
If   you   want  your  changes  to  be  visible,  you  will  need  to  call
UpdatePalette().   This  will  cause  the  Screen display to be updated and
reflect the new palette values.

This function has no visible effect on RGB based screens.

@{b}@{u}NOTE@{uu}@{ub}
Palette changes will appear when the next vertical blank occurs.

@{b}@{u}INPUTS@{uu}@{ub}
Screen
  Pointer to an initialised Screen structure.

@{b}@{u}SEE ALSO@{uu}@{ub}
Screens: @{"UpdateColour()" LINK "UpdateColour()"}

@EndNode
---------------------------------------------------------------------------
@NODE "WaitRastLine()" "Screens: WaitRastLine()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     WaitRastLine()
Short:    Waits for the strobe to reach a specific line.
Synopsis: LONG WaitRastLine(*Screen [a0], WORD LineNumber [d0])

@{b}@{u}DESCRIPTION@{uu}@{ub}
Waits  for  the strobe to reach the scan-line specified in LineNumber.  The
recognised  range is dependent on the height of your screen, eg 0-255 for a
standard  320x256  screen.   It is permissable to enter negative values and
values that exceed this range, but only do so if absolutely necessary.

This function has been specially written to avoid beam misses caused by the
untimely activation of interrupts.

@{b}@{u}NOTE@{uu}@{ub}
Not all graphics hardware will support this function.  If this is the case,
WaitRastLine() will return immediately with ERR_NOSUPPORT.

@{b}@{u}INPUTS@{uu}@{ub}
Screen
  The Screen that you are waiting on.

LineNumber
 Vertical beam position to wait for.

@{b}@{u}RESULT@{uu}@{ub}
Returns  ERR_OK  on  success,  or  ERR_NOSUPPORT  if  the hardware does not
support this function.

@{b}@{u}SEE ALSO@{uu}@{ub}
Screens: @{"WaitVBL()" LINK "WaitVBL()"}

@EndNode
---------------------------------------------------------------------------
@NODE "WaitSwitch()" "Screens: WaitSwitch()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     WaitSwitch()
Short:    Wait for the buffers to be switched at the vertical blank.
Synopsis: LONG WaitSwitch(*Screen [a0])

@{b}@{u}DESCRIPTION@{uu}@{ub}
This function is used to synchronise a Screen with the display buffers.  It
will  Unlock()  the  Screen from the last ReadySwitch() and will update the
memory buffers so that everything is correct.

Please  read  the  complete  theory  on display buffering before using this
function.

@{b}@{u}INPUT@{uu}@{ub}
Screen
  Pointer to an initialised Screen object.

@{b}@{u}RESULT@{uu}@{ub}
Currently returns NULL.

@{b}@{u}SEE ALSO@{uu}@{ub}
Screens: @{"ReadySwitch()" LINK "ReadySwitch()"}
Theory:  @{"Display Buffering" LINK "DisplayBuffering"}

@EndNode
---------------------------------------------------------------------------
@NODE "WaitAVBL()" "Screens: WaitAVBL()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     WaitAVBL()
Short:    Waits for a vertical blank.
Synopsis: LONG WaitAVBL(void)

@{b}@{u}DESCRIPTION@{uu}@{ub}
This  function  waits  until the horizontal beam reaches the Vertical BLank
area.   This  routine  will try and give you as much VBL space as possible,
usually by waiting for the exact point where the display stops.  If this is
not  possible,  then  it  will  wait  for  the beam to reach the top of the
monitor display.

This  version  of  WaitVBL() will automatically pause your Task if the user
moves  the focus to a different program.  This can be exceptionally useful,
as it will prevent your program from stealing resources when the user wants
to do something else.

@{b}@{u}RESULT@{uu}@{ub}
Currently returns NULL.

@{b}@{u}SEE ALSO@{uu}@{ub}
Screens: @{"WaitRastLine()" LINK "WaitRastLine()"}
         @{"WaitVBL()" LINK "WaitVBL()"}
@EndNode
---------------------------------------------------------------------------
@NODE "WaitVBL()" "Screens: WaitVBL()"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     WaitVBL()
Short:    Waits for a vertical blank.
Synopsis: LONG WaitVBL(void)

@{b}@{u}DESCRIPTION@{uu}@{ub}
Waits  until  the  horizontal  beam  reaches the Vertical BLank area.  This
routine  will  try  and  give you as much VBL space as possible, usually by
waiting  for  the  exact  point  where  the  display stops.  If this is not
possible,  then  it  will wait for the beam to reach the top of the monitor
display.

@{b}@{u}RESULT@{uu}@{ub}
Currently returns NULL.

@{b}@{u}SEE ALSO@{uu}@{ub}
Screens: @{"WaitAVBL()" LINK "WaitAVBL()"}
         @{"WaitRastLine()" LINK "WaitRastLine()"}

@EndNode
---------------------------------------------------------------------------
@NODE "()" "Screens:"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:     
Short:    
Synopsis: 

@{b}@{u}DESCRIPTION@{uu}@{ub}

@{b}@{u}INPUTS@{uu}@{ub}

@{b}@{u}RESULT@{uu}@{ub}

@{b}@{u}SEE ALSO@{uu}@{ub}

@EndNode
