/*
 * Client.h v1.2
 * Copyright © 1994 by Stefano Reksten of 3AM - The Three Amigos!!!
 * All rights reserved.
 *
 * This file and client.lib are needed to build a client blanker.
 *
 * What's to do:
 *
 * When blanking is needed, BServer will choose a client and launch it.
 * So when you are launched, it's supposed you will blank the screen!
 *
 * OpenCommunication() will return you a DisplayIDInformation structure
 * (see below). In this structure you'll find the user's preferred display
 * id, overscan dimensions, etc.
 *
 * If anything goes wrong, SendClientMsg( ACTION_FAILED ) will tell BServer
 * to run another client from its list (or to use its builtin blanker).
 *
 * When any input activity takes place, BServer will issue you a command
 * that will be hopefully COMMAND_QUIT. So long, you aren't needed anymore.
 * Do your cleanup, CloseCommunication( <your DisplayIDInformation> ) and
 * exit.
 *
 * Have fun! :-)
 *
 *
 * Here's the complete documentation of the function you can use to
 * interact with your server. (Functions that are internal only, like
 * AllocClientMessage, are not documented.)
 * 
 * 
 * NAME
 *   OpenCommunication
 *
 * SYNOPSIS
 *   dinfo = OpenCommunication()
 *
 *   struct DisplayIDInformation * = OpenCommunication()
 *
 * FUNCTION
 *   Opens a connection between your blanker (client) and the server.
 *
 * RESULTS
 *   A DisplayIDInformation if communication was opened, NULL otherwise.
 *
 * SEE ALSO
 *   CloseCommunication()
 *
 *
 *
 *
 * NAME
 *   CloseCommunication
 *
 * SYNOPSIS
 *   CloseCommunication( dinfo )
 *
 *   void CloseCommunication( struct DisplayIDInformation * )
 *
 * FUNCTION
 *   Closes communication between your client and the server. Frees the
 *   structure returned by OpenCommunication.
 *
 * SEE ALSO
 *   OpenCommunication()
 *
 *
 *
 *
 * NAME
 *   SendClientMsg
 *
 * SYNOPSIS
 *   success = SendClientMsg( action )
 *
 *   BOOL = SendClientMsg( ULONG )
 *
 * FUNCTION
 *   Sends a message to the server (waiting reply). Of course, your
 *   client should already have opened a communication with the server.
 *
 * INPUTS
 *   action: an UBYTE describing the action you're performing. This may be:
 *
 *          o ACTION_FAILED  (You couldn't start your blanking actions,
 *                           so you are telling the server to ask
 *                           another blanker.)
 *
 * RETURNS
 *   TRUE if message was received, FALSE otherwise.
 *
 * SEE ALSO
 *   OpenCommunication()
 *
 *
 *
 *
 * NAME
 *   GetServerCommand, WaitServerCommand
 *
 * SYNOPSIS
 *   command = GetServerCommand()
 *   command = WaitServerCommand()
 *
 *   UBYTE = GetServerCommand()
 *   UBYTE = WaitServerCommand()
 *
 * FUNCTION
 *   It returns the command sent by the server. The difference between
 *   the two functions is that GetServerCommand checks the communication
 *   port searching for any message coming from the server, while
 *   WaitServerCommand will make your program wait until a command
 *   (different from COMMAND_IDLE) is received.
 *   The server may send you these commands:
 *   o COMMAND_IDLE:    the CommunicationPort is empty. This one can be
 *                      obtained only with GetServerCommand.
 *   o COMMAND_QUIT:    the server is asking you to quit.
 *   Note that GetServerCommand POLLS the port so don't use it out of any
 *   rendering (or something else) cycle. Use WaitServerCommand instead.
 *
 * SEE ALSO
 *   any client's source
 *
 *
 *
 * Here are some macros that you can use for quicker programming.
 *
 *
 * NAME
 *   DISPLAYID
 *
 * SYNOPSIS
 *   DisplayID = DISPLAYID( dinfo )
 *
 *   ULONG = DISPLAYID( struct DisplayIDInformation * )
 *
 * MACRO
 *   This macro returns you an ULONG containing the screen mode choosen
 *   by the user for a client.
 *
 *
 *
 *
 * NAME
 *   FILTEROUT
 *
 * SYNOPSIS
 *   newDisplayID = FILTEROUT( oldDisplayID, flags_to_remove )
 *
 *   ULONG = FILTEROUT( ULONG, ULONG )
 *
 * MACRO
 *  This macro removes all the unwanted flags from a DisplayID, e.g.:
 *  you are told to blank; the server sent you also the preferred
 *  screenmode (stored in dinfo). You want to filter SUPERHIRES mode
 *  and LACE flag but want a hires screen. You could pass as value
 *  for SA_DisplayID this value:
 *  FILTEROUT( DISPLAYID(dinfo) | HIRES, SUPERHIRES|LACE )
 *
 * SEE ALSO
 *   GetServerCommand(), WaitServerCommand()
 *
 *
 *
 *
 * NAME
 *   GETSTANDARDRECT   
 *   GETMAXOSCANRECT
 *   GETVIDEOOSCANRECT
 *   GETTXTOSCANRECT
 *   GETSTDOSCANRECT
 *
 * SYNOPSIS
 *   rectangle = GET...RECT( struct DisplayIDInformation * )
 *
 *   struct Rectangle * = GET...RECT( struct DisplayIDInformation * )   
 *
 * MACRO
 *   These macro return the address of a Rectangle structure containing
 *   a certain overscan value. (As ever, the DisplayIDInformation
 *   structure was allocated by your server)
 *
 *
 *
 *
 * NAME
 *   RECTANGLEWIDTH
 *   RECTANGLEHEIGHT
 *
 * SYNOPSIS
 *  width = RECTANGLEWIDTH( rect )
 *  height = RECTANGLEHEIGHT( rect )
 *
 *  UWORD = RECTANGLEWIDTH( struct Rectangle * )
 *  UWORD = RECTANGLEHEIGHT( struct Rectangle * )
 *
 * MACRO
 *  This macro returns the current width/height for a screen from a
 *  Rectangle structure.
 *
 *
 *
 * Here are two functions you can use also for smaller sources:
 *
 *
 * NAME
 *  SpritesOff()
 *
 * SYNOPSIS
 *  SpritesOff()
 *
 * FUNCTION
 *  Disables sprite DMA, removes sprite from screen.
 *  Remember that performing a ScreenToFront action (when doublebuffering)
 *  or similar will activate sprite DMA again.
 *
 * SEE ALSO
 *  SpritesOn(), Balls.c, any other client's source
 *
 * BUGS
 *  Well sprites should remain deactivated...
 *
 *
 *
 * NAME
 *  SpritesOn()
 *
 * SYNOPSIS
 *  SpritesOn()
 *
 * FUNCTION
 *  Enables sprite DMA.
 *
 * SEE ALSO
 *  SpritesOff()
 *
 *
 *
 * NAME
 *  CheckAA()
 *
 * SYNOPSIS
 *  aa_chipset = CheckAA()
 *
 *  BOOL = CheckAA( void )
 *
 * FUNCTION
 *  Tells wether AA chipset is installed or not, and if you can use it
 *  (that is, if you have kickstart 3.0+ installed). If this function
 *  returns FALSE, you have to fall back to 2.0, or to quit. As a general
 *  behaviour, a client should fall back to ECS.
 */

