
// Little demo of rtgmaster.library
// written by Wolfram Schenk

#include <rtgmaster/rtgmaster.h>
#include <rtgmaster/rtgsublibs.h>
#include <rtgmaster/rtgc2p.h>
#include <exec/memory.h>
#include <clib/rtgmaster_protos.h>
#include <pragmas/rtgmaster_pragmas.h>
#include <stdlib.h>
#include <stdio.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/utility.h>
#include <math.h>

struct RtgScreen *RtgScreen;
struct ScreenReq *sr;
struct RTGMasterBase *RTGMasterBase;
ULONG signal;

ULONG cmap[800];
UBYTE *Memory=NULL;
struct TagItem rtag[] = {
    smr_ChunkySupport,  (1<<9),  // only 8-Bit!
    smr_PlanarSupport, -1,
    smr_Buffers,        2,
    smr_TitleText,      (ULONG)"Small Ball Demo",
    TAG_DONE,           NULL
};

struct TagItem tacks[] = {
    rtg_Buffers,        2,
    TAG_DONE,           0
};

#define SQRT_TABSIZE 1024
int sqrt_tab[SQRT_TABSIZE*2];

void InitSqrtTab(void)
{
  int i;

  for(i = 0; i < SQRT_TABSIZE+1; i++)
    sqrt_tab[i] = 255-sqrt((DOUBLE)i/SQRT_TABSIZE)*255;
  for(; i < SQRT_TABSIZE*2; i++)
    sqrt_tab[i] = 0;
}

void DrawBall(struct RtgScreen *screen, int buffer,
              int cx, int cy, int radius)
{
  int scrwidth, scrheight;
  int x, y;
  UBYTE *line1, *line2, *bufadr;
  int maxlight;
  static struct TagItem screendata[] =
  {
    grd_Width,  0,
    grd_Height, 0,
    TAG_DONE,   0,
  };

  GetRtgScreenData(screen, screendata);
  scrwidth  = screendata[0].ti_Data;
  scrheight = screendata[1].ti_Data;
  bufadr = Memory;
  /* Grundregel Nummer 1: Immer zeilenweise! */
  for(y = 0; y <= radius; y++)
  {
    int sqr_y, sqr_radius;
    line1= &bufadr[(cy+y)*scrwidth + cx];
    line2= &bufadr[(cy-y)*scrwidth + cx];
    sqr_y = y*y;
    sqr_radius = radius*radius;
    for(x = 0; x < radius; x++)
      line1[x] = line1[-x] = line2[x] = line2[-x] = 
        sqrt_tab[(x*x + sqr_y)*SQRT_TABSIZE/sqr_radius];
  }
  CallRtgC2P(RtgScreen,GetBufAdr(screen,buffer),Memory,signal,0,0,sr->Width,sr->Height,c2p_1x1);
  Wait(1<<signal);
}

void BallDemo(struct RtgScreen *screen)
{
  int size;
  int scrwidth, scrheight;
  int buffer;
  static struct TagItem screendata[] =
  {
    grd_Width,  0,
    grd_Height, 0,
    TAG_DONE,   0,
  };

  LockRtgScreen(RtgScreen);

  GetRtgScreenData(screen, screendata);
  scrwidth  = screendata[0].ti_Data;
  scrheight = screendata[1].ti_Data;

  buffer = 1;
  for(size = 2; size*4 < scrwidth && size*4 < scrheight; size+= 4)
  {
    DrawBall(screen, buffer, scrwidth/2, scrheight/2, size);
    SwitchScreens(screen, buffer);

    buffer = 1-buffer;
  }

  UnlockRtgScreen(RtgScreen);
}

void CloseStuff(char *errorString)
{
  if(errorString)
    printf("Error: %s\n", errorString);
  if(sr)             FreeRtgScreenModeReq(sr);
  if(RtgScreen)      CloseRtgScreen(RtgScreen);
  if(RTGMasterBase)  CloseLibrary((struct Library *) RTGMasterBase);
  exit(0);
}

void main(int argc, char **argv) {
    unsigned int x, i;
    if(!(RTGMasterBase = (struct RTGMasterBase *)OpenLibrary((STRPTR)"rtgmaster.library", 1)))
      CloseStuff("Can't open rtgmaster.library!");
   
    signal=AllocSignal(-1);
    if(!(sr = RtgScreenModeReq(rtag)))
      CloseStuff("No screenmode!");
    Memory=AllocMem(sr->Width*sr->Height,MEMF_CLEAR);
    if(!(RtgScreen = OpenRtgScreen(sr, tacks)))
      CloseStuff("Can't open screen!");

    cmap[0] = 256<<16+0;
    x = 1;
    for (i = 0; i < 256; i++) {
      cmap[x++] = i*0x1000000;
      cmap[x++] = 0;
      cmap[x++] = 0;
    }
    cmap[x++]=0;

    LoadRGBRtg(RtgScreen, cmap);
    InitSqrtTab();

    BallDemo(RtgScreen);
    Delay(500);
    FreeMem(Memory,sr->Width*sr->Height);
    FreeSignal(signal);
    CloseStuff(NULL);
}
