/*

Directory Opus 4
Original GPL release version 4.12
Copyright 1993-2000 Jonathan Potter

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

All users of Directory Opus 4 (including versions distributed
under the GPL) are entitled to upgrade to the latest version of
Directory Opus version 5 at a reduced price. Please see
http://www.gpsoft.com.au for more information.

The release of Directory Opus 4 under the GPL in NO WAY affects
the existing commercial status of Directory Opus 5.

*/

#include "DOpus.h"

static struct ViewPort *cy_VPort;
static struct Interrupt cy_VBlank;
static CRange *cy_Range;
static LONG cy_RangeNum,cy_ColNum;
static UWORD cy_ColMap[64],cy_TempCol,cy_UndoBuffer[64];
static short cy_TicksPassed[16],cy_WeAreWaiting,cy_Command;
static BOOL cy_CodeRun=FALSE;

void __saveds colourcycle()
{
	short i,j;

	if (cy_Command==CY_WAIT) {
		if (!cy_WeAreWaiting) LoadRGB4(cy_VPort,cy_UndoBuffer,cy_ColNum);
		cy_WeAreWaiting=TRUE;
		return;
	}
	if (cy_WeAreWaiting) {
		for (i=0;i<cy_ColNum;i++) cy_ColMap[i]=cy_UndoBuffer[i];
		for (i=0;i<cy_RangeNum;i++) cy_TicksPassed[i]=0;
		cy_WeAreWaiting=FALSE;
	}

	for (i=0;i<cy_RangeNum;i++) {
		cy_TicksPassed[i]++;
		if (cy_TicksPassed[i]==cy_Range[i].rate) {
			cy_TicksPassed[i]=0;
			if (!(cy_Range[i].active&CRNG_ACTIVE)) continue;
			if (cy_Range[i].active&CRNG_REVERSE) {
				cy_TempCol=cy_ColMap[cy_Range[i].low];
				for (j=cy_Range[i].low;j<cy_Range[i].high;j++)
					cy_ColMap[j]=cy_ColMap[j+1];
				cy_ColMap[cy_Range[i].high]=cy_TempCol;
			}
			else {
				cy_TempCol=cy_ColMap[cy_Range[i].high];
				for (j=cy_Range[i].high;j>cy_Range[i].low;j--)
					cy_ColMap[j]=cy_ColMap[j-1];
				cy_ColMap[cy_Range[i].low]=cy_TempCol;
			}
			LoadRGB4(cy_VPort,cy_ColMap,cy_ColNum);
		}
	}
}

initcycle(ViewPort,ColMap,ColNum,Range,RangeNum)
struct ViewPort *ViewPort;
UWORD *ColMap;
int ColNum;
CRange *Range;
int RangeNum;
{
	register short i;

	if (!ViewPort || !ColMap || !ColNum || ColNum>64 || !Range || !RangeNum) return(FALSE);

	cy_VPort=ViewPort;
	cy_ColNum=ColNum;
	cy_Range=Range;
	cy_RangeNum=RangeNum;

	for (i=0;i<ColNum;i++) cy_ColMap[i]=ColMap[i];
	for (i=0;i<cy_RangeNum;i++) cy_TicksPassed[i]=0;
	for (i=0;i<cy_ColNum;i++) cy_UndoBuffer[i]=cy_ColMap[i];

	cy_Command=CY_WAIT;
	cy_WeAreWaiting=TRUE;
	cy_VBlank.is_Data=(APTR)NULL;
	cy_VBlank.is_Code=colourcycle;
	cy_VBlank.is_Node.ln_Succ=NULL;
	cy_VBlank.is_Node.ln_Pred=NULL;
	cy_VBlank.is_Node.ln_Type=NT_INTERRUPT;
	cy_VBlank.is_Node.ln_Pri=0;
	cy_VBlank.is_Node.ln_Name="dopus_cycle";
	AddIntServer(INTB_VERTB,&cy_VBlank);
	cy_CodeRun=TRUE;
	return(TRUE);
}

void stopcycle()
{
	register short i;

	if (!cy_CodeRun) return;
	cy_WeAreWaiting=TRUE;
	cy_Command=CY_WAIT;
	RemIntServer(INTB_VERTB,&cy_VBlank);
	for (i=0;i<cy_ColNum;i++) cy_ColMap[i]=cy_UndoBuffer[i];
	WaitTOF();
	WaitTOF();
	WaitTOF();
	cy_CodeRun=FALSE;
}

void togglecycle()
{
	static short Mode=FALSE;

	Mode^=TRUE;
	cy_Command=(Mode)?CY_CYCL:CY_WAIT;
	WaitTOF();
}

checkcycling()
{
	return(cy_Command==CY_CYCL);
}
