/***********************************/
/* dual.c © 1989 by Christian Wolf */
/*    in Spandauer Str. 104L       */
/*         1 Berlin 20             */
/*     Tel.: 030/3660450           */
/* bugs fixed by Heiko Schlichting */
/***********************************/

#include <intuition/intuitionbase.h>
#include <exec/memory.h>
#include <graphics/gfxbase.h>
#ifdef LATTICE
#include <proto/all.h>
#else
#include <functions.h>
#endif

#define FRONT 1
#define BACK 0
/* Fehlermeldungen: */
#define NOTITLE              1
#define OUTOFMEM             2
#define SORRY_SCREENNOTFOUND 3
#define WRONGDEPTH           4
#define ALREADYSTARTED       5

/* Das übliche ... */
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;

/* Für den Benuzter */
struct BitMap *DualBitMap;
struct RastPort *DualRastPort;

/* für private Zwecke, am besten unberührt lassen */
static struct RasInfo *DualRasInfo;
static long planesize;
static struct BitMap *CBitMap;
static struct Screen *CScreen;
static BOOL StartFlag=FALSE;
static struct View *MyView;

/* Playfield nach vorn oder nach hinten */
void DualTo(Front)
 BOOL Front;
{
 if (Front)
     {
      CScreen->ViewPort.Modes|=DUALPF|PFBA;
      MyView->Modes|=DUALPF|PFBA;
     }
 else
     {
      CScreen->ViewPort.Modes|=DUALPF;
      CScreen->ViewPort.Modes&= (PFBA^0xffff);
     }
 /* keine Guru beim Verschieben des Screens */
 Forbid();
 MakeVPort(MyView,MyView->ViewPort);
 /* Um ein Flimmern zu verhindern */
 WaitBOVP(MyView->ViewPort);
 MrgCop(MyView);
 /* Display auf jeden Fall einschalten */
 LoadView(MyView);
 Permit();
}

/* Alles wieder freigeben */
void CloseDual()
{
 if (!StartFlag) return;
 CScreen->ViewPort.RasInfo->Next=0;
 CScreen->ViewPort.Modes^=DUALPF;
 MyView->Modes^=DUALPF;
 Forbid();
 MakeVPort(MyView,MyView->ViewPort);
 MrgCop(MyView);
 Permit();
 if (DualBitMap->Planes[0]) FreeMem(DualBitMap->Planes[0],planesize);
 if (DualBitMap->Planes[1]) FreeMem(DualBitMap->Planes[1],planesize);
 if (DualRasInfo) FreeMem(DualRasInfo,(long)sizeof(struct RasInfo));
 if (DualBitMap) FreeMem(DualBitMap,(long)sizeof(struct BitMap));
 if (DualRastPort) FreeMem(DualRastPort,(long)sizeof(struct RastPort));
 CloseLibrary((struct Library*)IntuitionBase);
 CloseLibrary((struct Library*)GfxBase);
 StartFlag=FALSE;
}

MakeDual(Depth,ScreenTitle)
 short Depth;
 char *ScreenTitle;
{
/* Argumente checken */
 if (StartFlag) return ALREADYSTARTED;
 if (Depth < 1 || Depth > 2) return(WRONGDEPTH);
 if (!ScreenTitle) return(NOTITLE);
/* Intuition- und GfxLibrary öffnen, geht NIE schief */
 IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0L);
 GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0L);
 /* Speicher für verschiedene Strukturen reservieren */
 if (!(DualRasInfo=AllocMem((long)sizeof(struct RasInfo),MEMF_PUBLIC)))
     {
      CloseDual();
      return OUTOFMEM;
     }
 if (!(DualBitMap=AllocMem((long)sizeof(struct BitMap),MEMF_PUBLIC)))
     {
      CloseDual();
      return OUTOFMEM;
     }
 if (!(DualRastPort=AllocMem((long)sizeof(struct RastPort),MEMF_PUBLIC)))
     {
      CloseDual();
      return OUTOFMEM;
     }
 /* Screen mit richtigem Namen suchen */
 CScreen=IntuitionBase->FirstScreen;
 while (CScreen)
        {
         /* Name gefunden -> DualPlayField aktivieren */
         if (!strcmp(ScreenTitle,CScreen->Title))
             {
              CBitMap=&CScreen->BitMap;
              /* BitMap kopieren */
              *DualBitMap=*CBitMap;
              /* RastPort kopieren... */
              *DualRastPort=CScreen->RastPort;
              /* ...und BitMap korrigieren */
              DualRastPort->BitMap=DualBitMap;
              MyView=GfxBase->ActiView;
              planesize=CBitMap->BytesPerRow*CBitMap->Rows;
              if (!(DualBitMap->Planes[0]=
                    AllocMem(planesize,MEMF_CHIP|MEMF_CLEAR)))
                  {
                   CloseDual();
                   return OUTOFMEM;
                  }
              if (Depth==2)
                  {
                   if (!(DualBitMap->Planes[1]=
                         AllocMem(planesize,MEMF_CHIP|MEMF_CLEAR)))
                       {
                        CloseDual();
                        return OUTOFMEM;
                       }
                  }
              else DualBitMap->Planes[1]=0;
              DualBitMap->Depth=Depth;
              DualRasInfo->BitMap=DualBitMap;
              DualRasInfo->RxOffset=0;
              DualRasInfo->RyOffset=0;
              DualRasInfo->Next=0;
              CScreen->ViewPort.RasInfo->Next=DualRasInfo;
              DualTo(FRONT);
              StartFlag=TRUE;
              return TRUE;
             }
         CScreen=CScreen->NextScreen;
        }
 return SORRY_SCREENNOTFOUND;
}

/* ein kleines Test-Programm */
void main()
{
 long  x,i;
 int Err;
 /* Dualplayfieldmode aktivieren */
 if (!(Err=MakeDual(1,"Workbench Screen")))
     {
      printf("Something has gone wrong...Error Nr. %d\n",Err);
      exit(0);
     }
 /* und ein bißchen malen */
 for (i=0;i<10;i++)
      {
      DualTo(FRONT);
      SetAPen(DualRastPort,1L);
      SetDrMd(DualRastPort,JAM1);
      for (x=0;x<639;x++)
           {
            Move(DualRastPort,x,0L);
            Draw(DualRastPort,x,255L);
           }
      DualTo(BACK);
      SetAPen(DualRastPort,0L);
      for (x=639;x>0;x--)
           {
            Move(DualRastPort,x,0L);
            Draw(DualRastPort,x,255L);
           }
      }
 /* wieder schließen */
 CloseDual();
}

