/*********************************************************
**                                                      **
**      CANYON (w) by Daniel Gembris in 1989            **
**                                                      **
*********************************************************/

#include <intuition/intuition.h>
#include <graphics/gfx.h>
#include <devices/keymap.h>
#include <graphics/regions.h>
#include <graphics/copper.h>
#include <graphics/gels.h>
#include <graphics/gfxbase.h>
#include <graphics/clip.h>
#include <graphics/view.h>
#include <graphics/rastport.h>
#include <graphics/layers.h>
#include <graphics/display.h>
#include <graphics/gfxmacros.h>
#include <hardware/blit.h>
#include <functions.h>
#include <math.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <exec/types.h>

ULONG class;
USHORT code;
UWORD i,Nummer;
WORD *count1 = 0xBF0800;          /* die Samen für den Zufall-Algorithmus */
WORD *count2 = 0xBF0900;          /* werden den Counter-Registern der CIAs*/
WORD *count3 = 0xBF0A00;          /* entnommen */
float number0,number1;

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Screen *screen;
struct Window *window;
struct RastPort *rastport;
struct ViewPort *viewport;
struct IntuiMessage *message;

/* IFF-Kopfdaten (komplette IFF-Datei ohne Body-Chunk) */

UWORD head[] = {
 0x464f, 0x524d, 0x0000, 0x5e2a, 0x494c, 0x424d,
 0x424d, 0x4844, 0x0000, 0x0014, 0x0140, 0x00c8,
 0x0000, 0x0000, 0x0300, 0x0000, 0x0000, 0x0a0b,
 0x0140, 0x00c8, 0x434d, 0x4150, 0x0000, 0x0018,
 0x0000, 0x0000, 0x0000, 0x0000, 0x00a0, 0x7000,
 0xc080, 0x00e0, 0xa000, 0x0000, 0x00f0, 0xf0f0,
 0x4341, 0x4d47, 0x0000, 0x0004, 0x0000, 0x4000,
 0x4343, 0x5254, 0x0000, 0x000e, 0x0000, 0xfeff,
 0x0000, 0x0000, 0x000f, 0x423f, 0x0000, 0x424f,
 0x4459, 0x0000, 0x5dc0  };

struct NewScreen Bildschirm = 
{
 0,0,
 320,256,
 3,0,1,
 SPRITES ,
 CUSTOMSCREEN,
 NULL,
 ( UBYTE *) "",
 NULL,
 NULL
};

struct NewWindow Fenster =
{
 0,0,
 320,233,
 0,1,
 CLOSEWINDOW,
 WINDOWCLOSE|ACTIVATE|WINDOWDRAG|GIMMEZEROZERO,
 NULL,
 NULL,
 (UBYTE *) "CANYON (w) by Daniel Gembris in 1989",
 0,
 NULL,
 320,232,
 320,234,
 CUSTOMSCREEN
};

ULONG palette [8][3] =
{
 {0,0,0},{15,15,15},{7,7,7},{10,7,0},{12,8,0},{14,10,0},{0,0,0},{15,15,15}
};

Initial_Screen ()

{
 GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",0L);
 if (GfxBase == NULL)
 {
  printf ("\f\n\n\t\tKeine Grafik-Library\n\n");
  exit();
 }
 IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",0L);
 if (IntuitionBase == NULL)
 {
  CloseLibrary(GfxBase);
  printf ("\f\n\n\t\tKeine Intuition-Library\n\n");
  exit();
 }
 screen  =  (struct Screen *) OpenScreen(&Bildschirm);
 if (screen == NULL) 
 {
  CloseLibrary(IntuitionBase);
  CloseLibrary(GfxBase);
  printf ("\f\n\n\t\tKein Screen\n\n");
  exit();
 }
 Fenster.Screen = screen;
 window  =  (struct Window *) OpenWindow(&Fenster);
 if (window == NULL)
 {
  CloseScreen (screen);
  CloseLibrary (IntuitionBase);
  CloseLibrary (GfxBase);
 }
}


Openscr()
{
 rastport = window->RPort;
 viewport = &screen->ViewPort;
 
 for (i = 0; i<8; i++)
 {
  SetRGB4 (&screen->ViewPort, (LONG) i, palette[i][0],
          palette[i][1], palette[i][2]);
 }
}

Closescr()
{
 CloseWindow (window);
 CloseScreen (screen);
 CloseLibrary (GfxBase);
 CloseLibrary (IntuitionBase);
}


Linie (a,b,a1,b1,Farbe)

SHORT  Farbe;
FLOAT a,b,a1,b1;
{
 SetDrMd (rastport, JAM1);
 SetAPen(rastport, (LONG)Farbe);
 Move (rastport, (LONG) a, (LONG) b);
 Draw (rastport, (LONG) a1, (LONG) b1);
}

FLOAT random()
{
   FLOAT
      temp;
   STATIC WORD x,y,z;

   x = *count1;            /* Samen "erzeugen" */
   y = *count2;
   z = *count3;

   if ( (x = 171 * (x % 177) - 2 * (x / 177)) < 0 )
      x += 30269;
      
   if ( (y = 172 * (y % 176) - 35 * (y / 176)) < 0 )
      y += 30307;
   
   if ( (z = 170 * (z % 178) - 63 * (z / 178)) < 0 )
      z += 30323;
      
   temp = x/30269.0 + y/30307.0 + z/30323.0;
   
   return (temp - trunc(temp));
}
VOID rnd()
{
  FLOAT hnum0,hnum1;
  int hi;
  for (hi=0;hi<=30000;hi++) {}
  hnum0=random();
  for (hi=0;hi<=30000;hi++) {}
  hnum1=random();
  if (hnum0>hnum1)
  {
    number0 = hnum1;
    number1 = hnum0;
  }
  else
  {
    number0 = hnum0;
    number1 = hnum1;
  }
}

