/* Dieser Programm erstellt eine Double-Buffer-Anzeige.
   Das heisst: Es gibt zwei Bildschirme. Immer einer wird angezeigt und
   im andern wird gezeichnet. Das Programm ist sehr leicht zu veraendern:
   nur unten zwischen den beiden waagerechten Linien aendern.
   Die Funktion Init() macht die Anzeige bereit.
   Die Funktion Switch() wechselt zwischen den beiden Anzeigen. Das heisst:
   Das vorher Gezeichnete (immer rp als RastPort-Argument verwenden) wird
   angezeigt, das vorher Angezeigte wird geloescht und als Zeichenfeld
   bereitgestellt. Das Umschalten wird synchronisiert, so kann man perferkte
   Animationen machen (abolut Flackerfrei).
   Die Funktio FreeMemory() raeumt den Speicher auf.
*/

#include "viewport.h"

#define DEPTH 2                   /* Anzahl der Bitplanes   */
#define WIDTH 325                 /* Breite des Screens */
#define HEIGHT 205                /* Hoehe  des Screens */

struct View v1,v2,*oldview;
struct ViewPort vp1,vp2;
struct ColorMap *cm1,*cm2;
struct RasInfo ri1,ri2;
struct BitMap b1,b2;
struct RastPort rastport,*rp;
extern struct ColorMap *GetColorMap();
USHORT colortable[]={0x000,0xf00,0x0f0,0x00f},*colorpalette,visible=1;
struct GfxBase *GfxBase,*OpenLibrary();
unsigned char *displaymem;
PLANEPTR *AllocRaster();
int i;




/* ------------------------Dies ist das Hauptprogramm--------------------*/
/*                              Hier aendern                             */
main()
{
  int a,i,x[10];
  Init();

  for(i=0;i<10;i++) x[i]=0;

  for(a=0;a<320;a++) {
    for(i=0;i<10;i++) {
      if((x[i]+=i)>320) x[i]-=320;
      Move(rp,x[i],0);
      Draw(rp,x[i],200);
    };
    Switch();
  };
  FreeMemory();
}
/*-------------------------Ende Hauptprogramm------------------------------*/
/*                       Ab hier nichts mehr aendern                       */

Init()
{
  int i;

  GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0);
  if (GfxBase == NULL) exit(100);

  oldview=GfxBase->ActiView;

  InitView(&v1);
  InitView(&v2);

  InitVPort(&vp1);
  InitVPort(&vp2);

  v1.ViewPort=&vp1;
  v2.ViewPort=&vp2;

  InitBitMap(&b1,DEPTH,WIDTH,HEIGHT);
  for(i=0;i<DEPTH;i++) {
    b1.Planes[i]=(PLANEPTR)AllocRaster(WIDTH,HEIGHT);
    if (b1.Planes[i]==NULL) exit(200);
  }

  InitBitMap(&b2,DEPTH,WIDTH,HEIGHT);
  for(i=0;i<DEPTH;i++) {
    b2.Planes[i]=(PLANEPTR)AllocRaster(WIDTH,HEIGHT);
    if (b2.Planes[i]==NULL) exit(300);
  }

  ri1.BitMap=&b1;      /* RasInfo zeigt auf BitMap */
  ri1.RxOffset=0;      /* Verschiebung des 0-Punkts im Grafikspeicher */
  ri1.RyOffset=0;
  ri1.Next=NULL;       /* Naechster RasInfo: Keiner */

  ri2.BitMap=&b2;
  ri2.RxOffset=0;
  ri2.RyOffset=0;
  ri2.Next=NULL;

  cm1=GetColorMap(4);
  if(cm1==NULL) exit(300);
  colorpalette=(unsigned short *)cm1->ColorTable;
  for(i=0;i<4;i++) {
    *colorpalette++=colortable[i];
  }

  cm2=GetColorMap(4);
  if(cm2==NULL) exit(400);
  colorpalette=(unsigned short *)cm2->ColorTable;
  for(i=0;i<4;i++) {
    *colorpalette++=colortable[i];
  }


  vp1.DWidth=WIDTH;   /* Die Breite des ViewPorts */
  vp1.DHeight=HEIGHT; /* Die Hoehe des ViewPorts  */
  vp1.RasInfo=&ri1;    /* Zeigt auf die RasInfo-Struktur  */
  vp1.ColorMap=cm1;    /* Zeigt auf die ColorMap-Struktur */

  vp2.DWidth=WIDTH;
  vp2.DHeight=HEIGHT;
  vp2.RasInfo=&ri2;
  vp2.ColorMap=cm2;

  InitRastPort(&rastport);

  MakeVPort(&v1,&vp1);
  MrgCop(&v1);

  MakeVPort(&v2,&vp2);
  MrgCop(&v2);

  for(i=0;i<2;i++) {
    displaymem=(unsigned char *)b1.Planes[i];
    BltClear(displaymem,RASSIZE(WIDTH,HEIGHT),0);
  }

  for(i=0;i<2;i++) {
    displaymem=(unsigned char *)b2.Planes[i];
    BltClear(displaymem,RASSIZE(WIDTH,HEIGHT),0);
  }

  LoadView(&v1);

  rastport.BitMap=&b2;
  rp=&rastport;

  SetAPen(rp,1);
  SetBPen(rp,0);
  SetDrMd(rp,JAM1);
}

FreeMemory()
{
  int i;
  LoadView(oldview);

  for(i=0;i<DEPTH;i++) {
    FreeRaster(b1.Planes[i],WIDTH,HEIGHT);
    FreeRaster(b2.Planes[i],WIDTH,HEIGHT);
  }

  FreeColorMap(cm1);           /* Farbspeicher freimachen */
  FreeColorMap(cm2);
  FreeVPortCopLists(&vp1);     /* Copper Lists freimachen (Wurden vom */
  FreeVPortCopLists(&vp2);
  FreeCprList(v1.LOFCprList);  /* Copper gebraucht */
  FreeCprList(v2.LOFCprList);

  CloseLibrary(GfxBase);      /* graphics.library loslassen */

  exit(0);                    /* Ade ! */
}

Switch()
{
  int a;
  if(visible==1) {
    visible=2;
    WaitBOVP(&vp1);
    LoadView(&v2);
    rastport.BitMap=&b1;
    for(a=0;a<DEPTH;a++) BltClear((unsigned char *)b1.Planes[a],RASSIZE(WIDTH,HEIGHT),0);
  }
  else {
    visible=1;
    WaitBOVP(&vp2);
    LoadView(&v1);
    rastport.BitMap=&b2;
    for(a=0;a<DEPTH;a++) BltClear((unsigned char *)b2.Planes[a],RASSIZE(WIDTH,HEIGHT),0);
  };
}
     
  

