/* Amiga Demo program */
/* Shows fast area filling (triangles) in C plus color palette animation */
/* P. Kittel CBM Ffm 23 Jul 87, 13 Dec 87 */
/* Version with automatic NTSC/PAL recognization */
/* When called from CLI a number can be added to limit run time,
   1 count is approx. 1/2 second */
/* Compiled with Lattice C Compiler 3.10 */
/* Link: */
/* .Key f 
   Blink FROM LIB:c.o+<f>.o TO <f> LIB
                                   LIB:lc.lib+LIB:amiga.lib+LIB:lcm.lib */

#include <stdio.h>
#include <stdlib.h>
#include <intuition/intuition.h>
#include <graphics/gfxmacros.h>
#include <graphics/gfxbase.h>
#include <graphics/text.h>
#include <math.h>
struct IntuitionBase *IntuitionBase; /* Pointer aus exec */
struct GfxBase *GfxBase;
struct ViewPort *vp;
#define INTUITION_REV 33             /* Version 33 */
#define GRAPHICS_REV 33

struct TextFont *font;
struct TextAttr MyFont =
   {
   "topaz.font",
   TOPAZ_SIXTY,
   FS_NORMAL,
   FPF_ROMFONT,
   };

struct NewScreen NewScreen =
   {
   0,
   0,
   570,
   256,
   4,
   0, 1,
   HIRES,
   CUSTOMSCREEN,
   &MyFont,
   "Dreier",
   NULL,
   NULL,
   };

