/* --------                                               --------  *
   --------                                               --------  *
   --------          H I R E S   G R A P H I C S          --------  *
   --------                                               --------  *
   --------             Plotting a SINE Wave              --------  *
   --------                                               --------  *
   --------                 C version                     --------  *
   --------                                               --------  *
   --------                                               --------  */    



/* --------       Preprocessor directives      -------- */
/* -------- Library references and definitions -------- */

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <math.h> 
#include <intuition/intuition.h> 
#include <proto/exec.h> 
#include <proto/dos.h> 
#include <proto/intuition.h> 
#include <proto/graphics.h>



/* -------- External data types for videomode -------- */

#define INTUITION_REV 33L 
#define GRAPHICS_REV 33L 
#define XPIXELS 640 
#define YPIXELS 200

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Screen *usr_Screen;
struct Window *usr_Window;
struct RastPort *usr_rp;

struct NewScreen fullHires =
{
    0,                  /* the LeftEdge must be zero          */
    0,                  /* TopEdge                            */
    XPIXELS,            /* Width (high resolution)            */
    YPIXELS,            /* Height (non-interlace)             */
    1,                  /* Depth (2 colors will be available) */
    0,                  /* Default DetailPen                  */
    1,                  /* Default BlockPen                   */
    HIRES,              /* the high-resolution display mode   */
    CUSTOMSCREEN,       /* the screen type                    */
    NULL,               /* no special font                    */
    NULL,               /* no screen title                    */
    NULL,               /* no special screen gadgets          */
    NULL                /* no CustomBitMap                    */
};

struct NewWindow clearWindow =
{
    0,                  /* LeftEdge                */
    0,                  /* TopEdge                 */
    XPIXELS,            /* Width (high resolution) */
    YPIXELS,            /* Height (non-interlace)  */
    0,                  /* Default DetailPen       */
    1,                  /* Default BlockPen        */
    RAWKEY,             /* IDCMP Flags             */
    ACTIVATE |
    BORDERLESS,         /* Flags                   */
    NULL,               /* no special gadgets      */
    NULL,               /* no checkmark            */
    NULL,               /* no Window title         */
    NULL,               /* Attach a screen later   */
    NULL,               /* No bitmap               */
    NULL,               /* Minimum width           */
    NULL,               /* Minimum height          */
    NULL,               /* Maximum width           */
    NULL,               /* Maximum height          */
    CUSTOMSCREEN        /* A screen of our own     */
};
 

   
/* -------- External data types for scaling -------- */

struct XY_Scale
{
    DOUBLE xmin;
    DOUBLE ymin;
    DOUBLE xmax;
    DOUBLE ymax;
    DOUBLE dx;
    DOUBLE dy;
};

struct XY_Scale s;



    /* -------- Function prototype definitions -------- */

