#include <stdio.h>
#include <exec/types.h>
#include <exec/exec.h>
#include "exec/memory.h"



#include <hardware/dmabits.h>
#include <hardware/blit.h>

#include <graphics/gfx.h>
#include <graphics/gfxmacros.h>
#include <graphics/copper.h>
#include <graphics/view.h>
#include <graphics/rastport.h>
#include <graphics/gels.h>
#include <graphics/regions.h>
#include <graphics/clip.h>
#include <graphics/text.h>
#include <graphics/gfxbase.h>

#include <hardware/custom.h>


/*   An overview of Amiga graphics--what's where:

  View  (what you see on the screen, contains important Modes variables
   |     for things like interlaced screen, dual playfield, and others)
   |
   |--(points to)
   V
  ViewPort1 --> ViewPort2 --> ... --> ViewPortN
   |   (A ViewPort is a horizontal slice of the screen; here you specify
   |  height, width, depth (determines # of colors available),
   |  sprites, type of display: dual-playfield, resolution, interlace,
   |  hold-and-modify, extra-halfbright)
   |    (The variables DxOffset and DyOffset position the upper left 
   |  corner of the viewport on the screen)
   |    (If there are multiple viewports, the first one points to the
   |  second, the second to the third, etc.)
   |\
   | \
   | V
   | ColorMap (establishes the colors available to this viewport)
   V
  RasInfo (contains RxOffset, RyOffset, which mark the pixel within 
   |       the bitmap (see below) that will be positioned in the
   |	   upper left corner of the viewport--you can scroll the 
   |	   bitmap in a viewport by changing these values)
   |
   |     RastPort (contains info on pen colors, text info, pointers
   |     /         to GelsInfo, AreaInfo (when needed)
   |    /
   |   /
   V  V
  BitMap (contains actual memory that represents an area of image;
          the image can be larger than what is visible on the screen)
*/
#define NOT_ENOUGH_MEMORY -1000

#define MDEPTH 3    /* of bitmap of main viewport */  
#define MWIDTH 320    
#define MHEIGHT 180

#define SDEPTH 2    /* of bitmap of scroll viewport */  
#define SWIDTH 8000    
#define SHEIGHT 19



/* construct a simple display */

struct View v;
struct ViewPort mvp,svp;

/* pointer to colormap structure, dynamically allocated */
struct ColorMap *mcm, *scm;

struct RasInfo mri, sri;
struct BitMap mbm, sbm;
struct RastPort mrp, srp;

extern struct ColorMap *GetColorMap();
struct GfxBase *GfxBase;


/* save the pointer to the old view so we can restore it later */
struct View *oldview;

USHORT scolortable[]=
{
 /*  clear, gold,  cyan,  cherry */
     0x000, 0xfb0, 0xccc, 0xf15 
};

USHORT mcolortable[]=
{
 /*  clear, blue,  black, rose   */
     0x000, 0x55f, 0x000, 0xc57, 0x500, 0xf00, 0x00f, 0x007
};

UWORD *colorpalette;

LONG i;
SHORT dx;

 UWORD colors[20] =
 {
 0X00f,0X20f,0X40f,0X60f,0X80f,
 0Xa0f,0Xc0f,0Xe0f,0Xc0f,0Xa0f,
 0X80f,0X60f,0X40f,0X20f,0X00f,
 0Xf00,0Xf02,0Xf04,0Xf06,0Xf08
 };

/* * * * * * * * * * * * * * * * * * * * * * * * * */