void main(argc,argv)
int argc;
char *argv[];
{
   struct Screen *Screen;
   struct NewWindow NewWindow;
   struct Window *Window;
   struct RastPort *rp;
   UWORD areabuffer[20];
   struct TmpRas mytmpras;
   struct AreaInfo myareainfo;
   PLANEPTR myplane;
   struct IntuiMessage *msg;
   int i,x1,y1,x2,y2,x3,y3,x9,y9,nn,nf,pf,ffi,co,fpal,z,zd,zm;
   int cc,c2,c6,cd;
   double fs,ff,sif,y0,ye,z1,z2,s2,z3,a,m,fr,fg,fb,ar,ag,ab,cf,nn1;
   double pr[16],pg[16],pb[16];
   int    pra[17],pga[17],pba[17];

   nf=4;     nn=15;

   nn1=(double)(nn-1);

   x9=500;   y9=184+53+2; fpal=1;   /* PAL */
             y0= 58.0;    ye=119.0;
   x1=250;   y1=140;      z1=0.0;
   x2= 90;   y2=y1;       z2=0.0;   z3=0.0;

   fs=0.0; ff=4000.0; sif=273.0+sin(0.15);  pf=0;
   c2=15*256; c6=15*16; co=2;
   cf=1.0; cc=0;        fr=0.0; fg=0.0; fb=0.0;

   IntuitionBase = (struct IntuitionBase *)
      OpenLibrary ("intuition.library",INTUITION_REV);
   if (IntuitionBase == NULL)
      { fpal=0;
        IntuitionBase = (struct IntutionBase *)
           OpenLibrary ("intuition.library",0);
        if (IntuitionBase == NULL) exit (FALSE);
      }

   GfxBase = (struct GfxBase *)
      OpenLibrary("graphics.library",GRAPHICS_REV);
   if(GfxBase == NULL)
      { CloseLibrary(IntuitionBase);
        exit (FALSE);
      }

   /* PAL / NTSC  ? */
   if (fpal > 0)
      { if (!((GfxBase->DisplayFlags) & PAL)) fpal=0; }

   if (fpal == 0)  
      { NewScreen.Height=200; /* NTSC */
        y9-=55; y1=105; y0=45.0; ye=93.0;
      }

   if((Screen = (struct Screen *) OpenScreen (&NewScreen)) == NULL)
      { CloseLibrary(GfxBase);
        CloseLibrary(IntuitionBase);
        exit (FALSE);
      }

   NewWindow.LeftEdge = 0;
   NewWindow.TopEdge  = 0;
   NewWindow.Width  = x9+9;
   NewWindow.Height = y9+16;
   NewWindow.DetailPen = 0;
   NewWindow.BlockPen  = 1;
   NewWindow.Title = "Commodore - AMIGA";
   NewWindow.Flags =
     WINDOWCLOSE|GIMMEZEROZERO|ACTIVATE;
   NewWindow.IDCMPFlags = CLOSEWINDOW;
   NewWindow.Type = CUSTOMSCREEN;
   NewWindow.FirstGadget = NULL;
   NewWindow.CheckMark = NULL;
   NewWindow.Screen = Screen;
   NewWindow.BitMap = NULL;
   NewWindow.MinWidth = x9;
   NewWindow.MinHeight = y9;
   NewWindow.MaxWidth = x9;
   NewWindow.MaxHeight = y9;
   if(( Window = ( struct Window *) OpenWindow( &NewWindow )) == NULL )
     { CloseScreen (Screen);
       CloseLibrary(IntuitionBase);
       CloseLibrary(GfxBase);
       exit(FALSE);
     }

   rp=Window->RPort;
   vp=&Screen->ViewPort;
   font=OpenFont(&MyFont);
   SetFont(rp,font);

   for (i=2; i<=nn; i++)
     { pra[i]=0; pga[i]=0; pba[i]=0;
       SetRGB4(vp,i,0,0,0);
     }
   SetRGB4(vp,0, 7, 7, 7);
   SetRGB4(vp,1,15,15,15);

   InitArea(&myareainfo,areabuffer,8);
   rp->AreaInfo=&myareainfo;
   myplane     =AllocRaster(320,256);
   rp->TmpRas  =InitTmpRas(&mytmpras,myplane,RASSIZE(320,256));

   SetAPen(rp,1);
   Move(rp,       4,    8); Text(rp,"Superfast"    , 9);
   Move(rp,       4,   17); Text(rp,"graphics"     , 8);
   SetAPen(rp,nn);
   Move(rp,       4,y9-12); Text(rp,"4096"         , 4);
   Move(rp,       4,y9- 3); Text(rp,"colors"       , 6);
   SetAPen(rp,1);
   Move(rp,x9-12*10,    8); Text(rp,"Area filling" ,12);
   Move(rp,x9-10*10,   17); Text(rp,"by Blitter"   ,10);
   Move(rp,x9- 6*10,y9-12); Text(rp,"Please"       , 6);
   Move(rp,x9- 8*10,y9- 3); Text(rp,"compare!"     , 8);

   zm = 9;
   zd = 0;
   if (argc > 1) { zm=atoi(argv[argc-1]); zd=1; } /* Time limit */
   z  = 0;

   while (z < zm)
     {
       if (msg = (struct IntuiMessage *)GetMsg(Window->UserPort))
         { ReplyMsg(msg); z=zm+1; }

       /* Compute new triangle coordinate, */
       /* radius and propagation angle are sine modulated */
       z1+=0.01;           if (z1 > 6.28) z1-=6.28;
       z2+=0.03*sin(z1);   if (z2 > 6.28) z2-=6.28;
       s2 =sin(z2);
       z3+=z1*s2/4;        if (z3 > 6.28) z3-=6.28;

       x3=x2;
       y3=y2;
       x2=(int)(120.0*(1.0+s2)*cos(z3)+(double)x1);
       y2=(int)(   y0*(1.0+s2)*sin(z3)+        ye);

       co+=1;
       if (co > nn)
         { co=2; z+=zd;

           /* Compute new color value, */
           /* propagation distance in values is sine modulated, */
           /* value of sif=1+16+256+(some odd decimals) */
           /* shall increase every color component by 1 */
           fs+=0.1; if (fs > 7.0) fs-=7.0;
           ff+=sif*(1.0+cos(fs)*1.02);
           if (ff > 4095.0) ff-=4095.0;
           ffi=(int)ff;
           ar=fr; ag=fg; ab=fb;
           fr=(ffi & 15)/15.0;
           fg=(ffi & c6)/((double)c6);
           fb=(ffi & c2)/((double)c2);
           pr[nn]=fr; pg[nn]=fg; pb[nn]=fb;

           if (cc++ > 20) { cc=0; cf=-cf; }

           /* Interpolate color values */
           /* Depending on cf, wrap always around 0 or 1, respectively, */
           /* to provide colors not being too identical */
           if ((cf*(fr+ar)) > cf)
             { m=(2.0-fr-ar)/nn1; a=ar-m;
               for (i=2; i<nn; i++)
                 { pr[i]=a+((double)i)*m; if (pr[i] > 1.0) pr[i]=2.0-pr[i]; }
             } else
             { m=(   -fr-ar)/nn1; a=ar-m;
               for (i=2; i<nn; i++)
                 { pr[i]=a+((double)i)*m; if (pr[i] < 0.0) pr[i]=   -pr[i]; }
             }

           if ((cf*(fg+ag)) > cf)
             { m=(2.0-fg-ag)/nn1; a=ag-m;
               for (i=2; i<nn; i++)
                 { pg[i]=a+((double)i)*m; if (pg[i] > 1.0) pg[i]=2.0-pg[i]; }
             } else
             { m=(   -fg-ag)/nn1; a=ag-m;
               for (i=2; i<nn; i++)
                 { pg[i]=a+((double)i)*m; if (pg[i] < 0.0) pg[i]=   -pg[i]; }
             }
              
           if ((cf*(fb+ab)) > cf)
             { m=(2.0-fb-ab)/nn1; a=ab-m;
               for (i=2; i<nn; i++)
                 { pb[i]=a+((double)i)*m; if (pb[i] > 1.0) pb[i]=2.0-pb[i]; }
             } else
             { m=(   -fb-ab)/nn1; a=ab-m;
               for (i=2; i<nn; i++)
                 { pb[i]=a+((double)i)*m; if (pb[i] < 0.0) pb[i]=   -pb[i]; }
             }
         }

       /* Cycle Palette */
       for (i=nn+1; i>2; i--)
         { pra[i]=pra[i-1]; pga[i]=pga[i-1];  pba[i]=pba[i-1]; }
       pra[2]=pra[nn+1];    pga[2]=pga[nn+1]; pba[2]=pba[nn+1];
       cd=2*co-2; if (cd > nn) cd=cd-nn+1;
       pra[cd]=(int)(pr[co]*nn);
       pga[cd]=(int)(pg[co]*nn);
       pba[cd]=(int)(pb[co]*nn);
       for (i=2; i<=nn; i++) SetRGB4(vp,i,pra[i],pga[i],pba[i]);

       /* Draw triangle */
       SetAPen (rp,co);
       AreaMove(rp,x1,y1);
       AreaDraw(rp,x2,y2);
       AreaDraw(rp,x3,y3);
       AreaEnd (rp);
     }  

   FreeRaster  (myplane,320,256);
   CloseWindow (Window);
   CloseScreen (Screen);
   CloseLibrary(IntuitionBase);
   CloseLibrary(GfxBase);
}
