home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 612b.lha / PicPak_v1.3c / pic_pak.c next >
C/C++ Source or Header  |  1992-02-01  |  31KB  |  1,173 lines

  1. /***************************************************************************
  2.  * pic_pak.c   - "PicPak" - IFF ILBM picture manipulation functions        *
  3.  *                (c) 1990 Videoworks Computer Applications                *
  4.  *                All rights reserved.                                     *
  5.  *                                                                         *
  6.  *                Written by Paul T. Miller                                *
  7.  *                                                                         *
  8.  * DISCLAIMER:                                                             *
  9.  * Feel free to use these routines or derivatives in your own code, but    *
  10.  * please leave credit in your documentation. This code is NOT public      *
  11.  * domain, and I am only allowing use of it because I'm a nice guy and I   *
  12.  * want to show people how to effectively use their code. If you make any  *
  13.  * modifications or enhancements to this code, please let me know.         *
  14.  *                                                                         *
  15.  * Send comments/suggestions to:                                           *
  16.  * Paul Miller                                                             *
  17.  * The MBT, Coconut Telegraph, The TARDIS                                  *
  18.  *                                                                         *
  19.  * Program Name:  N/A                                                      *
  20.  * Version:       1                                                        *
  21.  * Revision:      3                                                        *
  22.  *-------------------------------------------------------------------------*
  23.  * File: (pic_pak.c) IFF package routines                                  *
  24.  *-------------------------------------------------------------------------*
  25.  * Modification History                                                    *
  26.  * Date     Author   Comment                                               *
  27.  * -------- ------   -------                                               *
  28.  * 10-02-90    PTM   Created. Pic allocation/freeing with specified memtype
  29.  * 10-03-90    PTM   iff.library hooks
  30.  * 10-08-90    PTM   clean up memory allocation
  31.  * 11-28-90    PTM   SetImageType(), custom processing of non-standard forms
  32.  *                   ViewPort fade/color set functions, color-cycling
  33.  * 12-01-90    PTM   SHAM Chunk/ColorMap support - improve file parsing
  34.  * 12-02-90    PTM   SHAM Copper-list code, ViewPort support code
  35.  * 12-06-90    PTM   Add image decompression buffer
  36.  * 12-07-90    PTM   Free mask plane if present in a Frame BitMap
  37.  * 10-13-91    PTM   re-prototype
  38.  ***************************************************************************/
  39.  
  40. #ifndef PIC_PAK_H
  41. #include "pic_pak.h"
  42. #endif
  43.  
  44. extern struct Custom far custom;
  45. extern struct GfxBase *GfxBase;
  46. extern struct IntuitionBase *IntuitionBase;
  47. extern struct Library *DOSBase;
  48.  
  49. /* Some IFF parsing structs/constants */
  50. #define BUFFER_SIZE  32000                /* image decompression buffer */
  51.  
  52. #define MAKE_ID(a,b,c,d) (((long)(a)<<24)|((long)(b)<<16)|((long)(c)<<8)|(long)(d))
  53.  
  54. /*  IFF types we may encounter  */
  55. #define FORM   MAKE_ID('F', 'O', 'R', 'M')
  56. #define ILBM   MAKE_ID('I', 'L', 'B', 'M')
  57. #define BMHD   MAKE_ID('B', 'M', 'H', 'D')
  58. #define CMAP   MAKE_ID('C', 'M', 'A', 'P')
  59. #define BODY   MAKE_ID('B', 'O', 'D', 'Y')
  60. #define CAMG   MAKE_ID('C', 'A', 'M', 'G')
  61. #define CRNG   MAKE_ID('C', 'R', 'N', 'G')
  62. #define SHAM   MAKE_ID('S', 'H', 'A', 'M')
  63. #define DYCP   MAKE_ID('D', 'Y', 'C', 'P')
  64. #define CTBL   MAKE_ID('C', 'T', 'B', 'L')
  65. #define GRAB   MAKE_ID('G', 'R', 'A', 'B')
  66. #define SPRT   MAKE_ID('S', 'P', 'R', 'T')
  67. #define CCRT   MAKE_ID('C', 'C', 'R', 'T')
  68. #define DPPV   MAKE_ID('D', 'P', 'P', 'V')
  69. #define DPPS   MAKE_ID('D', 'P', 'P', 'S')
  70.  
  71. #define byte(n) (((n + 15) >> 4) << 1)  /* Word aligned width in bytes. */
  72.  
  73. struct BitMapHeader {
  74.    UWORD w,h;           /* Raster width & height. */
  75.    UWORD x,y;           /* Pixel position. */
  76.    UBYTE nPlanes;       /* Number of source bitplanes. */
  77.    UBYTE masking;       /* Masking... good for nothing maybe? */
  78.    UBYTE compression;   /* Packed or unpacked? */
  79.    UBYTE pad1;          /* We don't like odd length structures. */
  80.    UWORD transparentColor; /* Maybe good for... */
  81.    UBYTE xAspect, yAspect; /* Kind of quotient, width / height. */
  82.    WORD pageWidth, pageHeight;   /* Source page size. */
  83. };
  84.  
  85. /* IFF Stuff */
  86. union typekludge {
  87.    char type_str[4];
  88.    long type_long;
  89. };
  90. struct ChunkHeader {
  91.    union typekludge chunktype;
  92.    long chunksize;
  93. };
  94. #define TYPE            chunktype.type_long
  95. #define STRTYPE         chunktype.type_str
  96.  
  97. /*  Masking techniques  */
  98. #define mskNone                 0
  99. #define mskHasMask              1
  100. #define mskHasTransparentColor  2
  101. #define mskLasso                3
  102.  
  103. /*  Compression techniques  */
  104. #define cmpNone                 0
  105. #define cmpByteRun1             1
  106.  
  107. /* color-cycling stuff */
  108. #define CRNG_NORATE     36      /* Don't cycle this range. */
  109. #define CRNG_ACTIVE     1 << 0  /* This range is active. */
  110. #define CRNG_REVERSE    1 << 1  /* This range is cycling backwards. */
  111.  
  112. /* GraphiCraft private cycling chunk. */
  113. struct CcrtChunk {
  114.    WORD  direction;
  115.    UBYTE start;
  116.    UBYTE end;
  117.    LONG  seconds;
  118.    LONG  microseconds;
  119.    WORD  pad;
  120. };
  121.  
  122. /* some color-cycling globals (used only if color-cycling is enabled) */
  123. struct CycleData *cdata = NULL;
  124. int i, j;                     /* general-purpose indexes used by cycler */
  125.  
  126. UWORD fade_delay = 0;
  127. ULONG max_bufsize = BUFFER_SIZE;
  128.  
  129. struct Pic *AllocatePic(UWORD width, UWORD height, UBYTE depth, UBYTE memtype)
  130. {
  131.    struct Pic *pic;
  132.    struct BitMap *bitmap;
  133.    ULONG i, size, memsize;
  134.  
  135.    if (memtype == NULL)
  136.       memtype = MEMTYPE_CHIP;
  137.  
  138.    pic = (struct Pic *)AllocMem(PIC_SIZE, MEMF_CLEAR);
  139.    if (!pic) return(NULL);
  140.  
  141.    bitmap = &pic->BitMap;
  142.  
  143.    InitBitMap(bitmap, (long)depth, (long)width, (long)height);
  144.  
  145.    pic->Width = width;
  146.    pic->Height = height;
  147.    pic->Depth = depth;
  148.    pic->Colors = 1<<depth;
  149.  
  150.    size = bitmap->BytesPerRow * bitmap->Rows;
  151.    memsize = size * (ULONG)depth;
  152.  
  153.    if (memtype != MEMTYPE_NONE)
  154.    {
  155.       /* attempt to allocate a chunk of the required memory size and type */
  156.       if (memtype == MEMTYPE_ANY)      /* if ANY type, try CHIP first */
  157.       {
  158.          bitmap->Planes[0] = (PLANEPTR)AllocMem(memsize, MEMF_CHIP);
  159.          if (!bitmap->Planes[0])
  160.             memtype = MEMTYPE_FAST;    /* out of CHIP, try for FAST */
  161.       }
  162.  
  163.       if (memtype == MEMTYPE_CHIP)
  164.          bitmap->Planes[0] = (PLANEPTR)AllocMem(memsize, MEMF_CHIP);
  165.  
  166.       if (memtype == MEMTYPE_FAST)
  167.          bitmap->Planes[0] = (PLANEPTR)AllocMem(memsize, MEMF_FAST);
  168.  
  169.       if (!bitmap->Planes[0])       /* couldn't get the memory */
  170.       {
  171.          FreePic(pic);
  172.          return(NULL);
  173.       }
  174.       for (i = 1; i < depth; i++)      /* set the plane pointers */
  175.          bitmap->Planes[i] = (PLANEPTR)(bitmap->Planes[0] + (i * size));
  176.    }
  177.    if (memtype == MEMTYPE_ANY)   /* actually got CHIP ram */
  178.       memtype = MEMTYPE_CHIP;
  179.  
  180.    pic->Memtype = memtype;
  181.  
  182.    return(pic);
  183. }
  184.  
  185. void FreePic(struct Pic *pic)
  186. {
  187.    ULONG size, chunksize;
  188.    struct BitMap *bm;
  189.  
  190.    if (pic)
  191.    {
  192.       if (bm = &pic->BitMap)
  193.       {
  194.          size = bm->BytesPerRow * bm->Rows;
  195.          chunksize = size * (ULONG)bm->Depth;
  196.  
  197.          if (bm->Planes[0])
  198.             FreeMem(bm->Planes[0], chunksize);
  199.       }
  200.       if (pic->PicExt)
  201.       {
  202.          switch (pic->Type)
  203.          {
  204.             case PICTYPE_SHAM:
  205.                FreeMem(pic->PicExt, SHAMDATA_SIZE);
  206.                break;
  207.             case PICTYPE_DHIRES:
  208.                size = pic->Height * DHIRES_COLORS * sizeof(WORD);
  209.                FreeMem(pic->PicExt, size);
  210.                break;
  211.          }
  212.       }
  213.       FreeMem(pic, PIC_SIZE);
  214.    }
  215. }
  216.  
  217. struct Frame *AllocateFrame(UWORD width, UWORD height, UBYTE depth)
  218. {
  219.    struct Frame *frame;
  220.    struct BitMap *bitmap;
  221.    ULONG i, size, memsize;
  222.  
  223.    frame = (struct Frame *)AllocMem(FRAME_SIZE, MEMF_CLEAR);
  224.    if (!frame) return(NULL);
  225.  
  226.    bitmap = &frame->BitMap;
  227.  
  228.    InitBitMap(bitmap, (long)depth, (long)width, (long)height);
  229.  
  230.    frame->Width = width;
  231.    frame->Height = height;
  232.  
  233.    size = bitmap->BytesPerRow * bitmap->Rows;
  234.    memsize = size * (ULONG)depth;
  235.  
  236.    bitmap->Planes[0] = (PLANEPTR)AllocMem(memsize, MEMF_CHIP);
  237.    if (!bitmap->Planes[0])
  238.    {
  239.       FreeMem(frame, FRAME_SIZE);
  240.       return(NULL);
  241.    }
  242.    for (i = 1; i < depth; i++)      /* set the plane pointers */
  243.       bitmap->Planes[i] = (PLANEPTR)(bitmap->Planes[0] + (i * size));
  244.  
  245.    return(frame);
  246. }
  247.  
  248. void FreeFrame(struct Frame *frame)
  249. {
  250.    ULONG size, chunksize;
  251.    struct BitMap *bm;
  252.  
  253.    if (frame)
  254.    {
  255.       if (bm = &frame->BitMap)
  256.       {
  257.          size = RASSIZE(bm->BytesPerRow * 8, bm->Rows);
  258.          chunksize = size * (ULONG)bm->Depth;
  259.  
  260.          if (bm->Planes[0])
  261.             FreeMem(bm->Planes[0], chunksize);
  262.          if (bm->Planes[bm->Depth])                /* extra mask plane */
  263.             FreeMem(bm->Planes[bm->Depth], size);
  264.       }
  265.       FreeMem(frame, FRAME_SIZE);
  266.    }
  267. }
  268.  
  269. struct Pic *LoadPic(STRPTR filename, UBYTE memtype)
  270. {
  271.    return(LoadImage(filename, NULL, PICTYPE_NORMAL, memtype));
  272. }
  273.  
  274. struct Pic *LoadPic2BitMap(STRPTR filename, struct BitMap *bitmap)
  275. {
  276.    return(LoadImage(filename, bitmap, PICTYPE_NORMAL, MEMTYPE_NONE));
  277. }
  278.  
  279. struct Frame *LoadFrame(STRPTR filename)
  280. {
  281.    return((struct Frame *)LoadImage(filename, NULL, PICTYPE_FRAME, NULL));
  282. }
  283.  
  284. struct Pic *LoadImage(STRPTR filename, struct BitMap *bitmap, UBYTE type, UBYTE memtype)
  285. {
  286.    struct Pic *pic = NULL;
  287.    struct Frame *frame = NULL;
  288.    struct BitMapHeader bmhd;
  289.    struct ChunkHeader ch;
  290.    FILE *file;
  291.    LONG formsize, subtype;
  292.    UWORD version;
  293.    ULONG size;
  294.  
  295.    file = fopen(filename, "r");
  296.    if (!file)
  297.       return(NULL);
  298.  
  299.    if (!fread((char *)&ch, sizeof(struct ChunkHeader), 1, file))
  300.    {
  301.       fclose(file);
  302.       return(NULL);
  303.    }
  304.    if (ch.TYPE != FORM)    /* not an IFF file */
  305.    {
  306.       fclose(file);
  307.       return(NULL);
  308.    }
  309.  
  310.    if (!fread((char *)&subtype, sizeof(subtype), 1, file))
  311.    {
  312.       fclose(file);
  313.       return(NULL);
  314.    }
  315.    formsize = ch.chunksize - sizeof(subtype);
  316.    if (subtype != ILBM)    /* not an ILBM image */
  317.    {
  318.       fclose(file);
  319.       return(NULL);
  320.    }
  321.  
  322.    while (formsize > 0)
  323.    {
  324.       if (!fread((char *)&ch, sizeof(struct ChunkHeader), 1, file))
  325.       {
  326.          fclose(file);
  327.          if (pic) FreePic(pic);
  328.          if (frame) FreeFrame(frame);
  329.          return(NULL);
  330.       }
  331.       formsize -= sizeof(struct ChunkHeader);
  332.  
  333.       switch (ch.TYPE)
  334.       {
  335.          case BMHD:
  336.             fread((char *)&bmhd, ch.chunksize, 1, file);
  337.  
  338.             /* some error checking */
  339.             if (bmhd.nPlanes < 1 || bmhd.nPlanes > 8)
  340.             {
  341.                fclose(file);
  342.                return(NULL);
  343.             }
  344.             if (bitmap)          /* application has supplied a BitMap */
  345.                memtype = MEMTYPE_NONE;
  346.  
  347.             if (type == PICTYPE_FRAME)
  348.             {
  349.                frame = AllocateFrame(bmhd.w, bmhd.h, bmhd.nPlanes);
  350.                if (!frame)
  351.                {
  352.                   fclose(file);
  353.                   return(NULL);
  354.                }
  355.                frame->X = bmhd.w;
  356.                frame->Y = bmhd.h;
  357.             }
  358.             else
  359.             {
  360.                pic = AllocatePic(bmhd.w, bmhd.h, bmhd.nPlanes, memtype);
  361.                if (!pic)
  362.                {
  363.                   fclose(file);
  364.                   return(NULL);
  365.                }
  366.             }
  367.             break;
  368.          case CMAP:
  369.             if (type == PICTYPE_FRAME)
  370.             {
  371.                fseek(file, ch.chunksize, 1);
  372.                break;
  373.             }
  374.             pic->Colors = LoadCMAP(file, ch.chunksize, &pic->Colormap[0]);
  375.             break;
  376.          case CAMG:
  377.             if (type == PICTYPE_FRAME)
  378.             {
  379.                fseek(file, ch.chunksize, 1);
  380.                break;
  381.             }
  382.             fread((char *)&subtype, sizeof(subtype), 1, file);
  383.             pic->ViewModes = (ULONG)subtype;
  384.             if ((UWORD)pic->ViewModes == NULL)
  385.                pic->ViewModes >>= 16L;
  386.             pic->ViewModes &= ~(SPRITES|VP_HIDE|PFBA|GENLOCK_AUDIO|GENLOCK_VIDEO);
  387.             break;
  388.          case CRNG:
  389.          case CCRT:
  390.             if (type == PICTYPE_FRAME || pic->Cycles == MAXCRANGES)
  391.             {
  392.                fseek(file, ch.chunksize, 1);
  393.                break;
  394.             }
  395.             LoadCycleRange(file, &pic->CRanges[pic->Cycles], ch.TYPE);
  396.             pic->Cycles++;
  397.             break;
  398.          case SHAM:
  399.             if (type == PICTYPE_FRAME)
  400.             {
  401.                fseek(file, ch.chunksize, 1);
  402.                break;
  403.             }
  404.             pic->PicExt = (APTR)AllocMem(SHAMDATA_SIZE, NULL);
  405.             if (!pic->PicExt)
  406.                fseek(file, ch.chunksize, 1);
  407.             else
  408.             {
  409.                fread((char *)&version, sizeof(UWORD), 1, file);
  410.                ch.chunksize -= sizeof(UWORD);
  411.                if (version == 0)
  412.                {
  413.                   fread((char *)pic->PicExt, ch.chunksize, 1, file);
  414.                   pic->Type = PICTYPE_SHAM;
  415.                }
  416.                else
  417.                   fseek(file, ch.chunksize, 1);
  418.             }
  419.             break;
  420.          case CTBL:
  421.             if (type == PICTYPE_FRAME)
  422.             {
  423.                fseek(file, ch.chunksize, 1);
  424.                break;
  425.             }
  426.             size = pic->Height * DHIRES_COLORS * sizeof(WORD);
  427.             pic->PicExt = (APTR)AllocMem(size, NULL);
  428.             if (!pic->PicExt)
  429.                fseek(file, ch.chunksize, 1);
  430.             else
  431.             {
  432.                fread((char *)pic->PicExt, ch.chunksize, 1, file);
  433.                pic->Type = PICTYPE_DHIRES;
  434.             }
  435.             break;
  436.          case BODY:
  437.             if (type == PICTYPE_FRAME && frame)
  438.             {
  439.                if (!LoadRaster(file, ch.chunksize, &frame->BitMap.Planes[0], &bmhd))
  440.                {
  441.                   fclose(file);
  442.                   FreeFrame(frame);
  443.                   return(NULL);
  444.                }
  445.             }
  446.             if (type != PICTYPE_FRAME)
  447.             {
  448.                if (!bitmap)
  449.                   bitmap = &pic->BitMap;
  450.                if (!LoadRaster(file, ch.chunksize, &bitmap->Planes[0], &bmhd))
  451.                {
  452.                   fclose(file);
  453.                   FreePic(pic);
  454.                   return(NULL);
  455.                }
  456.             }
  457.             /* make sure the BODY isn't off a few bytes */
  458.             if (formsize - ch.chunksize > 0)
  459.                ch.chunksize += (formsize - ch.chunksize);
  460.             break;
  461.          default:
  462.             fseek(file, ch.chunksize, 1);
  463.             break;
  464.       }
  465.       formsize -= ch.chunksize;
  466.       if (ch.chunksize & 1)         /* odd-length chunk */
  467.       {
  468.          formsize--;
  469.          fseek(file, 1L, 1);
  470.       }
  471.    }
  472.    fclose(file);
  473.  
  474.    if (type == PICTYPE_FRAME)
  475.       return((struct Pic *)frame);
  476.  
  477.    SetImageType(pic);      /* perform any post-processing/identification */
  478.  
  479.    /* now double-check the display size flags */
  480.    if (bmhd.pageHeight > 242)
  481.       pic->ViewModes |= LACE;
  482.    if (bmhd.pageWidth >= 640)
  483.       pic->ViewModes |= HIRES;
  484.  
  485.    return(pic);
  486. }
  487.  
  488. /* GetPicAttrs()
  489.       - return the specified picture's size, depth, and viewmode information
  490.         in supplied pointer variables
  491. */
  492.  
  493. GetPicAttrs(STRPTR filename, WORD *w, WORD *h, WORD *d, ULONG *vm)
  494. {
  495.    struct Pic *pic;
  496.  
  497.    /* load just the header information */
  498.    pic = LoadImage(filename, NULL, NULL, MEMTYPE_NONE);
  499.    if (pic)
  500.    {
  501.       *w = pic->Width;
  502.       *h = pic->Height;
  503.       *d = pic->Depth;
  504.       *vm = pic->ViewModes;
  505.       FreePic(pic);
  506.       return(1);
  507.    }
  508.    return(NULL);
  509. }
  510.  
  511. /* Pic2BitMap()
  512.       - download Pic imagery stored in FAST RAM to the specified BitMap
  513. */
  514. Pic2BitMap(struct Pic *pic, struct BitMap *bm)
  515. {
  516.    ULONG i, size;
  517.  
  518.    if (pic && bm)
  519.    {
  520.       if (pic->Memtype == MEMTYPE_CHIP)
  521.       {
  522.          BltBitMap(&pic->BitMap, 0, 0, bm, 0, 0, pic->Width,pic->Height,
  523.                    0xc0, 0xff, NULL);
  524.          return(1);
  525.       }
  526.  
  527.       if (pic->Depth != bm->Depth)
  528.          return(NULL);
  529.       if (pic->Width != bm->BytesPerRow * 8)
  530.          return(NULL);
  531.       if (pic->Height != bm->Rows)
  532.          return(NULL);
  533.  
  534.       size = pic->BitMap.BytesPerRow * pic->BitMap.Rows;
  535.       for (i = 0; i < bm->Depth; i++)
  536.          memcpy(bm->Planes[i], pic->BitMap.Planes[i], size);
  537.  
  538.       return(1);
  539.    }
  540.    return(NULL);
  541. }
  542.  
  543. BOOL LoadRaster(FILE *file, ULONG chunksize, PLANEPTR *BitPlanes, struct BitMapHeader *BMHeader)
  544. {
  545.    register LONG i, j, k;
  546.    register BYTE ChkVal;
  547.    register UBYTE Value, SoFar;
  548.    UBYTE Compr, Depth;
  549.    LONG Height, Width;
  550.    PLANEPTR Planes[9];    /* 9 for possible bitmask. */
  551.    UBYTE *memory = NULL;
  552.  
  553.    for(i = 0; i < 9; i++)
  554.       Planes[i] = NULL;
  555.  
  556.    Width   = byte(BMHeader->w);
  557.    Height  = BMHeader->h;
  558.    Depth   = BMHeader->nPlanes;
  559.    Compr   = BMHeader->compression;
  560.  
  561.    if (Compr > cmpByteRun1 || !BitPlanes)
  562.       return(FALSE);
  563.  
  564.    for(i = 0; i < Depth; i++)
  565.       Planes[i] = BitPlanes[i];
  566.  
  567.    if (BMHeader->masking == mskHasMask)
  568.       Depth++;
  569.  
  570.    if (Compr == cmpNone)
  571.    {
  572.       for (k = 0; k < Height; k++)
  573.       {
  574.          for (j = 0; j < Depth; j++)
  575.          {
  576.             if (Planes[j])
  577.             {
  578.                fread((char *)Planes[j], Width, 1, file);
  579.                Planes[j] += Width;
  580.             }
  581.             else
  582.                fseek(file, Width, 1);
  583.          }
  584.       }
  585.    }
  586.    if (Compr == cmpByteRun1)
  587.    {
  588.       if (chunksize < max_bufsize)
  589.       {
  590.          memory = (UBYTE *)AllocMem(chunksize, NULL);
  591.          if (memory)
  592.          {
  593.             fread(memory, chunksize, 1, file);
  594.             mem_decompress(memory, &Planes[0], Width, Height, Depth);
  595.             FreeMem(memory, chunksize);
  596.             return(1);
  597.          }
  598.       }
  599.       for (k = 0; k < Height; k++)
  600.       {
  601.          for (j = 0; j < Depth; j++)
  602.          {
  603.             for (SoFar = 0; SoFar < Width ;)
  604.             {
  605.                ChkVal = fgetc(file);
  606.  
  607.                if (ChkVal > 0)
  608.                {
  609.                   if (Planes[j])
  610.                   {
  611.                      fread(Planes[j], ChkVal + 1, 1, file);
  612.                      Planes[j] += ChkVal + 1;
  613.                   }
  614.                   else
  615.                      fseek(file, ChkVal + 1, 1);
  616.  
  617.                   SoFar += ChkVal + 1;
  618.                }
  619.                else
  620.                {
  621.                   if (ChkVal != 128)
  622.                   {
  623.                      Value = fgetc(file);
  624.  
  625.                      for (i = 0; i <= -ChkVal; i++)
  626.                      {
  627.                         if (Planes[j])
  628.                         {
  629.                            *Planes[j] = Value;
  630.                            Planes[j]++;
  631.                         }
  632.                         SoFar++;
  633.                      }
  634.                   }
  635.                }
  636.             }
  637.          }
  638.       }
  639.    }
  640.    return(TRUE);
  641. }
  642.  
  643. void mem_decompress(register UBYTE *ptr, PLANEPTR *Planes, LONG Width, LONG Height, UBYTE Depth)
  644. {
  645.    LONG i, j, k;
  646.    register BYTE ChkVal;
  647.    UBYTE Value, SoFar;
  648.  
  649.    for (k = 0; k < Height; k++)
  650.    {
  651.       for (j = 0; j < Depth; j++)
  652.       {
  653.          for (SoFar = 0; SoFar < Width ;)
  654.          {
  655.             ChkVal = *ptr;
  656.             ptr++;
  657.  
  658.             if (ChkVal > 0)
  659.             {
  660.                if (Planes[j])
  661.                {
  662.                   memcpy(Planes[j], ptr, ChkVal+1);
  663.                   Planes[j] += ChkVal + 1;
  664.                   ptr += ChkVal + 1;
  665.                }
  666.                else
  667.                   ptr += ChkVal + 1;
  668.  
  669.                SoFar += ChkVal + 1;
  670.             }
  671.             else
  672.             {
  673.                if (ChkVal != 128)
  674.                {
  675.                   Value = *ptr;
  676.                   ptr++;
  677.  
  678.                   for (i = 0; i <= -ChkVal; i++)
  679.                   {
  680.                      if (Planes[j])
  681.                      {
  682.                         *Planes[j] = Value;
  683.                         Planes[j]++;
  684.                      }
  685.                      SoFar++;
  686.                   }
  687.                }
  688.             }
  689.          }
  690.       }
  691.    }
  692. }
  693.  
  694. void SetPicReadBufSize(ULONG size)
  695. {
  696.    max_bufsize = size;
  697. }
  698.  
  699. UWORD LoadCMAP(FILE *file, LONG csize, UWORD *cmap)
  700. {
  701.    UBYTE *ctable;
  702.    UWORD i, n;
  703.    LONG len;
  704.  
  705.    len = csize;
  706.    if (len > (MAXCOLORS * 3))
  707.       len = MAXCOLORS * 3;
  708.  
  709.    ctable = (UBYTE *)AllocMem(csize, NULL);
  710.    if (!ctable)
  711.       return(NULL);
  712.  
  713.    fread((char *)ctable, csize, 1, file);
  714.  
  715.    for (i = n = 0; n < len; i++, n += 3)
  716.       cmap[i] = ((ctable[n]>>4)<<8)+((ctable[n+1]>>4)<<4)+(ctable[n+2]>>4);
  717.  
  718.    FreeMem(ctable, csize);
  719.  
  720.    return(i);
  721. }
  722.  
  723. void LoadCycleRange(FILE *file, CRange *range, LONG type)
  724. {
  725.    struct CcrtChunk crtchunk;
  726.  
  727.    switch (type)
  728.    {
  729.       case CRNG:
  730.          fread((char *)range, sizeof(CRange), 1, file);
  731.  
  732.          /* Carefully determine the activity of the chunk. */
  733.          if (range->active == CRNG_NORATE || !range->rate || range->low == range->high)
  734.             range->active = 0;
  735.  
  736.          /* Recalculate speed value. */
  737.          if (range->rate > 0)
  738.             range->rate = 16384 / range->rate;
  739.          else
  740.             range->rate = 0;
  741.          break;
  742.       case CCRT:
  743.          fread((char *)&crtchunk, sizeof(struct CcrtChunk), 1, file);
  744.  
  745.          /* We have located a CCRT chunk, now make it a CRNG chunk. */
  746.          range->low  = crtchunk.start;
  747.          range->high = crtchunk.end;
  748.  
  749.          if (crtchunk.direction != 0)
  750.             range->active = CRNG_ACTIVE;
  751.          else
  752.             range->active = 0;
  753.  
  754.          if (crtchunk.direction > 0)
  755.             range->active |= CRNG_REVERSE;
  756.  
  757.          /* Recalculate speed (by Carolyn Scheppner). */
  758.          range->rate = 16384 / (crtchunk.seconds * 60 +
  759.                          (crtchunk.microseconds + 8334) / 16667);
  760.          if (!range->rate || range->low == range->high)
  761.             range->active = 0;
  762.          if (range->rate > 0)
  763.             range->rate = 16384 / range->rate;
  764.          else
  765.             range->rate = 0;
  766.          break;
  767.    }
  768. }
  769.  
  770. void SetImageType(struct Pic *pic)
  771. {
  772.    /* handle custom processing of non-standard picture types */
  773.    if (pic->Type)    /* already set */
  774.    {
  775.       switch (pic->Type)
  776.       {
  777.          case PICTYPE_SHAM:
  778.             pic->Colors = 16;
  779.             pic->ViewModes |= HAM;
  780.             break;
  781.       }
  782.       return;
  783.    }
  784.  
  785.    if (pic->ViewModes & HAM)
  786.    {
  787.       pic->Colors = 16;
  788.       pic->Type = PICTYPE_HAM;
  789.       return;
  790.    }
  791.    if (pic->Width <= 320 && pic->Height <= 200 && pic->Depth == 6)
  792.    {
  793.       pic->Colors = MAXCOLORS;
  794.       pic->ViewModes = EXTRA_HALFBRITE;
  795.       pic->Type = PICTYPE_EHB;
  796.       return;
  797.    }
  798.    pic->Type = PICTYPE_NORMAL;
  799. }
  800.  
  801. /**********************************************************/
  802. /* GENERAL-PURPOSE PICTURE/VIEWPORT MANIPULATION ROUTINES */
  803. /**********************************************************/
  804.  
  805. /*****************/
  806. /* COLOR-CYCLING */
  807. /*****************/
  808.  
  809. struct CycleData {
  810.    struct ViewPort *vp;
  811.    struct Pic *pic;
  812.    struct Interrupt *vblank;
  813.    UBYTE cycling;
  814.    UBYTE pad;
  815.    UWORD temp_col;
  816.    UWORD cmap[MAXCOLORS];
  817.    WORD  ticks[16];
  818. };
  819.  
  820. typedef void   (*FPTR)();
  821.  
  822. InitCycler()
  823. {
  824.    cdata = (struct CycleData *)AllocMem(sizeof(struct CycleData), MEMF_CLEAR);
  825.    if (!cdata)
  826.       return(NULL);
  827.  
  828.    cdata->vblank = (struct Interrupt *)AllocMem(sizeof(struct Interrupt), MEMF_CLEAR);
  829.    if (!cdata->vblank)
  830.       return(NULL);
  831.  
  832.    cdata->vblank->is_Data = NULL;
  833.    cdata->vblank->is_Code = (FPTR)cycle;
  834.    cdata->vblank->is_Node.ln_Succ = NULL;
  835.    cdata->vblank->is_Node.ln_Pred = NULL;
  836.    cdata->vblank->is_Node.ln_Type = NT_INTERRUPT;
  837.    cdata->vblank->is_Node.ln_Pri = 0;
  838.    cdata->vblank->is_Node.ln_Name = "PicPak_Color_Cycler";
  839.  
  840.    AddIntServer(INTB_VERTB, cdata->vblank);
  841.  
  842.    return(1);
  843. }
  844.  
  845. void FreeCycler()
  846. {
  847.    if (cdata)
  848.    {
  849.       if (cdata->vblank)
  850.       {
  851.          StopCycling();
  852.  
  853.          RemIntServer(INTB_VERTB, cdata->vblank);
  854.          FreeMem(cdata->vblank, sizeof(struct Interrupt));
  855.          WaitTOF();
  856.          WaitTOF();
  857.          WaitTOF();
  858.       }
  859.       FreeMem(cdata, sizeof(struct CycleData));
  860.    }
  861. }
  862.  
  863. __saveds void cycle()
  864. {
  865.    if (cdata->cycling)
  866.    {
  867.       for (i = 0; i < cdata->pic->Cycles; i++)
  868.       {
  869.          /* Increment event counter. */
  870.          cdata->ticks[i]++;
  871.  
  872.          /* Is this one up to cycle next? */
  873.          if (cdata->ticks[i] == cdata->pic->CRanges[i].rate)
  874.          {
  875.             /* Reset event counter for this range. */
  876.  
  877.             cdata->ticks[i] = 0;
  878.  
  879.             /* Is this range active? */
  880.  
  881.             if (!(cdata->pic->CRanges[i].active & CRNG_ACTIVE))
  882.                continue;
  883.  
  884.             /* Cycling backwards? */
  885.             if(cdata->pic->CRanges[i].active & CRNG_REVERSE)
  886.             {
  887.                /* Move the colours. */
  888.                cdata->temp_col = cdata->cmap[cdata->pic->CRanges[i].low];
  889.  
  890.                for(j = cdata->pic->CRanges[i].low; j < cdata->pic->CRanges[i].high; j++)
  891.                   cdata->cmap[j] = cdata->cmap[j+1];
  892.  
  893.                cdata->cmap[cdata->pic->CRanges[i].high] = cdata->temp_col;
  894.             }
  895.             else
  896.             {
  897.                /* This one is cycling forwards. */
  898.  
  899.                cdata->temp_col = cdata->cmap[cdata->pic->CRanges[i].high];
  900.  
  901.                for(j = cdata->pic->CRanges[i].high; j > cdata->pic->CRanges[i].low; j--)
  902.                   cdata->cmap[j] = cdata->cmap[j-1];
  903.  
  904.                cdata->cmap[cdata->pic->CRanges[i].low] = cdata->temp_col;
  905.             }
  906.             /* Okay, everything has been moved, now load the new palette. */
  907.             LoadRGB4(cdata->vp, cdata->cmap, cdata->pic->Colors);
  908.          }
  909.       }
  910.    }
  911. }
  912.  
  913. void StartCycling(struct ViewPort *vp, struct Pic *pic)
  914. {
  915.    if (cdata && pic->Cycles)
  916.    {
  917.       cdata->pic = pic;
  918.       cdata->vp = vp;
  919.  
  920.       /* reset the palette and event counters */
  921.       for (i = 0; i < pic->Colors; i++)
  922.          cdata->cmap[i] = pic->Colormap[i];
  923.  
  924.       for (i = 0; i < pic->Cycles; i++)
  925.          cdata->ticks[i] = 0;
  926.  
  927.       cdata->cycling = 1;
  928.    }
  929. }
  930.  
  931. void StopCycling()
  932. {
  933.    /* restore old colormap */
  934.    if (cdata)
  935.    {
  936.       if (cdata->cycling)
  937.          LoadRGB4(cdata->vp, &cdata->pic->Colormap[0], cdata->pic->Colors);
  938.  
  939.       cdata->cycling = NULL;
  940.    }
  941. }
  942.  
  943. void ToggleCycling()
  944. {
  945.    if (cdata)
  946.    {
  947.       if (cdata->cycling)
  948.          StopCycling();
  949.       else
  950.          StartCycling(cdata->vp, cdata->pic);
  951.    }
  952. }
  953.  
  954. IsCycling()
  955. {
  956.    if (!cdata) return(NULL);
  957.    return((int)cdata->cycling);
  958. }
  959.  
  960. /***************************/
  961. /* VIEWPORT-COLOR ROUTINES */
  962. /***************************/
  963.  
  964. void SetViewPortPicColors(struct ViewPort *vp, struct Pic *pic)
  965. {
  966.    switch (pic->Type)
  967.    {
  968.       case PICTYPE_SHAM:
  969.          InitSHAM(vp, pic);
  970.          break;
  971.       case PICTYPE_DHIRES:
  972.          InitDHIRES(vp, pic);
  973.          break;
  974.       default:
  975.          LoadRGB4(vp, &pic->Colormap[0], pic->Colors);
  976.    }
  977. }
  978.  
  979. void ClearViewPortColors(struct ViewPort *vp, UWORD colors)
  980. {
  981.    register int i;
  982.  
  983.    if (colors > MAXCOLORS)
  984.       colors = MAXCOLORS;
  985.  
  986.    for (i = 0; i < colors; i++)
  987.       SetRGB4(vp, i, 0, 0, 0);
  988. }
  989.  
  990. #define RED(c)    ((c >> 8) & 0xF)
  991. #define GREEN(c)  ((c >> 4) & 0xF)
  992. #define BLUE(c)   (c & 0xF)
  993.  
  994. void FadeViewPortIn(struct ViewPort *vp, UWORD *cm, UWORD colors)
  995. {
  996.    ULONG rf[MAXCOLORS], gf[MAXCOLORS], bf[MAXCOLORS];
  997.    register USHORT rgb, r, g, b;
  998.    WORD i, n;
  999.  
  1000.    if (colors > MAXCOLORS)
  1001.       colors = MAXCOLORS;
  1002.  
  1003.    for (i = 0; i < colors; i++)
  1004.    {
  1005.       rgb = cm[i];
  1006.       rf[i] = (RED(rgb) << 16) / 15;
  1007.       gf[i] = (GREEN(rgb) << 16) / 15;
  1008.       bf[i] = (BLUE(rgb) << 16) / 15;
  1009.    }
  1010.    for (n = 1; n < 16; n++)
  1011.    {
  1012.       for (i = 0; i < colors; i++)
  1013.       {
  1014.          r = (((rf[i] * n) + 0x8000) >> 16);
  1015.          g = (((gf[i] * n) + 0x8000) >> 16);
  1016.          b = (((bf[i] * n) + 0x8000) >> 16);
  1017.  
  1018.          SetRGB4(vp, i, r, g, b);
  1019.       }
  1020.       if (fade_delay > 0) Delay(fade_delay);
  1021.    }
  1022. }
  1023.  
  1024. void FadeViewPortOut(struct ViewPort *vp, UWORD colors)
  1025. {
  1026.    ULONG rf[MAXCOLORS], gf[MAXCOLORS], bf[MAXCOLORS];
  1027.    register UWORD rgb, r, g, b;
  1028.    WORD i, n;
  1029.    UWORD start = 0;
  1030.  
  1031.    if (GetRGB4(vp->ColorMap, 0) == 0x0000)
  1032.       start = 1;
  1033.  
  1034.    if (colors > MAXCOLORS)
  1035.       colors = MAXCOLORS;
  1036.  
  1037.    for (i = start; i < colors; i++)
  1038.    {
  1039.       rgb = GetRGB4(vp->ColorMap, i);
  1040.       rf[i] = (RED(rgb) << 16) / 15;
  1041.       gf[i] = (GREEN(rgb) << 16) / 15;
  1042.       bf[i] = (BLUE(rgb) << 16) / 15;
  1043.    }
  1044.    for (n = 14; n >= 0; n--)
  1045.    {
  1046.       for (i = start; i < colors; i++)
  1047.       {
  1048.          r = (((rf[i] * n) + 0x8000) >> 16);
  1049.          g = (((gf[i] * n) + 0x8000) >> 16);
  1050.          b = (((bf[i] * n) + 0x8000) >> 16);
  1051.  
  1052.          SetRGB4(vp, i, r, g, b);
  1053.       }
  1054.       if (fade_delay > 0) Delay(fade_delay);
  1055.    }
  1056. }
  1057.  
  1058. void SetFadeSpeed(UWORD val)
  1059. {
  1060.    fade_delay = val;
  1061. }
  1062.  
  1063. /* SPECIAL IMAGE TYPE INITIALIZATION CODE */
  1064.  
  1065. /* SHAM Copper-list initialization */
  1066. InitSHAM(struct ViewPort *vp, struct Pic *pic)
  1067. {
  1068.    register UWORD i, n;
  1069.    register struct SHAMData *sham;
  1070.    struct UCopList *ucoplist = NULL;
  1071.    BOOL lace = 0;
  1072.    register WORD view_dx = IntuitionBase->ViewLord.DxOffset;
  1073.  
  1074.    sham = (struct SHAMData *)pic->PicExt;
  1075.    if (!sham) return(NULL);
  1076.  
  1077.    SetRGB4(vp, 0, 0, 0, 0);
  1078.    for (i = 1; i < 16; i++)
  1079.       SetRGB4(vp, i, (UBYTE)(sham->ColorTable[0][i] / (UWORD)256),
  1080.                      (UBYTE)(sham->ColorTable[0][i] / (UWORD)16 % 16),
  1081.                      (UBYTE)(sham->ColorTable[0][i] % 16));
  1082.  
  1083.    ucoplist = (struct UCopList *)AllocMem(sizeof(struct UCopList), MEMF_PUBLIC|MEMF_CLEAR);
  1084.    if (!ucoplist) return(NULL);
  1085.  
  1086.    if (pic->Height > LORES_HEIGHT)
  1087.       lace = 1;
  1088.  
  1089.    CINIT(ucoplist, (199*16));
  1090.    for (i = 1; i < 200; i++)
  1091.    {
  1092.       if (lace)
  1093.       {
  1094.          if (view_dx < 114)
  1095.          {
  1096.             CWAIT(ucoplist, i + i - 2, 0);
  1097.          }
  1098.          else
  1099.          {
  1100.             if (view_dx < 129)
  1101.             {
  1102.                CWAIT(ucoplist, i + i - 2, 0);
  1103.             }
  1104.             else
  1105.             {
  1106.                CWAIT(ucoplist, i + i, 0);
  1107.             }
  1108.          }
  1109.       }
  1110.       else
  1111.       {
  1112.          if (view_dx < 128)
  1113.          {
  1114.             CWAIT(ucoplist, i - 1, 0);
  1115.          }
  1116.          else
  1117.          {
  1118.             CWAIT(ucoplist, i, 0);
  1119.          }
  1120.       }
  1121.       for (n = 1; n < 16; n++)
  1122.          CMOVE(ucoplist, custom.color[n], (WORD)sham->ColorTable[i][n]);
  1123.    }
  1124.    CEND(ucoplist);
  1125.  
  1126.    Forbid();
  1127.    vp->UCopIns = ucoplist;
  1128.    Permit();
  1129.    RethinkDisplay();
  1130.  
  1131.    return(1);
  1132. }
  1133.  
  1134. /* Dynamic-HIRES Copper-list initialization */
  1135. InitDHIRES(struct ViewPort *vp, struct Pic *pic)
  1136. {
  1137.    register UWORD i, n;
  1138.    UWORD *ctbl;
  1139.    struct UCopList *ucoplist = NULL;
  1140.    BOOL lace = 0;
  1141.  
  1142.    ctbl = (UWORD *)pic->PicExt;
  1143.    if (!ctbl) return(NULL);
  1144.  
  1145.    ucoplist = (struct UCopList *)AllocMem(sizeof(struct UCopList), MEMF_PUBLIC|MEMF_CLEAR);
  1146.    if (!ucoplist) return(NULL);
  1147.  
  1148.    if (pic->Height > LORES_HEIGHT)
  1149.       lace = 1;
  1150.  
  1151.    CINIT(ucoplist, (pic->Height * 16));
  1152.    for (i = 0; i < pic->Height; i++)
  1153.    {
  1154.       CWAIT(ucoplist, i, 0);
  1155.       for (n = 0; n < 16; n++)
  1156.          CMOVE(ucoplist, custom.color[n], (WORD)*(ctbl+(i*16)+n));
  1157.    }
  1158.    CEND(ucoplist);
  1159.  
  1160.    Forbid();
  1161.    vp->UCopIns = ucoplist;
  1162.    Permit();
  1163.    RethinkDisplay();
  1164.  
  1165.    return(1);
  1166. }
  1167.  
  1168. void FreeSHAM(struct ViewPort *vp)
  1169. {
  1170.    if (vp->UCopIns)
  1171.       FreeVPortCopLists(vp);
  1172. }
  1173.