home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 348.lha / SnowFall / SnowFall.c < prev    next >
C/C++ Source or Header  |  1990-02-14  |  8KB  |  366 lines

  1. #include <intuition/intuition.h>
  2. #include <graphics/gfxbase.h>
  3. #include <exec/memory.h>
  4. #include <stdio.h>
  5. #include "myiff.h"
  6. #include <ctype.h>
  7.  
  8. #define MAXSNOWMASS 200
  9.  
  10. void *OpenLibrary(),*OpenScreen(),*OpenWindow(),*GetMsg(),*AllocMem();
  11. struct GfxBase *GfxBase;
  12. struct IntuitionBase *IntuitionBase;
  13. struct Screen *s,*bs;
  14. struct Window *w;
  15. struct    NewScreen ns={0,0,320,256,5,1,2,0,CUSTOMSCREEN,0,0,0,0};
  16. struct NewWindow nw={0,0,320,256,-1,-1,CLOSEWINDOW,WINDOWCLOSE|BORDERLESS|
  17.     SMART_REFRESH|NOCAREREFRESH|ACTIVATE,0,0,0,0,0,0,0,0,0,CUSTOMSCREEN};
  18. UWORD BlackColors[32];
  19.  
  20. OpenAll(filename,backup)
  21. char *filename;
  22. int backup;
  23. {
  24.     long sec,mic;
  25.     
  26.     if ((GfxBase=OpenLibrary("graphics.library",0L))==0) abort("No gfxbase");
  27.     if ((IntuitionBase=OpenLibrary("intuition.library",0L))==0)
  28.         abort("No intuition");
  29.     CurrentTime(&sec,&mic);
  30.     srand((int)mic);
  31.     if ((LoadPicture(filename))==0) abort("Can't load picture");
  32.     if (backup) 
  33.         BltBitMap(&s->BitMap,0L,0L,&bs->BitMap,0L,0L,(long)s->Width,(long)s->Height,0xC0L,0xFFL,0L);
  34. }
  35.  
  36. abort(errortext)
  37. char *errortext;
  38. {
  39.     if (errortext!=0) puts(errortext);
  40.     if (w) CloseWindow(w);
  41.     if (bs) CloseScreen(bs);
  42.     if (s) CloseScreen(s);
  43.     if (GfxBase) CloseLibrary(GfxBase);
  44.     if (IntuitionBase) CloseLibrary(IntuitionBase);
  45.     exit(0);
  46. }
  47.  
  48. LoadPicture(filename)
  49. char *filename;
  50. {
  51.     FILE      *fd;
  52.     struct    BitMapHeader bmhd;
  53.     long      formsize;
  54.     UWORD     *colortable[32],modes;
  55.     
  56.     if (!(fd = fopen (filename, "r")))
  57.         return(0);
  58.     if (GetBMHD(fd,&bmhd,&formsize)==-1)
  59.         return(0);
  60.     if (GetCMap(fd,&formsize,colortable,&modes)==-1)
  61.         return(0);
  62. /* buildupdascreen */
  63.     if (modes==0xffff)
  64.     {
  65.         modes=0;
  66.         if (bmhd.w>452) modes|=HIRES;
  67.         if (bmhd.h>352) modes|=LACE;
  68.     }
  69.     ns.LeftEdge=bmhd.x;
  70.     ns.TopEdge=bmhd.y;
  71.     ns.Width=bmhd.w;
  72.     ns.Height=bmhd.h;
  73.     ns.Depth=bmhd.nplanes;
  74.     ns.ViewModes=modes;
  75.     ns.Type=CUSTOMSCREEN;
  76.     if ((bs=OpenScreen(&ns))==0) abort("Can't open backupscreen");
  77.     if ((s=(struct Screen *)OpenScreen(&ns))==0) abort("No memory for screen");
  78.     LoadRGB4(&s->ViewPort,BlackColors,(long)1<<bmhd.nplanes);
  79.     nw.Screen=s;
  80.     nw.Width=bmhd.w;
  81.     nw.Height=bmhd.h;
  82.     if ((w=(struct Window *)OpenWindow(&nw))==0) abort("No window here");
  83.     if (LoadBitMap(fd,&s->ViewPort,&bmhd)==-1) return(0);
  84.     LoadRGB4(&s->ViewPort,colortable,(long)1<<bmhd.nplanes);
  85.     return(1);
  86. }
  87.  
  88. GetCMap(fd,formsize,colortable,modes)
  89. FILE *fd;
  90. long *formsize;
  91. UWORD *colortable;
  92. UWORD *modes;
  93. {
  94.     struct ChunkHeader ch;
  95.     register UBYTE *ctable;
  96.     register int i,n;
  97.     ULONG temp=0;
  98.     
  99.     *modes=0xffff;
  100.     while (*formsize > 0) 
  101.     {
  102.         if (!fread (&ch, sizeof (ch), 1, fd))
  103.             return(-1);
  104.         *formsize -= sizeof (ch);
  105.  
  106.         switch (ch.TYPE)
  107.         {
  108.         case CMAP:
  109.         {
  110.             ctable=(UBYTE *)AllocMem((long)ch.chunksize,0L);
  111.             fread (ctable, (int) ch.chunksize, 1, fd);
  112.  
  113.             for (i = n = 0; n < ch.chunksize; i++, n+=3)
  114.                 colortable[i] = ((ctable[n]>>4 ) << 8) +
  115.                       ((ctable[n+1]>>4 ) << 4) +
  116.                       ( ctable[n+2]>>4 );
  117.             FreeMem(ctable,(long)ch.chunksize);
  118.             
  119.             break;
  120.         }
  121.  
  122.         case CAMG:
  123.             fread (&temp, (int) ch.chunksize, 1, fd);
  124.             *modes = (UWORD) (temp & 0xffffffff);
  125.             break;
  126.  
  127.         case BODY:
  128.             return(0);
  129.             break;
  130.  
  131.         case CRNG:
  132.         case GRAB:
  133.         case SPRT:
  134.         case DPPV:    /*  Anyone know what this one is for?  */
  135.         case DPPS:    /*  Anyone know what this one is for?  */
  136.             fseek (fd, ch.chunksize, 1);
  137.             break;
  138.  
  139.         default:
  140.             printf("unrecognized chunk 0x%lx\n",ch.TYPE);
  141.             fseek (fd, ch.chunksize, 1);
  142.         }
  143.  
  144.         *formsize -= ch.chunksize;
  145.         if (ch.chunksize & 1)        /*  Odd length chunk  */
  146.         {
  147.             *formsize --;
  148.             fseek (fd, 1L, 1);
  149.         }
  150.     }
  151.     return(-1);
  152. }
  153.     
  154. GetBMHD(fd,bmhd,formsize)
  155. FILE *fd;
  156. struct BitMapHeader *bmhd;
  157. long *formsize;
  158. {
  159.     long subtype;
  160.     struct ChunkHeader ch;
  161.     if (!fread (&ch, sizeof (ch), 1, fd))
  162.     {
  163.         return(-1);
  164.     }
  165.     
  166.     if (ch.TYPE != FORM)
  167.     {
  168.         return(-1);
  169.     }
  170.     *formsize=ch.chunksize;
  171.     
  172.     if (!fread (&subtype, sizeof (subtype), 1, fd))
  173.         return (-1);
  174.     *formsize -= sizeof (subtype);
  175.  
  176.     if (subtype != ILBM)
  177.         return(-1);
  178.  
  179.     if (!fread (&ch, sizeof (ch), 1, fd))
  180.         return(-1);
  181.     *formsize -= sizeof (ch);
  182.  
  183.     fread (bmhd, (int) ch.chunksize, 1, fd);
  184.  
  185.     *formsize -= ch.chunksize;
  186.     return(0);
  187. }
  188.  
  189. /* This routine is a fairly direct copy from Leo Schwab's Yaiffr - tanx */
  190.  
  191. LoadBitMap (fd, vp, header)
  192. FILE *fd;
  193. struct ViewPort *vp;
  194. struct BitMapHeader *header;
  195. {
  196.     register struct BitMap    *bm;
  197.     register int        i, n;
  198.     long            plane_offset = 0;
  199.  
  200.     bm = vp -> RasInfo -> BitMap;
  201.  
  202.     if (header->Compression != cmpNone &&
  203.         header->Compression != cmpByteRun1)
  204.         return(-1);
  205.  
  206.     for (i=0; i < bm->Rows; i++) {
  207.         for (n=0; n < bm->Depth; n++) {
  208. /*- - - - - - - - - - -*/
  209. if (!header->Compression) {    /* No compression */
  210.     if (!fread (bm -> Planes[n] + plane_offset,
  211.             bm -> BytesPerRow, 1, fd))
  212.         return(-1);
  213.  
  214. } else {
  215.     int        so_far;
  216.     register UBYTE    *dest = bm -> Planes[n] + plane_offset;
  217.     char        len;
  218.  
  219.     /*
  220.      * Note:  All file I/O after this point is assumed to be sucessful.
  221.      * This is clearly a poor assumption, but it saves on typing.
  222.      * And besides, putting the checking in is simple :-) :-).
  223.      */
  224.     so_far = bm -> BytesPerRow;
  225.     while (so_far > 0) {
  226.         if ((len = getc (fd)) >= 0) {    /*  Literal byte copy  */
  227.             so_far -= ++len;
  228.             if (!fread (dest, len, 1, fd)) return(-1);
  229.             dest += len;
  230.  
  231.         } else if ( len == -128)    /*  NOP  */
  232.             ;
  233.  
  234.         else if (len < 0) {        /*  Replication count  */
  235.             UBYTE    byte;
  236.  
  237.             len = -len + 1;
  238.             so_far -= len;
  239.             byte = getc (fd);
  240.             while (--len >= 0)
  241.                 *dest++ = byte;
  242.         }
  243.     }
  244.     if (so_far)
  245.         return(-1);
  246. }
  247. /*- - - - - - - - - - -*/
  248.         }
  249.         plane_offset += bm -> BytesPerRow;
  250.     }
  251.     return(0);
  252. }
  253.  
  254. DoSnow(mass,refresh,wind)
  255. long mass,refresh,wind;
  256. {
  257.     struct IntuiMessage *msg;
  258.     register long cx,cy,i,end,oldx,*x,*y,timer;
  259.     
  260.     timer=refresh;
  261.     x=AllocMem(800L,0L);
  262.     y=AllocMem(800L,0L);
  263.     if (mass>MAXSNOWMASS) mass=MAXSNOWMASS;
  264.     for (i=0;i<mass;i++) y[i]=-(rand()%w->Height);
  265.     while ((msg=GetMsg(w->UserPort))==0)
  266.     {
  267.         if (refresh!=-1)
  268.         {
  269.             if (--refresh==0)
  270.             {
  271.                 for (i=0;i<mass;i++)
  272.                     *(bs->BitMap.Planes[0]+(s->Width/8)*y[i]+x[i]/8) |= (128>>(x[i]%8));
  273.                 BltBitMap(&bs->BitMap,0L,0L,&s->BitMap,0L,0L,(long)s->Width,(long)s->Height,0xC0L,0xFFL,0x00L);
  274.                 for (i=0;i<mass;i++)
  275.                     *(bs->BitMap.Planes[0]+(s->Width/8)*y[i]+x[i]/8) &= ~(128>>(x[i]%8));
  276.                 refresh=timer;
  277.             }
  278.         }
  279.         for (i=0;i<mass;i++)
  280.         {
  281.             if (y[i]<-1) y[i]++;
  282.             else
  283.             {
  284.                 cx=x[i];
  285.                 cy=y[i];
  286.                 if (cy==-1) {cy=0;cx=rand()%w->Width;}
  287.                 else
  288.                 {
  289.                     oldx=cx;
  290.                     cx+=(rand()%31-wind-15)/8;
  291.                     if (cx>s->Width-1) cx-=s->Width;
  292.                     if (cx<0) cx+=s->Width;
  293.                     if (ReadPixel(w->RPort,cx,cy+1)==0)
  294.                     {
  295.                         *(s->BitMap.Planes[0]+(s->Width/8)*cy+oldx/8)&=~(128>>(oldx%8));
  296.                         cy++;
  297.                         *(s->BitMap.Planes[0]+(s->Width/8)*cy+cx/8) |= (128>>(cx%8));
  298.                     }
  299.                     else
  300.                     {
  301.                         end=1;
  302.                         if ((ReadPixel(w->RPort,cx+1,cy+1)==0)&&
  303.                             (ReadPixel(w->RPort,cx-1,cy+1)==0))
  304.                         {
  305.                             if ((cx>0)&&(rand()%2==1)) cx--;
  306.                             else if (cx<w->Width-1) cx++;
  307.                                 else cx--;
  308.                             end=0;
  309.                         }
  310.                         if ((ReadPixel(w->RPort,cx+1,cy+1)==0)&&(end==1)/* &&(rand()%6!=1) */)
  311.                             {cx++; end=0;}
  312.                         if ((ReadPixel(w->RPort,cx-1,cy+1)==0)&&(end==1)/* &&(rand()%6!=1) */)
  313.                             {cx--; end=0;}
  314.                         if (end==0)
  315.                         {
  316.                             *(s->BitMap.Planes[0]+(s->Width/8)*cy+oldx/8)&=~(128>>(oldx%8));
  317.                             cy++;
  318.                         }
  319.                         *(s->BitMap.Planes[0]+(s->Width/8)*cy+cx/8) |= (128>>(cx%8));
  320.                         if (end==1) cy=-1;
  321.                     }
  322.                 }
  323.                 x[i]=cx;
  324.                 y[i]=cy;
  325.             }
  326.         }
  327.     }
  328.     FreeMem(x,800L);
  329.     FreeMem(y,800L);
  330. }
  331.  
  332. DisplayUsage()
  333. {
  334.     puts("Snowfall - made December 1989 by Lars R. Clausen");
  335.     puts("Usage: SnowFall [-ppicture] [-n#snowflakes] [-trefreshtime] [-wwindforce]");
  336.     exit(0);
  337. }
  338.  
  339. main(argc,argv)
  340. int argc;
  341. char **argv;
  342. {
  343.     char file[100];
  344.     int number=40,refresh=10000,i,wind=0;
  345.     
  346.     if ((argc==2)&&(strcmp(argv[1],"?")==0)) DisplayUsage();
  347.     
  348.     strcpy(file,"SnowPic");
  349.     for (i=1;i<argc;i++)
  350.     {
  351.         if (argv[i][0]=='-')
  352.             switch (argv[i][1])
  353.             {
  354.                 case 'p': strcpy(file,&argv[i][2]); break;
  355.                 case 'n': number=atoi(&argv[i][2]); break;
  356.                 case 't': refresh=atoi(&argv[i][2]); break;
  357.                 case 'w': wind=atoi(&argv[i][2]); break;
  358.                 default: DisplayUsage();
  359.             }
  360.         else DisplayUsage();
  361.     }
  362.     if (refresh>-1) OpenAll(file,1);
  363.     else OpenAll(file,0);
  364.     DoSnow((long)number,(long)refresh,(long)wind);
  365.     abort(0);
  366. }