/*
 * MandelVroom 2.0
 *
 * (c) Copyright 1987,1989  Kevin L. Clague, San Jose, CA
 *
 * All rights reserved.
 *
 * Permission is hereby granted to distribute this program's source
 * executable, and documentation for non-comercial purposes, so long as the
 * copyright notices are not removed from the sources, executable or
 * documentation.  This program may not be distributed for a profit without
 * the express written consent of the author Kevin L. Clague.
 *
 * This program is not in the public domain.
 *
 * Fred Fish is expressly granted permission to distribute this program's
 * source and executable as part of the "Fred Fish freely redistributable
 * Amiga software library."
 *
 * Permission is expressly granted for this program and it's source to be
 * distributed as part of the Amicus Amiga software disks, and the
 * First Amiga User Group's Hot Mix disks.
 *
 * contents: this file contains the functions to manage the task that
 * performs the color cycling.
 */

#include "mandp.h"

/* Cycle Task stuff */
#define CYCLETIME  16384L
#define ACTIVE     0x01

extern VOID cycleTask();
char  *cyTaskName = "CycleTask";
struct Task *cyTask;

/* Data shared with cycleTask */
CrngChunk       *cyCrngs;
struct ViewPort *cyVport;
int    cyRegs, cyCnt;
BOOL   CycleOn, PrepareToDie;
USHORT cyMap[maxColorReg];
LONG   cyClocks[maxCycles];
LONG   cyRates[maxCycles];

extern LONG MainPri;

CreateCycle()
{
   extern int Num_vp_Colors;

   if (cyTask) {
     KillCycle();
     LoadRGB4(vp, CurPict->RGBs, Num_vp_Colors);
   }

   /* Set up cycle task */

   initCycle(CurPict, Num_vp_Colors, 4, vp);

   cyTask = (struct Task *)CreateTask(cyTaskName,MainPri,cycleTask,4000);

   if(!cyTask) {
     DispErrMsg("Can't create cycling task",0);
     return;
   }
   CycleOn = TRUE;
}

KillCycle()
{
   if (cyTask) {
      CycleOn = FALSE;
      PrepareToDie = TRUE;
      while(PrepareToDie);
      DeleteTask(cyTask);
      cyTask = NULL;
      LoadRGB4(vp, CurPict->RGBs, Num_vp_Colors);
   }
}


initCycle(Pict, Regs, Cnts, vp)
  struct Picture *Pict;
  int Regs, Cnts;
  struct ViewPort *vp;
{
   int k;

   CycleOn  = FALSE;
   PrepareToDie = FALSE;
   cyCrngs  = Pict->Crngs;
   cyVport  = vp;
   cyRegs   = Regs;
   cyCnt    = Cnts;

   for(k=0; k<cyRegs; k++) {
      cyMap[k] = Pict->RGBs[k];
   }

   /* Init Rates and Clocks */
   for(k=0; k<cyCnt; k++) {

      /* In DPaint CRNG, rate = RNG_NORATE (36) means don't cycle */

      if(cyCrngs[k].rate == RNG_NORATE) {
         cyCrngs[k].rate = 0;
         cyCrngs[k].active &= ~ACTIVE;
      }

      if((cyCrngs[k].active & ACTIVE)&&(cyCrngs[k].rate)) {
         cyRates[k] = cyCrngs[k].rate;
      } else {
         cyRates[k] = 0;  /* Means don't cycle to my cycleTask */
      }
      cyClocks[k] = 0;
   }
}


VOID cycleTask()
   {
   int    k, i, j;
   UBYTE  low, high;
   USHORT cyTmp;
   BOOL   Cycled;

   geta4();

   while (!PrepareToDie) {
      WaitTOF();

      if (CycleOn) {
         Cycled = FALSE;

         for(k=0; k<cyCnt; k++) {

            if(cyCrngs[k].rate)  /* cyRate 0 = inactive */ {

               cyClocks[k] += cyCrngs[k].rate;

               if(cyClocks[k] >= CYCLETIME) {

                  Cycled = TRUE;
                  cyClocks[k] -= CYCLETIME;
                  low = cyCrngs[k].low;
                  high= cyCrngs[k].high;

                  if(cyCrngs[k].active & REVERSE) { /* Reverse cycle */
                     cyTmp = cyMap[low];

                     for(i=low,j=low+1; i < high; i++,j++) {
                        cyMap[i] = cyMap[j];
                     }
                     cyMap[high] = cyTmp;
                  } else {    /* Forward cycle */
                     cyTmp = cyMap[high];
                     for(i=high,j=high-1; i > low; i--,j--) {
                        cyMap[i] = cyMap[j];
                     }
                     cyMap[low] = cyTmp;
                  }
               }
            }
         }
         if(Cycled) {
            LoadRGB4(cyVport,cyMap,cyRegs);
         }
      }
   }
   PrepareToDie = FALSE;
   while(TRUE);  /* Busy wait to die */
}

