ShapeShifter External Video Driver Interface Specification (Level 2)
====================================================================

Level 1 (ShapeShifter 3.0d), 01.Aug.1995
 - Created

Level 2 (ShapeShifter 3.3), 12.Nov.1995
 - Added SHEV_Flags and SHEVF_DblWidthWin



The structure of an external video driver
-----------------------------------------

A ShapeShifter external video driver is a standard Amiga executable
that has a special identification at the beginning. It is loaded
with LoadSeg() by ShapeShifter and removed with UnLoadSeg().

The first bytes of the driver must be as follows:

	moveq	#0,d0
	rts
	dc.b	"SHAPEEXV"
	dc.l	PointerToTagList

The macro "EVHEADER" is provided to create such a header.

The "PointerToTagList" is a pointer to an array of TagItems containing
the following tags (the data type of the ti_Data field and whether the
Tag is mandatory, recommended or optional is given behind the Tag name):

SHEV_Level (LONG, Mandatory)
	The interface level the driver conforms to. ShapeShifter will
	tell you its interface level when SHEV_OpenScreen is called.
	You can think of the "levels" as a sort of version numbers.
	A new level will be introduced for every change to the interface
	that some driver (or ShapeShifter) may depend on. This document
	describes level 2. Absence of this tag will cause an error
	message.

SHEV_Version (LONG, Recommended)
	Version number of the driver. This is ignored by ShapeShifter.

SHEV_Revision (LONG, Recommended)
	Revision number of the driver. This is ignored by ShapeShifter.

SHEV_Name (APTR to string, Recommended)
	Name of the driver. This is currently not used by ShapeShifter.

SHEV_ID (APTR to string, Recommended)
	$VER identification string of the driver (including version/
	revision and date). This is currently not used by ShapeShifter.

SHEV_Author (APTR to string, Recommended)
	Name of the driver's author. This is currently not used by
	ShapeShifter.

SHEV_OpenScreen (APTR to code, Mandatory)
	Routine for opening a screen.

SHEV_CloseScreen (APTR to code, Mandatory)
	Routine for closing a screen.

SHEV_Refresh (APTR to code, Optional)
	Routine for refreshing the display. Only required if the driver
	uses the RTYPE_CUSTOM refresh type.

SHEV_LockDisplay (APTR to code, Optional)
	Routine for locking the screen base in memory and for fetching
	a pointer to the start of the display memory. Only required if
	the driver uses a refresh type other than RTYPE_NONE or
	RTYPE_CUSTOM and if the display memory may move.

SHEV_UnlockDisplay (APTR to code, Optional)
	Routine for unlocking the screen base. Only required if the
	driver uses a refresh type other than RTYPE_NONE or RTYPE_CUSTOM
	and if the display memory may move.
	
SHEV_LoadRGB32 (APTR to code, Recommended)
	Routine for setting the color palette of indexed video modes.
	This routine is never called for VMODE_15BIT and VMODE_24BIT
	modes.

SHEV_PointerInvisible (APTR to code, Optional)
	Routine for blanking the Amiga mouse pointer.

SHEV_PointerVisible (APTR to code, Optional)
	Routine for making the Amiga mouse pointer visible.


Macintosh graphics basics
-------------------------

QuickDraw is very limited in its display memory handling. ShapeShifter
and your driver have to guarantee three points:

1. The display memory base provided by your driver that is passed to
   QuickDraw early in the startup phase must never change as long as
   the Mac is runnning. This is the reason why the Mac draws over the
   Workbench screen when both the Workbench screen and ShapeShifter's
   screen are on a CyberGraphX card because CyberGraphX swaps the
   display memory when switching screens and there is no way of telling
   QuickDraw the new base address.

2. The display memory must be a linear, processor accessible memory
   space. No segmentation is allowed. Drivers for cards without such
   display memory (like the A2410 and the Retina Z2) must provide a
   display buffer in RAM instead and refresh the display.

