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 >
C/C++ Source or Header  |  1989-11-20  |  9KB  |  457 lines

  1. /******************************************************************************
  2. *
  3. *    Cycling.c 01/07/89 by:    Olaf Barthel
  4. *                Brabeckstrasse 35
  5. *                D-3000 Hannover 71
  6. *
  7. *                Federal Republic of Germany
  8. *
  9. *    Cycling 1.5 (C) Copyright 1989 by Olaf Barthel & ED Hannover
  10. *
  11. *    Not  even  a  single character of this wonderful piece of code
  12. *    may  be  incorporated  into  any  other  program  without  the
  13. *    author's  consent.   Yep,  still a splendid time is guaranteed
  14. *    for all!
  15. *
  16. *******************************************************************************
  17. *
  18. *    Cycling  contains colour cycling support routines for LoadImage.c,
  19. *    and is based on example source code written by Carolin Scheppner
  20. *    (Display.c). This version uses interrupt code to handle the
  21. *    cycling job.
  22. *
  23. ******************************************************************************/
  24.  
  25. #include <graphics/gfxbase.h>
  26. #include <exec/interrupts.h>
  27. #include <graphics/view.h>
  28. #include <exec/memory.h>
  29. #include <stdio.h>
  30.  
  31.     /* The typical format of a DPaint colour cycling range. */
  32.  
  33. typedef struct
  34. {
  35.     WORD pad1;    /* Not used. */
  36.     WORD rate;    /* Cycling speed. */
  37.     WORD active;    /* Is it active? Which way is it cycling? */
  38.     UBYTE low,high;    /* Start and stop colour. */
  39. } CRange;
  40.  
  41.     /* LoadCycleRange needs these macros. */
  42.  
  43. #define CRNG_NORATE    36    /* Don't cycle this range. */
  44. #define CRNG_ACTIVE    1 << 0    /* This range is active. */
  45. #define CRNG_REVERSE    1 << 1    /* This range is cycling backwards. */
  46.  
  47.     /* The following values are to controll the interrupt code. */
  48.  
  49. #define CY_CYCL 0    /* Keep on cycling. */
  50. #define CY_WAIT    1    /* Don't cycle, wait for startup message. */
  51.  
  52.     /* A sole forward declaration. */
  53.  
  54. extern BOOL FindChunk();
  55.  
  56.     /* CycleCode needs this data, InitCycleCode prepares it. */
  57.  
  58. struct ViewPort    *cy_VPort;        /* Where to cycle. */
  59. struct Interrupt cy_VBlank;        /* The Cycling-interrupt. */
  60. CRange        *cy_Range;        /* The cycling-ranges. */
  61. LONG         cy_RangeNum;        /* The number of ranges. */
  62. UWORD         cy_ColMap[32];        /* The colourmap. */
  63. LONG         cy_ColNum;        /* The number of colours. */
  64. short         cy_TicksPassed[16];    /* Event counter for ranges. */
  65. UWORD         cy_TempCol;        /* Temporary colour buffer. */
  66. UWORD         cy_UndoBuffer[32];
  67. short         cy_WeAreWaiting;    /* CycleCode is waiting. */
  68. short         cy_Command;        /* What is the CycleCode up to do? */
  69. BOOL         cy_CodeRun = FALSE;    /* Is the CycleCode already running? */
  70.  
  71. extern void VBlankHandler();
  72.  
  73. #asm
  74. _VBlankHandler:    MOVEM.L    A2-A6/D2-D7,-(A7)    ; Save some registers
  75.  
  76.         JSR    _geta4#            ; Adjust data register
  77.         JSR    _CycleCode        ; Call 'C' routine
  78.  
  79.         CLR.L    D0            ; D0 must be cleared
  80.                         ; or strange things will
  81.                         ; happen
  82.  
  83.         MOVEM.L    (A7)+,A2-A6/D2-D7    ; Restore registers
  84.  
  85.         RTS                ; ...and go on
  86. #endasm
  87.  
  88.     /* CycleCode() :
  89.      *
  90.      *    CycleCode is the 'C' cycling routine. It runs as an
  91.      *    interrupt server to save task time.
  92.      */
  93.  
  94. void
  95. CycleCode()
  96. {
  97.     register short i,j;    /* Loop counter. */
  98.  
  99.         /* Are we to wait? */
  100.  
  101.     if(cy_Command == CY_WAIT)
  102.     {
  103.             /* Restore the original palette. */
  104.  
  105.         if(!cy_WeAreWaiting)
  106.             LoadRGB4(cy_VPort,cy_UndoBuffer,cy_ColNum);
  107.  
  108.         cy_WeAreWaiting = TRUE;
  109.  
  110.             /* Don't continue to cycle. */
  111.  
  112.         return;
  113.     }
  114.  
  115.         /* We aren't waiting any more. */
  116.  
  117.     if(cy_WeAreWaiting)
  118.     {
  119.             /* Re-initialize the palette. */
  120.  
  121.         for(i = 0 ; i < cy_ColNum ; i++)
  122.             cy_ColMap[i] = cy_UndoBuffer[i];
  123.  
  124.             /* Reset event counters. */
  125.  
  126.         for(i = 0 ; i < cy_RangeNum ; i++)
  127.             cy_TicksPassed[i] = 0;
  128.  
  129.         cy_WeAreWaiting = FALSE;
  130.     }
  131.  
  132.         /* Now handle the cycle ranges. */
  133.  
  134.     for(i = 0 ; i < cy_RangeNum ; i++)
  135.     {
  136.             /* Increment event counter. */
  137.  
  138.         cy_TicksPassed[i]++;
  139.  
  140.             /* Is this one up to cycle next? */
  141.  
  142.         if(cy_TicksPassed[i] == cy_Range[i] . rate)
  143.         {
  144.                 /* Reset event counter for this range. */
  145.  
  146.             cy_TicksPassed[i] = 0;
  147.  
  148.                 /* Is this range active? */
  149.  
  150.             if(!(cy_Range[i] . active & CRNG_ACTIVE))
  151.                 continue;
  152.  
  153.                 /* Cycling backwards? */
  154.  
  155.             if(cy_Range[i] . active & CRNG_REVERSE)
  156.             {
  157.                     /* Move the colours. */
  158.  
  159.                 cy_TempCol = cy_ColMap[cy_Range[i] . low];
  160.  
  161.                 for(j = cy_Range[i] . low ; j < cy_Range[i] . high ; j++)
  162.                     cy_ColMap[j] = cy_ColMap[j + 1];
  163.  
  164.                 cy_ColMap[cy_Range[i] . high] = cy_TempCol;
  165.             }
  166.             else
  167.             {
  168.                     /* This one is cycling forwards. */
  169.  
  170.                 cy_TempCol = cy_ColMap[cy_Range[i] . high];
  171.  
  172.                 for(j = cy_Range[i] . high ; j > cy_Range[i] . low ; j--)
  173.                     cy_ColMap[j] = cy_ColMap[j - 1];
  174.  
  175.                 cy_ColMap[cy_Range[i] . low] = cy_TempCol;
  176.             }
  177.  
  178.                 /* Okay, everything has been moved, now
  179.                  * load the new palette.
  180.                  */
  181.  
  182.             LoadRGB4(cy_VPort,cy_ColMap,cy_ColNum);
  183.         }
  184.     }
  185. }
  186.  
  187.     /* InitCycleCode(ViewPort,ColMap,ColNum,Range,RangeNum) :
  188.      *
  189.      *    Initializes all data and starts up the interrupt
  190.      *    server.
  191.      */
  192.  
  193. BOOL
  194. InitCycleCode(ViewPort,ColMap,ColNum,Range,RangeNum)
  195. struct ViewPort *ViewPort;
  196. UWORD *ColMap;
  197. LONG ColNum;
  198. CRange *Range;
  199. LONG RangeNum;
  200. {
  201.     register short i;
  202.  
  203.         /* Check for valid parameters. */
  204.  
  205.     if(!ViewPort || !ColMap || !ColNum || !Range || !RangeNum)
  206.         return(FALSE);
  207.  
  208.         /* Copy the data. */
  209.  
  210.     cy_VPort    = ViewPort;
  211.     cy_ColNum    = ColNum;
  212.     cy_Range    = Range;
  213.     cy_RangeNum    = RangeNum;
  214.  
  215.     for(i = 0 ; i < ColNum ; i++)
  216.         cy_ColMap[i] = ColMap[i];
  217.  
  218.         /* Clear event counters. */
  219.  
  220.     for(i = 0 ; i < cy_RangeNum ; i++)
  221.         cy_TicksPassed[i] = 0;
  222.  
  223.         /* Copy the original palette to the undo buffer. */
  224.  
  225.     for(i = 0 ; i < cy_ColNum ; i++)
  226.         cy_UndoBuffer[i] = cy_ColMap[i];
  227.  
  228.         /* Let the CycleCode wait. */
  229.  
  230.     cy_Command    = CY_WAIT;
  231.     cy_WeAreWaiting    = TRUE;
  232.  
  233.         /* Ta Da! The CycleCode enters the stage!. */
  234.  
  235.     cy_VBlank . is_Data        = (APTR)NULL;
  236.     cy_VBlank . is_Code        = VBlankHandler;
  237.     cy_VBlank . is_Node . ln_Succ    = NULL;
  238.     cy_VBlank . is_Node . ln_Pred    = NULL;
  239.     cy_VBlank . is_Node . ln_Type    = NT_INTERRUPT;
  240.     cy_VBlank . is_Node . ln_Pri    = 0;
  241.     cy_VBlank . is_Node . ln_Name    = "Cycling Interrupt";
  242.  
  243.     AddIntServer(5,&cy_VBlank);
  244.  
  245.     cy_CodeRun = TRUE;
  246.  
  247.     return(TRUE);
  248. }
  249.  
  250.     /* ClearCycleCode() :
  251.      *
  252.      *    Forces the CycleCode to hit and quit.
  253.      */
  254.  
  255. void
  256. ClearCycleCode()
  257. {
  258.     register short i;
  259.  
  260.         /* Is the interrupt already running? */
  261.  
  262.     if(!cy_CodeRun)
  263.         return;
  264.  
  265.         /* Tell it to wait. */
  266.  
  267.     cy_WeAreWaiting    = TRUE;
  268.     cy_Command    = CY_WAIT;
  269.  
  270.         /* Remove the server code. */
  271.  
  272.     RemIntServer(5,&cy_VBlank);
  273.  
  274.         /* Rebuild palette. */
  275.  
  276.     for(i = 0 ; i < cy_ColNum ; i++)
  277.         cy_ColMap[i] = cy_UndoBuffer[i];
  278.  
  279.  
  280.         /* Wait for it to finish. */
  281.  
  282.     WaitTOF();
  283.     WaitTOF();
  284.     WaitTOF();
  285.  
  286.         /* Close the shop. */
  287.  
  288.     cy_CodeRun = FALSE;
  289. }
  290.  
  291.     /* ToggleCycleCode() :
  292.      *
  293.      *    Toggles the activity of the cycling code.
  294.      */
  295.  
  296. void
  297. ToggleCycleCode()
  298. {
  299.     static short Mode = FALSE;
  300.  
  301.     Mode ^= TRUE;
  302.  
  303.     if(Mode)
  304.         cy_Command = CY_CYCL;
  305.     else
  306.         cy_Command = CY_WAIT;
  307.  
  308.     WaitTOF();
  309. }
  310.  
  311.     /* IsCycling() :
  312.      *
  313.      *    Returns the present status of the cycling code.
  314.      */
  315.  
  316. short
  317. IsCycling()
  318. {
  319.     if(cy_Command == CY_CYCL)
  320.         return(TRUE);
  321.  
  322.     if(cy_Command == CY_WAIT)
  323.         return(FALSE);
  324. }
  325.  
  326.     /* LoadCycleRange(FileName,Range,MaxRange) :
  327.      *
  328.      *    Searches the IFF-ILBM-file for CRNG or CCRT
  329.      *    chunks und initializes the colour-ranges.
  330.      */
  331.  
  332. LONG
  333. LoadCycleRange(FileName,Range,MaxRange)
  334. char *FileName;
  335. CRange *Range;
  336. LONG MaxRange;
  337. {
  338.     FILE *CycFile;
  339.     register short i;
  340.  
  341.         /* GraphiCraft private cycling chunk. */
  342.  
  343.     struct
  344.     {
  345.         WORD direction;
  346.         UBYTE start;
  347.         UBYTE end;
  348.         LONG seconds;
  349.         LONG microseconds;
  350.         WORD pad;
  351.     } CcrtChunk;
  352.  
  353.         /* Clear all ranges. */
  354.  
  355.     for(i = 0 ; i < MaxRange ; i++)
  356.         Range[i] . active = 0;
  357.  
  358.         /* Open the file and try to locate the CRNG chunk. */
  359.  
  360.     if(!(CycFile = fopen(FileName,"r")))
  361.         return(FALSE);
  362.  
  363.     if(FindChunk("CRNG",CycFile))
  364.     {
  365.             /* Read all ranges. */
  366.  
  367.         for(i = 0 ; i < MaxRange ; i++)
  368.         {
  369.             fread(&Range[i],sizeof(CRange),1,CycFile);
  370.  
  371.                 /* Carefully determine the activity
  372.                  * of the chunk.
  373.                  */
  374.  
  375.             if(Range[i] . active == CRNG_NORATE || !Range[i] . rate || Range[i] . low == Range[i] . high)
  376.                 Range[i] . active = 0;
  377.  
  378.                 /* Recalculate speed value. */
  379.  
  380.             if(Range[i] . rate > 0)
  381.                 Range[i] . rate = 16384 / Range[i] . rate;
  382.             else
  383.                 Range[i] . rate = 0;
  384.  
  385.                 /* Finished reading the chunks? */
  386.  
  387.             if(!FindChunk("CRNG",CycFile))
  388.             {
  389.                 i++;
  390.                 break;
  391.             }
  392.         }
  393.     }
  394.     else
  395.     {
  396.             /* Didn't find a CRNG chunk, try to find a
  397.              * CCRT chunk.
  398.              */
  399.  
  400.         fseek(CycFile,0,0);
  401.  
  402.         if(FindChunk("CCRT",CycFile))
  403.         {
  404.             for(i = 0 ; i < MaxRange ; i++)
  405.             {
  406.                 fread(&CcrtChunk,sizeof(CcrtChunk),1,CycFile);
  407.  
  408.                     /* We have located a CCRT chunk, now
  409.                      * make it a CRNG chunk.
  410.                      */
  411.  
  412.                 Range[i] . low    = CcrtChunk . start;
  413.                 Range[i] . high    = CcrtChunk . end;
  414.  
  415.                 if(CcrtChunk . direction != 0)
  416.                     Range[i] . active = CRNG_ACTIVE;
  417.                 else
  418.                     Range[i] . active = 0;
  419.  
  420.                 if(CcrtChunk . direction > 0)
  421.                     Range[i] . active |= CRNG_REVERSE;
  422.  
  423.                     /* Recalculate speed (by
  424.                      * Carolyn Scheppner).
  425.                      */
  426.  
  427.                 Range[i] . rate    = 16384 / (CcrtChunk . seconds * 60 + (CcrtChunk . microseconds + 8334) / 16667);
  428.  
  429.                 if(!Range[i] . rate || Range[i] . low == Range[i] . high)
  430.                     Range[i] . active = 0;
  431.  
  432.                 if(Range[i] . rate > 0)
  433.                     Range[i] . rate = 16384 / Range[i] . rate;
  434.                 else
  435.                     Range[i] . rate = 0;
  436.  
  437.                 if(!FindChunk("CCRT",CycFile))
  438.                 {
  439.                     i++;
  440.                     break;
  441.                 }
  442.             }
  443.         }
  444.         else
  445.         {
  446.                 /* Seems that we failed. */
  447.  
  448.             fclose(CycFile);
  449.             return(FALSE);
  450.         }
  451.     }
  452.  
  453.     fclose(CycFile);
  454.  
  455.     return(i);
  456. }
  457.