home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
200-299
/
ff281.lzh
/
LoadImage
/
Cycling.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-11-20
|
9KB
|
457 lines
/******************************************************************************
*
* Cycling.c 01/07/89 by: Olaf Barthel
* Brabeckstrasse 35
* D-3000 Hannover 71
*
* Federal Republic of Germany
*
* Cycling 1.5 (C) Copyright 1989 by Olaf Barthel & ED Hannover
*
* Not even a single character of this wonderful piece of code
* may be incorporated into any other program without the
* author's consent. Yep, still a splendid time is guaranteed
* for all!
*
*******************************************************************************
*
* Cycling contains colour cycling support routines for LoadImage.c,
* and is based on example source code written by Carolin Scheppner
* (Display.c). This version uses interrupt code to handle the
* cycling job.
*
******************************************************************************/
#include <graphics/gfxbase.h>
#include <exec/interrupts.h>
#include <graphics/view.h>
#include <exec/memory.h>
#include <stdio.h>
/* The typical format of a DPaint colour cycling range. */
typedef struct
{
WORD pad1; /* Not used. */
WORD rate; /* Cycling speed. */
WORD active; /* Is it active? Which way is it cycling? */
UBYTE low,high; /* Start and stop colour. */
} CRange;
/* LoadCycleRange needs these macros. */
#define CRNG_NORATE 36 /* Don't cycle this range. */
#define CRNG_ACTIVE 1 << 0 /* This range is active. */
#define CRNG_REVERSE 1 << 1 /* This range is cycling backwards. */
/* The following values are to controll the interrupt code. */
#define CY_CYCL 0 /* Keep on cycling. */
#define CY_WAIT 1 /* Don't cycle, wait for startup message. */
/* A sole forward declaration. */
extern BOOL FindChunk();
/* CycleCode needs this data, InitCycleCode prepares it. */
struct ViewPort *cy_VPort; /* Where to cycle. */
struct Interrupt cy_VBlank; /* The Cycling-interrupt. */
CRange *cy_Range; /* The cycling-ranges. */
LONG cy_RangeNum; /* The number of ranges. */
UWORD cy_ColMap[32]; /* The colourmap. */
LONG cy_ColNum; /* The number of colours. */
short cy_TicksPassed[16]; /* Event counter for ranges. */
UWORD cy_TempCol; /* Temporary colour buffer. */
UWORD cy_UndoBuffer[32];
short cy_WeAreWaiting; /* CycleCode is waiting. */
short cy_Command; /* What is the CycleCode up to do? */
BOOL cy_CodeRun = FALSE; /* Is the CycleCode already running? */
extern void VBlankHandler();
#asm
_VBlankHandler: MOVEM.L A2-A6/D2-D7,-(A7) ; Save some registers
JSR _geta4# ; Adjust data register
JSR _CycleCode ; Call 'C' routine
CLR.L D0 ; D0 must be cleared
; or strange things will
; happen
MOVEM.L (A7)+,A2-A6/D2-D7 ; Restore registers
RTS ; ...and go on
#endasm
/* CycleCode() :
*
* CycleCode is the 'C' cycling routine. It runs as an
* interrupt server to save task time.
*/
void
CycleCode()
{
register short i,j; /* Loop counter. */
/* Are we to wait? */
if(cy_Command == CY_WAIT)
{
/* Restore the original palette. */
if(!cy_WeAreWaiting)
LoadRGB4(cy_VPort,cy_UndoBuffer,cy_ColNum);
cy_WeAreWaiting = TRUE;
/* Don't continue to cycle. */
return;
}
/* We aren't waiting any more. */
if(cy_WeAreWaiting)
{
/* Re-initialize the palette. */
for(i = 0 ; i < cy_ColNum ; i++)
cy_ColMap[i] = cy_UndoBuffer[i];
/* Reset event counters. */
for(i = 0 ; i < cy_RangeNum ; i++)
cy_TicksPassed[i] = 0;
cy_WeAreWaiting = FALSE;
}
/* Now handle the cycle ranges. */
for(i = 0 ; i < cy_RangeNum ; i++)
{
/* Increment event counter. */
cy_TicksPassed[i]++;
/* Is this one up to cycle next? */
if(cy_TicksPassed[i] == cy_Range[i] . rate)
{
/* Reset event counter for this range. */
cy_TicksPassed[i] = 0;
/* Is this range active? */
if(!(cy_Range[i] . active & CRNG_ACTIVE))
continue;
/* Cycling backwards? */
if(cy_Range[i] . active & CRNG_REVERSE)
{
/* Move the colours. */
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
{
/* This one is cycling forwards. */
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;
}
/* Okay, everything has been moved, now
* load the new palette.
*/
LoadRGB4(cy_VPort,cy_ColMap,cy_ColNum);
}
}
}
/* InitCycleCode(ViewPort,ColMap,ColNum,Range,RangeNum) :
*
* Initializes all data and starts up the interrupt
* server.
*/
BOOL
InitCycleCode(ViewPort,ColMap,ColNum,Range,RangeNum)
struct ViewPort *ViewPort;
UWORD *ColMap;
LONG ColNum;
CRange *Range;
LONG RangeNum;
{
register short i;
/* Check for valid parameters. */
if(!ViewPort || !ColMap || !ColNum || !Range || !RangeNum)
return(FALSE);
/* Copy the data. */
cy_VPort = ViewPort;
cy_ColNum = ColNum;
cy_Range = Range;
cy_RangeNum = RangeNum;
for(i = 0 ; i < ColNum ; i++)
cy_ColMap[i] = ColMap[i];
/* Clear event counters. */
for(i = 0 ; i < cy_RangeNum ; i++)
cy_TicksPassed[i] = 0;
/* Copy the original palette to the undo buffer. */
for(i = 0 ; i < cy_ColNum ; i++)
cy_UndoBuffer[i] = cy_ColMap[i];
/* Let the CycleCode wait. */
cy_Command = CY_WAIT;
cy_WeAreWaiting = TRUE;
/* Ta Da! The CycleCode enters the stage!. */
cy_VBlank . is_Data = (APTR)NULL;
cy_VBlank . is_Code = VBlankHandler;
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 = "Cycling Interrupt";
AddIntServer(5,&cy_VBlank);
cy_CodeRun = TRUE;
return(TRUE);
}
/* ClearCycleCode() :
*
* Forces the CycleCode to hit and quit.
*/
void
ClearCycleCode()
{
register short i;
/* Is the interrupt already running? */
if(!cy_CodeRun)
return;
/* Tell it to wait. */
cy_WeAreWaiting = TRUE;
cy_Command = CY_WAIT;
/* Remove the server code. */
RemIntServer(5,&cy_VBlank);
/* Rebuild palette. */
for(i = 0 ; i < cy_ColNum ; i++)
cy_ColMap[i] = cy_UndoBuffer[i];
/* Wait for it to finish. */
WaitTOF();
WaitTOF();
WaitTOF();
/* Close the shop. */
cy_CodeRun = FALSE;
}
/* ToggleCycleCode() :
*
* Toggles the activity of the cycling code.
*/
void
ToggleCycleCode()
{
static short Mode = FALSE;
Mode ^= TRUE;
if(Mode)
cy_Command = CY_CYCL;
else
cy_Command = CY_WAIT;
WaitTOF();
}
/* IsCycling() :
*
* Returns the present status of the cycling code.
*/
short
IsCycling()
{
if(cy_Command == CY_CYCL)
return(TRUE);
if(cy_Command == CY_WAIT)
return(FALSE);
}
/* LoadCycleRange(FileName,Range,MaxRange) :
*
* Searches the IFF-ILBM-file for CRNG or CCRT
* chunks und initializes the colour-ranges.
*/
LONG
LoadCycleRange(FileName,Range,MaxRange)
char *FileName;
CRange *Range;
LONG MaxRange;
{
FILE *CycFile;
register short i;
/* GraphiCraft private cycling chunk. */
struct
{
WORD direction;
UBYTE start;
UBYTE end;
LONG seconds;
LONG microseconds;
WORD pad;
} CcrtChunk;
/* Clear all ranges. */
for(i = 0 ; i < MaxRange ; i++)
Range[i] . active = 0;
/* Open the file and try to locate the CRNG chunk. */
if(!(CycFile = fopen(FileName,"r")))
return(FALSE);
if(FindChunk("CRNG",CycFile))
{
/* Read all ranges. */
for(i = 0 ; i < MaxRange ; i++)
{
fread(&Range[i],sizeof(CRange),1,CycFile);
/* Carefully determine the activity
* of the chunk.
*/
if(Range[i] . active == CRNG_NORATE || !Range[i] . rate || Range[i] . low == Range[i] . high)
Range[i] . active = 0;
/* Recalculate speed value. */
if(Range[i] . rate > 0)
Range[i] . rate = 16384 / Range[i] . rate;
else
Range[i] . rate = 0;
/* Finished reading the chunks? */
if(!FindChunk("CRNG",CycFile))
{
i++;
break;
}
}
}
else
{
/* Didn't find a CRNG chunk, try to find a
* CCRT chunk.
*/
fseek(CycFile,0,0);
if(FindChunk("CCRT",CycFile))
{
for(i = 0 ; i < MaxRange ; i++)
{
fread(&CcrtChunk,sizeof(CcrtChunk),1,CycFile);
/* We have located a CCRT chunk, now
* make it a CRNG chunk.
*/
Range[i] . low = CcrtChunk . start;
Range[i] . high = CcrtChunk . end;
if(CcrtChunk . direction != 0)
Range[i] . active = CRNG_ACTIVE;
else
Range[i] . active = 0;
if(CcrtChunk . direction > 0)
Range[i] . active |= CRNG_REVERSE;
/* Recalculate speed (by
* Carolyn Scheppner).
*/
Range[i] . rate = 16384 / (CcrtChunk . seconds * 60 + (CcrtChunk . microseconds + 8334) / 16667);
if(!Range[i] . rate || Range[i] . low == Range[i] . high)
Range[i] . active = 0;
if(Range[i] . rate > 0)
Range[i] . rate = 16384 / Range[i] . rate;
else
Range[i] . rate = 0;
if(!FindChunk("CCRT",CycFile))
{
i++;
break;
}
}
}
else
{
/* Seems that we failed. */
fclose(CycFile);
return(FALSE);
}
}
fclose(CycFile);
return(i);
}