main(argc, argv)
long int argc;
char *argv[];
{

 FLOAT yc=0, xc=1, xl=-.15, xr=.26, yo=.47, yu=.9, dx, dy, y1;
 FLOAT u,v,u1,v1;
 REGISTER FLOAT y, x , x2, y2;
 long int n,m,k,s=60,t=20,xm=210,ym=105,ze,again;
 char var[3];
 char ask[2];
 char name[30];
 ULONG handle;

 again = TRUE;
 while(again)
 {
   if ((argc == 1) || (argc >= 65536))
   {
     while(strcmp(var,"q"))
     {
       printf("\f              CANYON (w) by DANIEL GEMBRIS in 1989\n");
       printf("              ====================================\n");
       printf("\n\n");
       printf("xc = %f\n", xc);
       printf("yc = %f\n", yc);
       printf("xl = %f\n", xl);
       printf("xr = %f\n", xr);
       printf("yo = %f\n", yo);
       printf("yu = %f\n", yu);
       printf("s  = %ld\n", s);
       printf("t  = %ld\n", t);
       printf("xm = %ld\n", xm);
       printf("ym = %ld\n", ym);
       printf("\nWelche Variable möchten Sie ändern ?\n");
       printf("(Ende mit `q')\n");
       scanf("%s", var);
       if (strcmp(var, "q")) printf("Neuer Wert :\n");
       if (!strcmp(var, "xc")) scanf("%f", &xc);
       if (!strcmp(var, "yc")) scanf("%f", &yc);
       if (!strcmp(var, "xl")) scanf("%f", &xl);
       if (!strcmp(var, "xr")) scanf("%f", &xr);
       if (!strcmp(var, "yo")) scanf("%f", &yo);
       if (!strcmp(var, "yu")) scanf("%f", &yu);
       if (!strcmp(var, "s")) scanf("%ld", &s);
       if (!strcmp(var, "t")) scanf("%ld", &t);
       if (!strcmp(var, "xm")) scanf("%ld", &xm);
       if (!strcmp(var, "ym")) scanf("%ld", &ym);
     }
   }

   else            /* Aufruf von Workbench ? */
   {               /* ja, dann Zufallswerte ermitteln */
     rnd();
     xl=number0;
     xr=number1;
     rnd();
     yo=number0;
     yu=number1;
   }

   *var = ' ';
   Initial_Screen ();
   Openscr();

   dx=(xr-xl)/xm;
   dy=(yu-yo)/ym;
   for (n=0;n<=ym;n++)
   {
    y1=yo+n*dy;
    for (m=0;m<=xm;m++)
    {
     message = (struct IntuiMessage *)GetMsg(window->UserPort);
     if (message != 0)
     {
      class = message -> Class;
      code = message -> Code;
      if (class = CLOSEWINDOW)
      {
       m=xm+1;
       n=ym+1;
      }
      ReplyMsg(message);
     }
     x=xl+m*dx;
     y=y1;
     k=0;
     do
     {
      x2=x*x;
      y2=y*y;
      y=2*x*y-yc;
      x=x2-y2-xc;
      k=k+1;
     } while ((k<t) && (x2+y2<s));
     u = m+53-(n/2);
     u1 = u+1;
     v = n+80;
     v1 = v-3*(k-1);
     Linie(u,v,u,v1,3);
     Linie(u1,v,u1,v1,4);
     Linie(u,v1,u1,v1,5);
    }
   }
    SetRGB4 (&screen->ViewPort, (LONG) 1, (LONG) 0, (LONG) 0, (LONG) 0);
    SetRGB4 (&screen->ViewPort, (LONG) 2, (LONG) 0, (LONG) 0, (LONG) 0);

    if ((argc == 1) || (argc >= 65536))
    {
      ScreenToBack(screen);
      printf("\nSoll das Bild abgespeichert werden (j|n) ?\n");
      scanf("%s", ask);
      if (!strcmp(ask, "j"))
      {
          printf("Wie soll das Bild heißen ?\n");
          scanf("%s", name);
          if ((handle = (LONG) Open((UBYTE *) name, MODE_NEWFILE)) == 0) {
              Closescr();
              exit();
          }

          Write(handle, (UBYTE *) head, (LONG) 114);
          rastport = &screen->RastPort;
          for(ze=0;ze<=199;ze++)
          {
            Write(handle, (UBYTE *) rastport->BitMap->Planes[0]+(ze*40), (LONG) 40);
            Write(handle, (UBYTE *) rastport->BitMap->Planes[1]+(ze*40), (LONG) 40);
            Write(handle, (UBYTE *) rastport->BitMap->Planes[2]+(ze*40), (LONG) 40);
          }
          Close(handle);
      }
      printf("\nNeustart (Variablenwerte bleiben erhalten) (j|n) ?\n");
      scanf("%s", ask);
      if (strcmp(ask, "j")) again = FALSE;
      Closescr();
    }  
    else
    {
      while (class != CLOSEWINDOW)
      {
        WaitPort(window->UserPort);
        message = (struct IntuiMessage *)GetMsg(window->UserPort);
        if (message != NULL)
        {
          class = message -> Class;
          code = message -> Code;
        }
      }
      again = FALSE;
      Closescr();
    }
 }
}