#ifndef GRAPHICS_DISPLAYINFO_H
#include <graphics/displayinfo.h>
#endif

#ifndef CLIENT_H
#define CLIENT_H

/* Client actions  - what the client can say to the server */

#define ACTION_FAILED      3

/* Server commands - what the server can say to the client */

#define COMMAND_IDLE        0
#define COMMAND_QUIT        1

/*=====================================================*/
/*=== DisplayIDInformation ============================*/
/*=====================================================*/

struct DisplayIDInformation
	{
	struct DisplayInfo   di_DisplayInfo;
	struct DimensionInfo di_DimensionInfo;
	struct MonitorInfo   di_MonitorInfo;
	UBYTE di_Brightness;
	};

/* These information should be enough. :-) */

#define FREEDISPLAYIDINFO(dinf) FreeServerData(dinf)
#define DISPLAYID(dinf)         dinf->di_DisplayInfo.Header.DisplayID
#define FILTEROUT(id,flags)     ((id) & ~(flags))
#define GETSTANDARDRECT(dinf)   &(dinf->di_DimensionInfo.Nominal)
#define GETMAXOSCANRECT(dinf)   &(dinf->di_DimensionInfo.MaxOScan)
#define GETVIDEOOSCANRECT(dinf) &(dinf->di_DimensionInfo.VideoOScan)
#define GETTXTOSCANRECT(dinf)   &(dinf->di_DimensionInfo.TxtOScan)
#define GETSTDOSCANRECT(dinf)   &(dinf->di_DimensionInfo.StdOScan)
#define GETBRIGHTNESS(dinf)     (dinf->di_Brightness)

#define RECTANGLEWIDTH(r)	((r)->MaxX - (r)->MinX + 1)
#define RECTANGLEHEIGHT(r)	((r)->MaxY - (r)->MinY + 1)

#define STILL_BLANKING (GetServerCommand()==COMMAND_IDLE)

/* Protypes for the functions you need to communicate with BServer */

BOOL  __asm __saveds SendClientMsg( register __d0 ULONG );
ULONG __asm __saveds GetServerCommand( void );
ULONG __asm __saveds WaitServerCommand( void );
struct DisplayIDInformation *__asm __saveds OpenCommunication( void );
void  __asm __saveds CloseCommunication( register __a1 struct DisplayIDInformation * );

/* Feel free to use these functions */

void __asm __saveds SpritesOff( void );
void __asm __saveds SpritesOn( void );
BOOL __asm __saveds CheckAA( void );

#endif
