/*****************************************************************************
* FRAME buffered ZVG driver routines.
*
* Author:       Zonn Moore
* Created:      05/20/03
*
* History:
*    07/02/03
*       Moved spotkiller logic to zvgEnc.c. Added calls to 'zvgSOF()' to
*       handle spotkiller.
*
*    07/01/03
*       Moved Color to B&W conversions to 'zvgEnc.c'.
*
*    06/30/03
*       Do Color to B&W conversions. Limit colors instead of masking them.
*
*    06/29/03
*       Yet another adjustment to spotkill.  RipOff was still occasionally
*       triggering the spotkiller.  Set new boundary to require at least
*       a 3/4 screen deflection before spotkill dots are not drawn.
*
*    06/26/03
*       Moved the spotkiller tests to zvgEnc.c since the comparisons must
*       be made after clipping. Blank POINTs are still generated here since
*       the encoder doesn't know how to send data to the next frame.
*
*    06/20/03
*       Added spotkiller killer code.  Looks for screens the would cause
*       the spotkiller to activate, and if found, send some "blank" dots
*       to keep the spotkiller from activating.
*
* (c) Copyright 2003-2004, Zektor, LLC.  All Rights Reserved.
*****************************************************************************/

#include	"zstddef.h"
#include	"zvgPort.h"
#include	"zvgEnc.h"
//#include	"zvgError.h"

#define	MAME										// if set, indicate this compile is to be used with MAME

// Allocate a small encode buffer used to buffer commands generated by the
// ZVG encoder.

uchar			EncodeBfr[zENC_CMD_SIZE*10];

// Keep track of status information returned from the ZVG

ZvgSpeeds_a	ZvgSpeeds;
ZvgMon_s	ZvgMon;
ZvgID_s		ZvgID;

/*****************************************************************************
* Intialize the ZVG, setup DMA buffers, etc.
*
* This routine is called before anything ZVG related is done.
*****************************************************************************/
uint zvgFrameOpen( void)
{

	uint	err;

	// look for the ZVG

	err = zvgInit();

	// read IEEE version information data from ZVG

	if (!err)
		err = zvgReadDeviceID( &ZvgID);

	// read Monitor setup information from ZVG

	if (!err)
		err = zvgReadMonitorInfo( &ZvgMon);

	// read Speed table information for ZVG

	if (!err)
		err = zvgReadSpeedInfo( ZvgSpeeds);

	// reset the ZVG encoder, point to encoder scratch buffer

	if (!err)
	{	zvgEncReset();							// reset ZVG encoder
		zvgEncSetPtr( EncodeBfr);					// point to local encode buffer

		// move monitor flags from environment variable to encoder flags

		if (ZvgIO.envMonitor & MONF_FLIPX)
			ZvgENC.encFlags |= ENCF_FLIPX;

		if (ZvgIO.envMonitor & MONF_FLIPY)
			ZvgENC.encFlags |= ENCF_FLIPY;

		if (ZvgIO.envMonitor & MONF_SPOTKILL)
			ZvgENC.encFlags |= ENCF_SPOTKILL;

		if (ZvgIO.envMonitor & MONF_BW)
			ZvgENC.encFlags |= ENCF_BW;

		if (ZvgIO.envMonitor & MONF_NOOVS)
		{	ZvgENC.encFlags |= ENCF_NOOVS;
			zvgEncSetClipNoOverscan();
		}
	}

	if (err)
		zvgClose();										// if any error occurred, fix everything

	return (err);
}

/*****************************************************************************
* Setup ZVG for buffered frame use.
*****************************************************************************/
void zvgFrameClose( void)
{
	zvgClose();											// restore everything but the timers
}

/*****************************************************************************
* Encode and Send a single vector to the DMA buffer.
*
* For this call, a vector is an absolute position on the screen. The screen's
* dimensions are:
*
*    Upper Left Corner:  X = -512, Y =  383
*    Center of screen:   X =    0, Y =    0
*    Lower Right Corner: X =  511, Y = -384
*
* The screen may be overscanned by 1.25 inches (on a 19" monitor), the
* screen's dimensions with overscan are:
*
*    Upper Left Corner:  X = -600, Y =  471
*    Center of screen:   X =    0, Y =    0
*    Lower Right Corner: X =  599, Y = -472
*
* So the screen is laid out like a peice of graph paper in math class with
* X getting larger as it moves to the right, and Y getting larger as it
* moves upwards.  The orgin: 0,0 is located at the center of the screen.
*
* The color of the vector must have been previously set by a call to one
* of the set color routines.
*
* Called with:
*    xStart = Starting X position of vector.
*    yStart = Starting Y position of vector.
*    xEnd   = Ending X position of vector.
*    yEnd   = Ending Y position of vector.
*
*****************************************************************************/
uint zvgFrameVector( uint xStart, uint yStart, uint xEnd, uint yEnd)
{
	uint	err;

	// Encoode vector into 'EncodeBfr[]'

	zvgEnc( xStart, yStart, xEnd, yEnd);

	// move encoded ZVG command into DMA buffer

	err = zvgDmaPutMem( EncodeBfr, zvgEncSize());

	// clear the encode buffer

	zvgEncClearBfr();

	return (err);
}

/*****************************************************************************
* Send the current buffer to the ZVG.
*****************************************************************************/
uint zvgFrameSend(void)
{
	uint	err;

	// Send End of Frame info. (Center Trace, pad ZVG buffer)
	zvgEncEOF();

	err = zvgDmaPutMem( EncodeBfr, zvgEncSize());

	if (err)
		return (err);

	// wait for the end of the frame, using the timer functions
	//tmrWaitForFrame();

	zvgEncClearBfr();				// Clear the encode buffer

	// Start the DMA transfer of the encoded command in the DMA buffer to
	// the ZVG.  SCJ: NEED TO DO A "PREV SWAP!", since the "current" buffer will
	// have bupkis in it due to having no points in the frame!!!

	//if(npoints > 0)
	//{
		err = zvgDmaSendSwap();		// send the current buffer and swap DMA buffers
	//}
	//else
	//{
	//	err = zvgDmaSendPrev();		// if there are no points, send previous
	//}

	if (err)
		return (err);

	// Start next buffer with spot kill stuff if needed

	zvgEncSOF();

	err = zvgDmaPutMem( EncodeBfr, zvgEncSize());

	if (err)
		return (err);

	zvgEncClearBfr();				// Clear the encode buffer
	return (errOk);
}