VOID main(int argc, char *argv[]);
VOID Scale_Window(VOID);
LONG Fx(DOUBLE x);
LONG Fy(DOUBLE y);
DOUBLE Rad(DOUBLE x);


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

    /* -------- External data type declarations -------- */

    GLOBAL struct IntuitionBase *IntuitionBase;
    GLOBAL struct GfxBase *GfxBase;
    GLOBAL struct Screen *usr_Screen;
    GLOBAL struct NewScreen fullHires;
    GLOBAL struct Window *usr_Window;
    GLOBAL struct NewWindow clearWindow;
    GLOBAL struct RastPort *usr_rp;
    GLOBAL struct XY_Scale s;

   
 
    /* -------- Internal data type declarations -------- */

    FLOAT angle, da;
    char message_buffer[80];

    struct IntuiMessage *msg = NULL;
    ULONG signalmask;



    /* -------- Set the Videomode -------- */

   if(!(IntuitionBase = (struct IntuitionBase *)
                        OpenLibrary("intuition.library",INTUITION_REV)))
   {
      printf("Cannot open intuition.library\n");
      Delay(200);       exit(RETURN_FAIL);
   }

   if(!(GfxBase = (struct GfxBase *)
                    OpenLibrary("graphics.library", GRAPHICS_REV)))
   {
      printf("Can't load graphics.library.\n");
      Delay(200);
      CloseLibrary(IntuitionBase);
      exit(RETURN_FAIL);
   }
   if(!(usr_Screen = (struct Screen *)OpenScreen(&fullHires)))
   {
      printf("Cannot open screen!!\n");
      Delay(200);
      CloseLibrary(IntuitionBase);
      CloseLibrary(GfxBase);
      exit(RETURN_FAIL);
   }

   clearWindow.Screen = usr_Screen;

   if(!(usr_Window = (struct Window *)OpenWindow(&clearWindow)))
   {
      printf("Cannot open window!!\n");
      Delay(200);
      CloseScreen(usr_Screen);
      CloseLibrary(IntuitionBase);
      CloseLibrary(GfxBase);
      exit(RETURN_FAIL);
   }

   usr_rp = usr_Window->RPort;



   /* -------- Scale the screen in degrees -------- */

   s.xmin = -360.0;
   s.xmax =  360.0;
   s.ymin = -1.2;
   s.ymax =  1.2;
   da = 15.0;
   Scale_Window();

    

   /* -------- Draw the sine wave on the screen -------- */

   for(angle = s.xmin, Move(usr_rp, Fx(angle),Fy(sin(Rad(angle))));
       angle <= s.xmax;
       angle += da)
          Draw(usr_rp, Fx(angle),Fy(sin(Rad(angle))));



   /* ------ Display instructions to proceed -------- */

   strcpy(message_buffer, "... press any key ...");
   Move(usr_rp, (XPIXELS - 8*strlen(message_buffer))/2, YPIXELS - 2);
   Text(usr_rp, message_buffer, strlen(message_buffer));



   /* -------- Hold the screen for viewing -------- */

   signalmask = 1L << usr_Window->UserPort->mp_SigBit;
   Wait(signalmask);

   while(msg = (struct IntuiMessage *)GetMsg(usr_Window->UserPort))
      ReplyMsg((struct Message *)msg);



    /* -------- Restore the original Video environment --------- */

   if(usr_Window)
      CloseWindow((struct Window *)usr_Window);

   if(usr_Screen)
      CloseScreen((struct Screen *)usr_Screen);

   if(GfxBase)
      CloseLibrary((struct Library *)GfxBase);
 
   if(IntuitionBase)
      CloseLibrary((struct Library *)IntuitionBase);
       exit(RETURN_OK);
}



/* -------- Window scaling -------- */

VOID Scale_Window(VOID)
{
   GLOBAL struct XY_Scale s;

   s.dx = (s.xmax-s.xmin)/(DOUBLE)(XPIXELS-1);
   s.dy = (s.ymax-s.ymin)/(DOUBLE)(YPIXELS-1);
}



/* -------- Horizontal coordinate conversion -------- */

LONG Fx(DOUBLE x)
{
   GLOBAL struct XY_Scale s;

   if(x > s.xmin-s.dx/2 && x < s.xmax+s.dx/2)
      return((LONG)( ( (x-s.xmin)+s.dx/2 )/s.dx ) );
   else if(x < s.xmin)
      return((LONG)0);
   else return((LONG)XPIXELS-1);
}



/* -------- Vertical coordinate conversion -------- */

LONG Fy(DOUBLE y)
{
   GLOBAL struct XY_Scale s;

   if( y > (s.ymin-s.dy/2) && y < (s.ymax+s.dy/2) )
      return( (YPIXELS - 1) - (LONG)(((y-s.ymin)+s.dy/2)/s.dy));
   else if(y < s.ymin)
      return((LONG)YPIXELS-1);
   else return((LONG)0);
}



/* -------- Angle conversion -------- */

DOUBLE Rad(DOUBLE x)
{
    return((DOUBLE)x*((DOUBLE)3.141592653589793/(DOUBLE)180.0));
}