3. The pixel format of the display memory is always chunky and has to
   be one of the following:

   Depth  Bytes/Pixel  Meaning of each bit in four adjacent bytes
   --------------------------------------------------------------
       1          1/8  00000000 00000000 00000000 00000000 \
       2          2/8  10101010 10101010 10101010 10101010 | indexed
       4          4/8  32103210 32103210 32103210 32103210 |
       8            1  76543210 76543210 76543210 76543210 /
      15            2  xRRRRRGG GGGBBBBB xRRRRRGG GGGBBBBB \ direct
      24            4  xxxxxxxx RRRRRRRR GGGGGGGG BBBBBBBB /

   If the graphics card uses other pixel formats or color depths,
   the display must be refreshed.

QuickDraw must always be supplied with a display memory that conforms
to these points. This may be done by passing a pointer that points
directly to the display memory on the graphics card. But if the memory
on the card does not conform to these points, a conforming display buffer
in RAM has to be provided and the display must be refreshed.


How ShapeShifter calls your driver's routines; the "Context" concept
--------------------------------------------------------------------

The goal of this interface specification is a maximum of flexibility
and the possibility for future expansion without breaking existing
software. To achieve this, two basic concepts are used:

1. All communication between ShapeShifter and your driver is done via
   TagLists which store all input and output parameters for the routines
   you provide.

2. All of the driver's routines must be reentrant. The driver must NOT
   store global variables in a private data segment. Instead, global
   variables must be stored in a "Context" stucture that is passed to
   your driver whenever ShapeShifter calls one of its routines. The
   Context is treated as an abstract data structure by ShapeShifter, i.e.
   it never accesses the data, you can store everything you want in it,
   in any order. The Context is allocated by your driver in the
   SHEV_OpenScreen routine and passed to all other routines when they
   are called. The driver must free the Context in SHEV_CloseScreen.

All driver routines are called with "jsr" by ShapeShifter, so they
must all end with "rts". The routines must preserve all registers except
d0-d1/a0-a1. A video driver should be written in assembly language as
ShapeShifter passes the parameters in registers. The parameters are
always the same for every routine:

a0 Holds a pointer to a TagList with input parameters (i.e. parameters
   passed by ShapeShifter to the driver). The driver must not change
   this TagList, it must only read the tags with the functions provided
   by utility.library (GetTagData()/FindTagItem()). You should not depend
   on certain tags to be present and provide reasonable defaults. See
   the description of the driver routines below to find out which tags
   are optional and may therefore be missing.

a1 Holds a pointer to a TagList with output parameters (i.e. return
   values of the driver routines). This works as follows: ShapeShifter
   provides a list of Tags for the data it wants from the driver and
   the driver uses FindTagItem() from utility.library to find the Tags
   for which it has data to return and changes the ti_Data field of
   these tags. Changing the ti_Data fields is the only allowed operation
   on the output TagList. The driver must not replace or add its own
   Tags. If it has some data to return but it can't find a Tag for it,
   it should simply ignore this and throw the data away.

a2 Holds a pointer to the Context structure, except for the routine
   SHEV_OpenScreen that is used to allocate the Context. All global
   data needed by the driver routines should be stored in the Context.
   ShapeShifter will never dereference the Context pointer, it will
   only pass it in a2 when calling a driver routine. Future versions
   of ShapeShifter may allow multiple displays but only load the driver
   once. Then, the Context will be used to distinguish the displays
   by the driver.

a6 Holds a pointer to the base of utility.library and is provided for
   convenience. This may be cached locally by the driver.

All routines must provide an error code in d0. If no error occurs, zero
must be returned.

Be prepared that the routines of a single driver may be called multiple
times with different Contexts. The only routines that are guaranteed
not to be called several times at once are SHEV_OpenScreen and
SHEV_CloseScreen. All other routines must be completely reentrant and
must store global data only in the Context structure.


Refreshing the display: How and when
------------------------------------

ShapeShifter supports three types of video refresh selected in the
SHEV_OpenScreen routine by returning an appropriate value in the
SHEV_RefreshType tag:

1. RTYPE_NONE: No refresh. The Macintosh may write directly to the
   display memory which conforms to the three points outlined above.

2. RTYPE_CUSTOM: The driver provides a SHEV_Refresh routine that
   refreshes the display and is called periodically by ShapeShifter.

3. Other refresh types: Use one of ShapeShifter's refresh routines.
   ShapeShifter has built-in routines for the most common 15 and 24 bit
   pixel formats that also use the 68040's MMU (if present) to speed
   things up. The driver provides the SHEV_LockDisplay and
   SHEV_UnlockDisplay routines that return a pointer to the display
   memory and lock it as long as the refresh lasts. A SHEV_Refresh
   routine is not required as the refresh is done by ShapeShifter.
   If the display memory of the card never moves, even the
   SHEV_(Un)LockDisplay routines are not required as the display base
   address is returned by SHEV_OpenScreen anyway. The display memory
   must not be segmented.


Description of the driver routines
----------------------------------

Every routine a driver can provide is now described along with the
meaning of the input and ouput Tags that are passed to it. Certain tags
are guaranteed to be present in the TagLists (those marked with "Always
present"). All others are optional and you should fall back to reasonable
defaults for input Tags. Output Tags with missing "Always present" are
NOT optional. You should always provide a return value for them if you
find them.

See the description of the driver header TagList above to find out which
routines are mandatory and which are optional.


SHEV_OpenScreen
---------------

Description:

This routine is used to open a screen on the graphics card, allocate
a Context structure and set up everything necessary for the other
routines. It must return a pointer to an Intuition screen. This is
the only routine that won't be passed a Context pointer in a2.


Input Tags:

SHEV_Level (LONG, Always present)
	The interface level to which the version of ShapeShifter your
	driver runs under conforms to. If your driver absolutely requires
	features that are only present starting with a certain level,
	you should check this value and display an error message if
	a higher level is needed. You can think of the "level" as a
	sort of version number. A new level will be introduced for every
	change to the interface	that some driver (or ShapeShifter) may
	depend on. This document describes level 2.

SHEV_ScreenX (LONG, Optional)
	The desired width of the screen as selected by the user.
	This will always be an even multiple of 16.

SHEV_ScreenY (LONG, Optional)
	The desired height of the screen as selected by the user.

SHEV_DisplayID (LONG, Optional)
	The display ID as selected by the user. If you don't support
	display IDs, you should ignore it and base your screen mode
	selection on the screen dimensions instead.

SHEV_OverscanType (LONG, Optional)
	The overscan type (OSCAN_*) as selected by the user.

SHEV_VideoMode (LONG, Always present)
	The bit depth of the display as selected by the user. It may
	be one of the following:
	 VMODE_1BIT	1 bit per pixel, 2 colors, indexed
	 VMODE_2BIT	2 bits per pixel, 4 colors, indexed
	 VMODE_4BIT	4 bits per pixel, 16 colors, indexed
	 VMODE_8BIT	8 bits per pixel, 256 colors, indexed
	 VMODE_15BIT	16 bits per pixel, 32768 colors, direct
	 VMODE_24BIT	32 bits per pixel, 16 mio. colors, direct


Output Tags:

SHEV_Context (APTR, Always present)
	Your SHEV_OpenScreen routine must allocate a Context and store
	it here. Otherwise, ShapeShifter will display an error message.
	The Context is passed to all other routines and must be used
	to store global variables. It is never accessed by ShapeShifter.

SHEV_Screen (APTR, Always present)
	You must return a pointer to an Intuition screen here on which
	ShapeShifter can open a window. This screen should be "bound"
	to the display of the graphics card if possible (this is always
	the case for Intuition emulators). Don't worry about the color
	palette. This complete palette will be loaded with SHEV_LoadRGB32
	when the Mac starts.

SHEV_ScreenBase (APTR)
	The meaning of this field depends on what you return in
	SHEV_RefreshType. For RTYPE_NONE and RTYPE_CUSTOM, it is a
	pointer to the Mac display memory where QuickDraw may directly
	write into. For the other refresh types, this is the base
	address of the graphics card memory that is required by
	ShapeShifter's refresh routines.

SHEV_BytesPerRow (APTR)
	Here, you must return the number of bytes in one pixel row
	of the screen memory that SHEV_ScreenBase points to, be it
	the Mac display memory or the graphics card memory.

SHEV_RefreshType (LONG)
	In this Tag, you return the type of refresh required for the
	display (RTYPE_*, see above).

SHEV_Flags (LONGBITS) (Level 2)
	This is used to store special flag bits for ShapeShifter.
	Currently, only one bit is defined: SHEVB_DblWidthWin will
	instruct ShapeShifter to open a window of twice the SHEV_ScreenX
	width (used by the Graffiti driver).


SHEV_CloseScreen
----------------

Description:

This routine closes a screen opened with SHEV_OpenScreen and frees the
Context structure. This routine will always be called, even if
SHEV_OpenScreen failed, so be prepared to handle uninitialized variables,
NULL pointers etc. You can only make one assumption: The Context pointer
in a2 will always be valid. If you SHEV_OpenScreen routines returns a
NULL pointer in SHEV_Context or doesn't set SHEV_Context at all,
ShapeShifter will display an error message and SHEV_CloseScreen will not
be called.


Input Tags:

None (Note this! You must store the screen pointer in your Context!)


Output Tags:

None


SHEV_Refresh
------------

Description:

This routine is needed if your SHEV_OpenScreen returned a refresh type
of RTYPE_CUSTOM. It will be called in regular intervals by ShapeShifter
and should copy and convert the Mac screen buffer (a pointer to which the
SHEV_OpenScreen routine returned in SHEV_ScreenBase) to the card's
display memory.


Input Tags:

None


Output Tags:

None


SHEV_LockDisplay
----------------

Description:

This routine is needed if your SHEV_OpenScreen returned a refresh type
other than RTYPE_NONE or RTYPE_CUSTOM (i.e. one of ShapeShifter's
built-in refresh routines should be used) and the display memory that
the SHEV_OpenScreen routine returned in SHEV_ScreenBase is in danger
of being swapped or moved. ShapeShifter will call this routine to
get the current display memory base address just before it refreshes
the screen. If possible, this routine should also lock the screen
buffer in memory. After the refresh is done, ShapeShifter calls
SHEV_UnlockDisplay to undo the locking.


Input Tags:

None


Output Tags:

SHEV_ScreenBase (APTR, Always present)
	Here, you must return the base address of the graphics card
	memory.


SHEV_UnlockDisplay
------------------

Description:

This routine is called by ShapeShifter after a built-in refresh routine
has completed to undo everything that SHEV_LockDisplay did. See the
description of SHEV_LockDisplay for more details.


Input Tags:

None


Output Tags:

None


SHEV_LoadRGB32
--------------

Description:

This routine sets the complete color palette of the screen when the
video mode is an indexed one (1, 2, 4 or 8 bit). It will never be called
for VMODE_15BIT and VMODE_24BIT displays.


Input Tags:

SHEV_ColorTable (APTR)
	This is a pointer to an array of red/green/blue color values,
	each 32-bit in size, starting with color register 0 and
	containing the full number of entries for the video mode being
	used (i.e. 2/4/16/256 entries for 1/2/4/8 bit modes). For example,
	for a 2 bit screen, the color table will look like this:
	R0,G0,B0,R1,G1,B1,R2,G2,B2,R3,G3,B3 (each value being a longword)


Output Tags:

None


SHEV_PointerInvisible
---------------------

Description:

This routine blanks out the Amiga mouse pointer on the screen. If you
don't provide it, ShapeShifter will use Intuition/SetPointer().


Input Tags:

None


Output Tags:

None


SHEV_PointerVisible
-------------------

Description:

This routine makes the Amiga mouse pointer reappear. If you don't provide
it, ShapeShifter will use Intuition/ClearPointer().


Input Tags:

None


Output Tags:

None