main()
{

  /* Open the graphics library.... */
  GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0);
  if (GfxBase == NULL) exit(1);

  /* Save the current view to restore it later. */

  oldview = GfxBase->ActiView;

  InitView(&v);       /* initialize view */
  InitVPort(&mvp); /* init viewport */
  InitVPort(&svp);
  v.ViewPort = &svp;     /* link view into viewport */

  /* Init bit map (for rasinfo and rastport). */

  InitBitMap(&mbm, MDEPTH,MWIDTH, MHEIGHT);
  InitBitMap(&sbm, SDEPTH,SWIDTH, SHEIGHT);

  for(i=0; i<MDEPTH; i++) {
    mbm.Planes[i] = (PLANEPTR) AllocRaster(MWIDTH, MHEIGHT);
	if(mbm.Planes[i] == NULL) exit(NOT_ENOUGH_MEMORY);
	BltClear(mbm.Planes[i], RASSIZE(MWIDTH, MHEIGHT), 1);
  }

  for(i=0; i<SDEPTH; i++) {
    sbm.Planes[i] = (PLANEPTR) AllocRaster(SWIDTH, SHEIGHT);
	if(sbm.Planes[i] == NULL) exit(NOT_ENOUGH_MEMORY);
	BltClear(sbm.Planes[i], RASSIZE(SWIDTH, SHEIGHT), 1);
  }


  /* Init RasInfos for playfield 1, then playfield 2. */

  mri.BitMap = &mbm;
  mri.RxOffset = 0;
  mri.RyOffset = 0;
  mri.Next = NULL;

  sri.BitMap = &sbm;
  sri.RxOffset = 0;
  sri.RyOffset = 0;
  sri.Next = &mri;   

  /* Now specify critical characteristics.... */
  mvp.DWidth = MWIDTH;
  mvp.DHeight = MHEIGHT;
  mvp.RasInfo = &mri;
  mvp.Next = NULL;

  svp.DxOffset = 0; 
  svp.DyOffset = MHEIGHT+1; 
  svp.DWidth = MWIDTH;
  svp.DHeight = SHEIGHT;
  svp.RasInfo = &sri;
  svp.Next = &mvp;


  /* Initialize the color map, which has 4 entries (sprites take up
     the top 16).   */

  mcm = GetColorMap(8);

  /* If no memory for color map, reclaim memory and exit. */
  if (mcm == NULL)
  {
    FreeMemory();
    exit(100);
  }

  /* 'colorpalette' points to the color table for this color map. */
  colorpalette = (UWORD *)mcm->ColorTable;
  /* We initialize this color table with the values from our array. */
  for(i=0; i<8; i++)  *colorpalette++ = mcolortable[i];
  /* Copy the color table into the viewport structure. */
  mvp.ColorMap = mcm;

  /* Initialize the color map, which has 32 entries */

  scm = GetColorMap(4);

  /* If no memory for color map, reclaim memory and exit. */
  if (scm == NULL)
  {
    FreeMemory();
    exit(100);
  }

  /* 'colorpalette' points to the color table for this color map. */
  colorpalette = (UWORD *)scm->ColorTable;
  /* We initialize this color table with the values from our array. */
  for(i=0; i<4; i++)  *colorpalette++ = scolortable[i];

  /* Copy the color table into the viewport structure. */
  svp.ColorMap = scm;


  /* Allocate space for bitmap 1, then bitmap 2. */


  /* Establish rast.port for playfield */

  InitRastPort(&mrp);
  InitRastPort(&srp);

  mrp.BitMap = &mbm;
  srp.BitMap = &sbm;



  /* These three instructions assemble and "load" the view we've defined.*/
  MakeVPort(&v, &svp);
  MakeVPort(&v, &mvp);
  MrgCop(&v);

  SetRast(&mrp,0);
  SetRast(&srp,0);

  LoadView(&v);


  SetAPen(&srp,1);
  Move(&srp,320,14);
  Text(&srp,"This is the first scrolly produced in the BAMIGA SECTOR ONE PROGRAMMING LAB ",90-14);
  Text(&srp,"deep beneath the surface of the city Antwerp in Belgium. ",71-14);
  Text(&srp,"BAMIGA SECTOR ONE : Leading the way for Belgium on the Amiga. ",76-14);
  Text(&srp,"And now for something completly different ... A joke (?) for all you Amigoids : ",94-14);
  Text(&srp,"MAC owners do it in black and white, ATARI owners do it in colour and AMIGA owners ",97-14);
  Text(&srp,"... do it in HOLD AND MODIFY ! And while Bert is still trying to compile his first ",97-14);
  Text(&srp,"C-program ('Only kidding Berty Boy !), we welcome 2 new BS ONE SUBDIVISIONS, ",91-14);
  Text(&srp,"namely, in Holland, land of cheese, tulips and 1001 (hahaha ...) the SUBDIVISION",94-14);
  Text(&srp," DDL, our beloved brother Evert and in Belgium, land of Pommes Frites ",84-14);
  Text(&srp,"or French Freis like some assholes tend to call them, Manneke Pis ",80-14);
  Text(&srp,"(this 'll give the 1001 crew a nice subject to comment about in their next demo) ",95-14);
  Text(&srp,"and BAMIGA SECTOR ONE (the ONLY Belgian group worth swapping with) the SUBDIVISION Serge!",103-14); 


 sri.RxOffset = 0;
 sri.RyOffset = 0;



 for(dx=0;dx<(SWIDTH-MWIDTH)/3;dx++)
 {
  SetAPen(&mrp,dx%4);
  SetDrPt(&mrp,0xFFFF);

  Move(&mrp,0,0);Draw(&mrp,319-dx%320,dx%MHEIGHT);
  Move(&mrp,319,0);Draw(&mrp,dx%320,dx%MHEIGHT);
  MakeVPort(&v,&mvp);

  sri.RxOffset = sri.RxOffset + 3;
  MakeVPort(&v,&svp);

  MrgCop(&v);
  WaitTOF();

  LoadView(&v);
 }

 sri.RxOffset = 0;
 sri.RyOffset = 0;


 for(dx=0;dx<(SWIDTH-MWIDTH)/3;dx++)
 {
  SetAPen(&mrp,dx%4+4);
  SetDrPt(&mrp,0xcccc);

  Move(&mrp,0,0);Draw(&mrp,319-dx%320,dx%MHEIGHT);
  Move(&mrp,319,0);Draw(&mrp,dx%320,dx%MHEIGHT);

  MakeVPort(&v,&mvp);

  MakeVPort(&v,&svp);
  sri.RxOffset = sri.RxOffset + 3;

  MrgCop(&v);
  WaitTOF();

  LoadView(&v);
 }

 LoadView(oldview);
 FreeMemory();
 CloseLibrary(GfxBase);
} 

FreeMemory()
/* Return user and system-allocated memory to the system. */
{
  LONG i;

  /* Free bitmap */
  for (i=0; i<MDEPTH; i++)
  {
   if (mbm.Planes[i] != NULL) FreeRaster(mbm.Planes[i], MWIDTH, MHEIGHT);
  }

  /* Free bitmap */
  for (i=0; i<SDEPTH; i++)
  {
   if (sbm.Planes[i] != NULL) FreeRaster(sbm.Planes[i], SWIDTH, SHEIGHT);
  }

  /* free the color map created by GetColorMap() */
  if (mcm != NULL)  FreeColorMap(mcm);
  if (scm != NULL)  FreeColorMap(scm);

  /* Free some other dynamically created structures. */
  FreeVPortCopLists(&mvp);

/*  FreeVPortCopLists(&svp); */
  
  FreeCprList(v.LOFCprList);

  return(0);

}   /* end FreeMemory */
