#define P96 //SuRgEoN :for compatibility - still through cgfx


#ifdef __PPC__
#define MAXWIDTH  640
#define MAXHEIGHT 480
#else
#define MAXWIDTH  512
#define MAXHEIGHT 384
#endif

#define NUMFIELDS 19
#define NUMWAVES 12

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>

#include <exec/types.h>
#include <exec/libraries.h>
#include <exec/memory.h>
#include <exec/devices.h>
#include <graphics/gfx.h>
#include <graphics/gfxbase.h>
#include <intuition/intuition.h>
#include <cybergraphics/cybergraphics.h>

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/cybergraphics.h>
#include <proto/icon.h>
#include <proto/keymap.h>
#include <devices/timer.h>
#include <proto/timer.h>

#include <workbench/startup.h>
#include <dos/dostags.h>
//#include <graphics/gfxbase.h>
//#include <cybergraphx/cybergraphics.h>
//#include <libraries/picasso96.h>
//#include <clib/picasso96_protos.h>

#ifdef __SASC
struct Library *PPCLibBase;
#include <PowerUP/PPCLib/tasks.h>
ULONG   PPCCallOS(struct Caos*);
ULONG   PPCSetTaskAttrs(void*, struct TagItem*);

#define PPCSetTaskAttrs(TaskObject, Tags)       _PPCSetTaskAttrs(PPC_BASE_NAME, TaskObject, Tags)
static __inline ULONG _PPCSetTaskAttrs(void *PPCLibBase, void*TaskObject, struct TagItem*Tags) {
        struct Caos     MyCaos;
        MyCaos.M68kCacheMode    =       IF_CACHEFLUSHALL;
        MyCaos.PPCCacheMode     =       IF_CACHEFLUSHALL;
        MyCaos.a0               =(ULONG) TaskObject;
        MyCaos.a1               =(ULONG) Tags;
        MyCaos.caos_Un.Offset   =       (-192);
        MyCaos.a6               =(ULONG) PPCLibBase;    
        return((ULONG)PPCCallOS(&MyCaos));
}
#endif


#include "TrackInfo.h"

BOOL PluginInit(int argc, char **argv);
void PluginExit(void);
void PluginLoop(void); //mainloop for viasualization effects
void ShowRequester(char *Text, char *Button);
struct MsgPort *MyCreatePort(UBYTE *name, LONG pri);
void MyDeletePort(struct MsgPort *mp);

/***************************************************************************/
/* This is the global variables section. Don't change anything here unless */
/* you know what you're doing!                                             */
/***************************************************************************/

BYTE             PluginSignal, InfoSignal, ConfigSignal;
ULONG            PluginMask,   InfoMask,   ConfigMask;
BOOL             Accepted;
struct Process   *PluginTask;
struct MsgPort   *PluginMP;
struct MsgPort   *PluginRP;
struct TrackInfo *tinfo;

#ifdef __SASC
struct Library     *TimerBase;
#else
 #ifdef __VBCC__ //SuRgEoN
struct Library      *TimerBase = NULL;
 #else
struct Device      *TimerBase;
 #endif
#endif
struct MsgPort     *TimerMP;
struct timerequest *TimerIO = NULL;
struct EClockVal   ev1;
struct EClockVal   ev2;
BYTE               TimerError = -1;
ULONG              EFreq=0;
ULONG              TimerMask;

UWORD   TrackInfoPos = 1;

UWORD   *PluginRawL;
UWORD   *PluginRawR;
WORD    *PluginSamples;
UWORD   *SpecRawL;
UWORD   *SpecRawR;
WORD *SampleRaw;

struct PluginMessage {
        struct Message   msg;
        ULONG            PluginMask;
        struct Process   *PluginTask;
        UWORD            **SpecRawL;
        UWORD            **SpecRawR;
        UWORD            Accepted;
        UWORD            reserved0;
        ULONG            InfoMask;
        struct TrackInfo **tinfo;
        ULONG            ConfigMask;
        WORD             **SampleRaw;
};

BOOL OpenTimer(void);
void CloseTimer(void);
void StartTimer(void);

/***************************************************************************/
/* This is the main part. Again, don't change anything here if you haven't */
/* got a very good reason to do so!                                        */
/***************************************************************************/

int main(int argc, char **argv) {
        struct PluginMessage *PluginMsg;
        struct PluginMessage *ReplyMsg;


        /* Allocate all user resources */
        if(PluginInit(argc, argv)) {
                /* Check if a plugin capable instance of AmigaAMP is running */
                if(PluginMP=FindPort("AmigaAMP plugin port"))   {
                        /* Allocate some sigbits for receiving signals FROM AmigaAMP */
                        PluginSignal = AllocSignal(-1);
                        ConfigSignal = AllocSignal(-1);
                        InfoSignal   = AllocSignal(-1);
                        PluginTask   = (struct Process *)FindTask(NULL);

                        if(PluginSignal != -1 && InfoSignal != -1 && PluginSignal != -1) {
                                PluginMask = 1L << PluginSignal;
                                ConfigMask = 1L << ConfigSignal;
                                InfoMask   = 1L << InfoSignal;

                                /* Allocate a message and reply port for sending messages TO AmigaAMP */
                                #if defined (__SASC) || defined (__VBCC__) //SuRgEoN
#ifdef __PPC__
                                PluginMsg=PPCAllocVec(sizeof(struct PluginMessage), MEMF_PUBLIC|MEMF_CLEAR);
#else
                                PluginMsg=AllocVec(sizeof(struct PluginMessage), MEMF_PUBLIC|MEMF_CLEAR);
#endif
                                PluginRP=(struct MsgPort*)MyCreatePort(0,0);
                                #else
                                PluginMsg=AllocVecPPC(sizeof(struct PluginMessage), MEMF_PUBLIC|MEMF_CLEAR, 0);

                                PluginRP=(struct MsgPort*)CreatePort(0,0);
                                #endif

                                /* Tell AmigaAMP all the details it needs to know */
                                PluginMsg->msg.mn_Node.ln_Type = NT_MESSAGE;
                                PluginMsg->msg.mn_Length       = sizeof(struct PluginMessage);
                                PluginMsg->msg.mn_ReplyPort    = PluginRP;
                                PluginMsg->PluginMask          = PluginMask;
                                PluginMsg->PluginTask          = PluginTask;
                                PluginMsg->SpecRawL            = &SpecRawL;
                                PluginMsg->SpecRawR            = &SpecRawR;
                                PluginMsg->InfoMask            = InfoMask;
                                PluginMsg->tinfo               = &tinfo;
                                PluginMsg->ConfigMask          = ConfigMask;
                                PluginMsg->SampleRaw           = &SampleRaw;
                                PutMsg(PluginMP, (struct Message *)PluginMsg);
                                /* Wait for a reply */
                                WaitPort(PluginRP);
                                /* Let's see if AmigaAMP accepted our registration attempt */
                                if(ReplyMsg = (struct PluginMessage *)GetMsg(PluginRP)) Accepted=ReplyMsg->Accepted;
                                else Accepted=FALSE;

                                if(Accepted) {
                                        /* If it did, start the plugin loop */
                                        printf("Init ok! - entering plugin loop\n");
                                        PluginLoop();

                                        /* Tell AmigaAMP that this plugin is going down */
                                        PluginMsg->PluginMask          = 0;
                                        PluginMsg->PluginTask          = NULL;
                                        PluginMsg->SpecRawL            = NULL;
                                        PluginMsg->SpecRawR            = NULL;
                                        PluginMsg->ConfigMask          = 0;
                                        PluginMsg->InfoMask            = 0;
                                        PluginMsg->tinfo               = NULL;
                                        PluginMsg->SampleRaw           = NULL;
                                        PutMsg(PluginMP, (struct Message *)PluginMsg);
                                        /* Wait for confirmation before going on! */
                                        WaitPort(PluginRP);
                                        GetMsg(PluginRP);
                                        /* Now that AmigaAMP knows that we're gone, we can quit */
                                }
                                else {
                                        /* If AmigaAMP didn't accept us, tell the user about it */
                                        ShowRequester("Plugin rejected by AmigaAMP!\nPerhaps there's another one running.", "Abort");
                                }

                                /* Free all resources */
                                #ifdef __SASC

                                        PPCFreeVec(PluginMsg);
                                        MyDeletePort(PluginRP);
                                #else
                                        #ifndef PPC__ //SuRgEoN
                                        FreeVec(PluginMsg);
                                        DeletePort(PluginRP);
                                        #else
                                        FreeVecPPC(PluginMsg);
                                        DeletePort(PluginRP);
                                        #endif
                                #endif
                        }
                        else {
                                ShowRequester("Signal allocation failure!", "Abort");
                        }
                        if(PluginSignal != -1) FreeSignal(PluginSignal);
                        if(ConfigSignal != -1) FreeSignal(ConfigSignal);
                        if(InfoSignal   != -1) FreeSignal(InfoSignal);
                }
                else {
                        ShowRequester("Could not find message port!\nAmigaAMP probably not running.", "Abort");
                }
        }
        else {
                ShowRequester("Plugin initialisation failed!", "Ok");
        }
        /* Free all user resources */
        PluginExit();
}

/*****************************************************************************/
/* Ok, now for the individual plugin sourcecode. Everything below should be  */
/* changed to your needs.                                                    */
/* Just like before, we start with the global variables section              */
/*****************************************************************************/

void InitWave(UBYTE WaveNum, ULONG BufNum);
void CalcWave(UBYTE WaveNum, ULONG BufNum);
void DrawWave(LONG *WaveX, LONG *WaveY, ULONG Width, ULONG Height, UBYTE WaveNum, ULONG BufNum);

void InitField(LONG *Zoom, ULONG Width, ULONG Height);
void PrepareConstants(UBYTE FieldNum);
void CalcLine(LONG *Zoom, ULONG Width, ULONG Height, UBYTE FieldNum);
void MakeCMap(void);
void Blur(UBYTE *PixelC, UBYTE *PixelD);
void ReColor(void);
void MakeTitle(void);
float rnd(float max);
float sgn(float val);

const char VersionString[]="\0$VER: Subspace68k 1.0 (14.03.01)";
const char Line1[]="Subspace";
const char Line2[]="by Thomas Wenzel";

#define PRECISION PRECISION_EXACT

struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase *GfxBase      = NULL;
struct Library *IconBase     = NULL;
struct Library *KeymapBase   = NULL;
struct Library *AslBase      = NULL;
struct Library *GadToolsBase = NULL;
struct Library *CyberGfxBase = NULL;
struct Library *P96Base = NULL;
struct Screen  *PluginScreen = NULL;
struct Window  *PluginWin    = NULL;
struct RastPort *rp;
struct ViewPort *vp;


struct EClockVal ev1;
struct EClockVal ev2;


ULONG ModeID;
ULONG WinMask;

UBYTE *PixelD;
UBYTE *PixelC;
ULONG *Colour;

UWORD *EmptyPointer;

char InfoLine[256];

LONG Zoom[MAXWIDTH*MAXHEIGHT];
LONG Zoom2[MAXWIDTH*MAXHEIGHT];
LONG WaveX[MAXWIDTH*2];
LONG WaveY[MAXWIDTH*2];
LONG WaveX2[MAXWIDTH*2];
LONG WaveY2[MAXWIDTH*2];

ULONG MidR[4], MidG[4], MidB[4];
ULONG DisplayFPS;
ULONG ShowWave;
ULONG LimitFPS;
#ifdef __PPC__
ULONG ScreenSize = 100;
#else
ULONG ScreenSize = 85;
#endif
#ifdef PPC
ULONG Width      = 320;
ULONG Height     = 240;
ULONG HalfHeight = 120;
#else
ULONG Width      = 288; //256*192    60, 256, 170
ULONG Height     = 200; //120 with ScreenSize 80!
ULONG HalfHeight = 100;
#endif
#ifndef __PPC__
ULONG Woffset     = 16;// 32 for width 256
#else
ULONG Woffset     = 0;
#endif

ULONG Cutoff     = 1;
ULONG InfoCount;
ULONG FrameCountLow;
ULONG FrameCountHigh;
ULONG FrameCountWave;
ULONG FrameCountField;
ULONG TimeWave;
ULONG DestWaveNum;
ULONG DestWaveBuffer;
float WaveMorph;
ULONG MidRdst[3], MidGdst[3], MidBdst[3];
ULONG LineToCalc;
UBYTE FieldToCalc;
UBYTE WaveToCalc, WaveToCalc0, WaveToCalc1;
UBYTE PrevField;

/****************************************************************************/
/* This function will be called once when the plugin is started. You should */
/* allocate all needed resources here. Return TRUE if all went well.        */
/****************************************************************************/

BOOL PluginInit(int argc, char **argv) {
        long i,xs,ys,xd,yd,ysp,ydp;
        float xf,yf;
        UBYTE **ttypes = 0; //VBCC
        char *str;
        struct DiskObject *IconObj = NULL; //VBCC
        struct WBStartup  *WBStart = NULL; //VBCC
        #ifdef __SASC
        void *ThisTask;
        #else
        struct TaskPPC *ThisTask;
        #endif
        WORD Length;

  char *module = "CGfx_Init: ";
  static short ColorModel[] = {PIXFMT_LUT8,-1};

#ifdef __PPC__
        struct TagItem ModeIDtags[] = {
                CYBRBIDTG_Depth, 8, CYBRBIDTG_NominalWidth, 320, CYBRBIDTG_NominalHeight, 240, TAG_DONE};
#else
        struct TagItem ModeIDtags[] = {
                CYBRBIDTG_Depth, 8, CYBRBIDTG_NominalWidth, 320, CYBRBIDTG_NominalHeight, 200, TAG_DONE};
/*
        struct TagItem ModeIDtags[] = {CYBRMREQ_MinWidth, 320,  CYBRMREQ_MinHeight, 200, CYBRMREQ_MaxHeight, 240, TAG_DONE};
*/

#endif
        AslBase=OpenLibrary("asl.library", 0);
        if(!AslBase) {
                ShowRequester("Can't open asl.library!", "Abort");
                return(FALSE);
        }

        IconBase=OpenLibrary("icon.library", 0);
        if(!IconBase) {
                ShowRequester("Can't open icon.library!", "Abort");
                return(FALSE);
        }

        KeymapBase=OpenLibrary("keymap.library", 0);
        if(!KeymapBase) {
                ShowRequester("Can't open keymap.library!", "Abort");
                return(FALSE);
        }

        IntuitionBase=(struct IntuitionBase*)OpenLibrary("intuition.library", 0);
        if(!IntuitionBase) {
                ShowRequester("Can't open intuition.library!", "Abort");
                return(FALSE);
        }

        GadToolsBase=OpenLibrary("gadtools.library", 0);
        if(!GadToolsBase) {
                ShowRequester("Can't open gadtools.library!", "Abort");
                return(FALSE);
        }

        if(!(GfxBase= (struct GfxBase*) OpenLibrary("graphics.library", 0)))
       {
                ShowRequester("Can't open graphics.library!", "Abort");
                return(FALSE);
        }

        if(GfxBase->LibNode.lib_Version < 39) {
                ShowRequester("This plugin requires AmigaOS 3.0 or greater!", "Abort");
                return(FALSE);
        }
        if (!(CyberGfxBase = (struct Library *) OpenLibrary("cybergraphics.library", 0)))
       {
                ShowRequester("This plugin requires CyberGraphX v3 or higher!", "Abort");
                return(FALSE);
        }

      P96Base = (struct Library *) OpenLibrary("Picasso96API.library",0);
        if(!P96Base) {
                ShowRequester("This plugin requires Picasso96", "Abort");
                return(FALSE);
        }

        #ifdef __SASC
                /* Increase the priority of the 68k mirror task */
                SetTaskPri(FindTask(NULL), 15);
                /* Increase our own priority (if it only would work...) */
                PPCSetTaskAttr(PPCTASKTAG_PRIORITY, 15);
        #else
                #ifdef __VBCC__
        //              SetTaskPri(FindTask(NULL), 15);
                #else
                /* Increase our own priority */
                ThisTask = FindTaskPPC(NULL);
                SetNiceValue(ThisTask, -15);
                #endif
        #endif

        WBStart=(struct WBStartup *)argv;

// if(argc==0) printf("IconName: %s\n", WBStart->sm_ArgList[0].wa_Name);

        if(argc==0) IconObj=GetDiskObject(WBStart->sm_ArgList[0].wa_Name);
        else        IconObj=GetDiskObject(argv[0]);

        LimitFPS = 999;

        if(IconObj) {
                if(str=FindToolType(IconObj->do_ToolTypes,"MAXFPS"))
                {
                        LimitFPS = atol(str);
                }

                if(str=FindToolType(IconObj->do_ToolTypes,"RESOLUTION"))
                {
                        if(stricmp(str,"high") == 0) {
                                Width      = 640;
                                Height     = 480;
                                ScreenSize = 66;
                        }
                        else {
#ifdef __PPC__
                                Width      = 320;
                                Height     = 240;
                                ScreenSize = 100;
#else
                                Width      = 288;
                                Height     = 200;
                                ScreenSize = 85;
#endif

                        }
                }

                if(str=FindToolType(IconObj->do_ToolTypes,"SCREENSIZE"))
                {
                        ScreenSize = atol(str);
                }
        FreeDiskObject(IconObj);
        }

        if(ttypes=(UBYTE**)ArgArrayInit(argc, argv)) {
                str=(char*)ArgString(ttypes, "MAXFPS", "0");
                LimitFPS = atol(str);

                str=(char*)ArgString(ttypes, "RESOLUTION", "low");
                if(stricmp(str,"high") == 0) {
                        Width      = 640;
                        Height     = 480;
                        ScreenSize = 66;
                        ShowWave   = 1;
                }
                else {
#ifdef __PPC__
                        Width      = 320;
                        Height     = 240;
                        ScreenSize = 100;
#else
                        Width      = 288; //240
                        Height     = 200; //190
                        ScreenSize = 85;//60
#endif
                        ShowWave   = 0;
                }

                if(str=(char*)ArgString(ttypes, "SCREENSIZE", NULL)) {
                        ScreenSize = atol(str);
                }

                ArgArrayDone();
        }
#ifndef PPC
        if(LimitFPS == 0)  LimitFPS = 999;
        if(LimitFPS > 999) LimitFPS = 999;
#else
	LimitFPS = 10;
#endif
        if(ScreenSize <  25) ScreenSize =  25;
        if(ScreenSize > 100) ScreenSize = 100;

        Cutoff = Height * (100-ScreenSize) / 200;
        if(Cutoff <   1) Cutoff =   1;
        if(Cutoff > 200) Cutoff = 200;

        ModeIDtags[1].ti_Data = Width;
        ModeIDtags[2].ti_Data = Height;

        HalfHeight = Height/2;

        #if defined (__SASC) || defined (__VBCC__)
                #ifdef __PPC__
                PixelD       = PPCAllocVec(Width*Height, MEMF_PUBLIC|MEMF_CLEAR);
                PixelC       = PPCAllocVec(Width*Height, MEMF_PUBLIC|MEMF_CLEAR);
                Colour       = PPCAllocVec(770*4,        MEMF_PUBLIC|MEMF_CLEAR);
                EmptyPointer = PPCAllocVec(512,          MEMF_CHIP|MEMF_CLEAR);
                #else //68k
                PixelD       = AllocVec(Width*Height, MEMF_PUBLIC|MEMF_CLEAR);
                PixelC       = AllocVec(Width*Height, MEMF_PUBLIC|MEMF_CLEAR);
                Colour       = AllocVec(770*4,        MEMF_PUBLIC|MEMF_CLEAR);
                EmptyPointer = AllocVec(512,          MEMF_CHIP|MEMF_CLEAR);
                #endif
        #else
                PixelD       = AllocVecPPC(Width*Height, MEMF_PUBLIC|MEMF_CLEAR, 0);
                PixelC       = AllocVecPPC(Width*Height, MEMF_PUBLIC|MEMF_CLEAR, 0);
                Colour       = AllocVecPPC(770*4,        MEMF_PUBLIC|MEMF_CLEAR, 0);
                EmptyPointer = AllocVecPPC(512,          MEMF_CHIP|MEMF_CLEAR,   0);
        #endif

        OpenTimer();

        if(PixelD==NULL || PixelC==NULL) {
                ShowRequester("Out of memory for graphics buffers!", "Abort");
                return(FALSE);
        }

        srand(time(NULL));

        MidR[0] = 230;
        MidG[0] = 230;
        MidB[0] = 230;

        MidR[1] = 86;
        MidG[1] = 86;
        MidB[1] = 170;

        MidR[2] = 25;
        MidG[2] = 25;
        MidB[2] = 100;

        MidR[3] = 0;
        MidG[3] = 0;
        MidB[3] = 0;

        MidRdst[0] = (UBYTE)(rand()>>25) + 127;
        MidGdst[0] = (UBYTE)(rand()>>25) + 127;
        MidBdst[0] = (UBYTE)(rand()>>25) + 127;

        MidRdst[1] = (UBYTE)(rand()>>25) + 96;
        MidGdst[1] = (UBYTE)(rand()>>25) + 96;
        MidBdst[1] = (UBYTE)(rand()>>25) + 96;

        MidRdst[2] = (UBYTE)(rand()>>25) + 64;
        MidGdst[2] = (UBYTE)(rand()>>25) + 64;
        MidBdst[2] = (UBYTE)(rand()>>25) + 64;

        DisplayFPS      = 0;
        InfoCount       = 0;
        FrameCountLow   = 0;
        FrameCountHigh  = 0;
        FrameCountWave  = 0;
        FrameCountField = 0;
        TimeWave        = 0;
        DestWaveNum     = 1;
        DestWaveBuffer  = 1;
        WaveMorph       = 0.0;
        LineToCalc      = 0;
        WaveToCalc      = 0;
        WaveToCalc0     = 0;

        FieldToCalc     = (UBYTE)(rand() % NUMFIELDS);
        WaveToCalc1     = (UBYTE)(rand() % NUMWAVES);

//      FieldToCalc   = 0; //10=endblur;16=radial;2=tunnel
//      WaveToCalc1   = 1;
//1=tunnel;2=lines;3=radar;4=flower;5=solsweep;6=xx;7=chaoticlines;8=circwaves;9=occludinglines;10=quad;11=;
//      FieldToCalc   = NUMFIELDS-1;
//      WaveToCalc1   = NUMWAVES-1;


        PrepareConstants(FieldToCalc);

        MakeCMap();

#ifdef P96
/*
  if (!(ModeID = CModeRequestTagList(NULL, ModeIDtags)))
  {
    ShowRequester("Can't open the screenmode requester", module);
    return(FALSE);
  }

  if (ModeID == INVALID_ID)
  {
    ShowRequester("Screenmode requester aborted",module);
    return(FALSE);
  }
*/
//      ModeID=CModeRequestTagList(NULL, ModeIDtags);
        ModeID=p96RequestModeIDTagList(ModeIDtags);
#else
        ModeID=BestCModeIDTagList(NULL, ModeIDtags);
#endif
        if(ModeID == INVALID_ID) {
                ShowRequester("Could not find suitable screen mode!", "Abort");
                return(FALSE);
        }
        

        PluginScreen=OpenScreenTags(NULL, SA_DisplayID, ModeID, SA_Depth, 8, SA_Width, Width, SA_Height, Height, SA_SharePens, TRUE, SA_ShowTitle, FALSE, SA_Quiet, TRUE, TAG_DONE);
        if(PluginScreen == NULL) {
                ShowRequester("Could not open screen!", "Abort");
                return(FALSE);
        }
        rp = &PluginScreen->RastPort;
        vp = &PluginScreen->ViewPort;

        LoadRGB32(vp, Colour);

        PluginWin=OpenWindowTags(NULL, WA_CustomScreen, (ULONG)PluginScreen,
                                       WA_Left,         0,
                                       WA_Top,          0,
                                       WA_Width,        Width,
                                       WA_Height,       Height,
                                       WA_SizeGadget,   FALSE,
                                       WA_DragBar,      FALSE,
                                       WA_DepthGadget,  FALSE,
                                       WA_CloseGadget,  FALSE,
                                       WA_Backdrop,     TRUE,
                                       WA_Borderless,   TRUE,
                                       WA_Activate,     TRUE,
                                       WA_AutoAdjust,   TRUE,  // Just to be sure :-)
                                       WA_IDCMP,        IDCMP_RAWKEY | IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW,
                                       TAG_DONE);
        if(PluginWin == NULL) {
                ShowRequester("Could not open window!", "Abort");
                return(FALSE);
        }

        SetPointer(PluginWin, EmptyPointer, 1, 1, 0, 0);
        SetAPen(rp, 1);
        RectFill(rp, 0, 0, (Width-1), (Height-1));
        SetAPen(rp, 255);

        WinMask = 1L << PluginWin->UserPort->mp_SigBit;

        InitField(Zoom, Width, Height);
        MakeTitle();

        return(TRUE);
}

/******************************************************************************/
/* This function will be called when the plugin is shut down. You should free */
/* all previously allocated resources here.                                   */
/******************************************************************************/

void PluginExit(void) {
        long i;

        if(PluginWin)    CloseWindow(PluginWin);
        if(PluginScreen) CloseScreen(PluginScreen);
        #ifdef __SASC
                if(PixelD)       PPCFreeVec(PixelD);
                if(PixelC)       PPCFreeVec(PixelC);
                if(Colour)       PPCFreeVec(Colour);
                if(EmptyPointer) PPCFreeVec(EmptyPointer);
        #else
         #ifdef __PPC__ 
                if(PixelD)       FreeVecPPC(PixelD);
                if(PixelC)       FreeVecPPC(PixelC);
                if(Colour)       FreeVecPPC(Colour);
                if(EmptyPointer) FreeVecPPC(EmptyPointer);
         #else
                if(PixelD)       FreeVec(PixelD);
                if(PixelC)       FreeVec(PixelC);
                if(Colour)       FreeVec(Colour);
                if(EmptyPointer) FreeVec(EmptyPointer);
         #endif
        #endif

        CloseTimer();
        if(CyberGfxBase)  CloseLibrary(CyberGfxBase);
        if(P96Base)	CloseLibrary(P96Base);
//      if(GfxBase)       CloseLibrary(GfxBase);
        if(AslBase)       CloseLibrary(AslBase);
        if(IconBase)      CloseLibrary(IconBase);
        if(KeymapBase)    CloseLibrary(KeymapBase);
        if(GadToolsBase)  CloseLibrary(GadToolsBase);
//      if(IntuitionBase) CloseLibrary(IntuitionBase);
}

/*******************************************************************************/
/* This is the main Plugin Loop. It will receive a signal matching PluginMask  */
/* each time new spectral data is ready. The data is stored in two arrays,     */
/* UWORD Spec[512] in structures DataL and DataR. The scale is logarithmic,    */
/* 0 means below -96dB, 65535 means 0dB.                                       */
/* No matter how long it takes until your plugin actually processes the data,  */
/* the memory referenced by the array pointers always remains valid!           */
/*                                                                             */
/* Your plugin loop MUST quit when it receives SIGBREAKF_CTRL_C. If you've     */
/* opened a window you should react to the close gadget as well. For full      */
/* screen plugins I strongly recommend checking the ESC key.                   */
/*******************************************************************************/

void PluginLoop(void) {
        struct TextExtent te;
        ULONG *PixelL = 0;
        UBYTE *ActPixel;
        ULONG Signals = 0;
        LONG i,j,k;
        LONG l,r;
        LONG x,y;
        UBYTE v;
        UWORD w;
        UBYTE ColorMode;

        ULONG   hi,lo,itime,eclock;
        char FPStext[64];

        UBYTE Vanilla;
        struct InputEvent ie;
        WORD    RawLen;
        printf("entering main loop\n");
        Wait(SIGBREAKF_CTRL_C | PluginMask);

        /* Make a backup of the data pointers */
        PluginRawL    = SpecRawL;
        PluginRawR    = SpecRawR;
        PluginSamples = SampleRaw;
        WritePixelArray(PixelC, 0, 0, Width, rp, Woffset, 0, Width, Height, RECTFMT_LUT8);
        Delay(100);

        StartTimer();

        InitWave(WaveToCalc0, 0);
        InitWave(WaveToCalc1, 1);

        for(;;) {
                /* Wait until there's something to do */

                Signals=Wait(SIGBREAKF_CTRL_C | PluginMask | ConfigMask | InfoMask | WinMask | TimerMask);
                if(Signals & TimerMask) {
                        WaitIO((struct IORequest *) TimerIO);
                }

                /* Break received -> quit at once! */
                if(Signals & SIGBREAKF_CTRL_C) break;

                /* Window close gadget hit -> quit as well! */
                if(Signals & WinMask) {
                        struct IntuiMessage *imsg;
                        BOOL done=0;

                        while(imsg=(struct IntuiMessage *)GetMsg(PluginWin->UserPort)) {
                                if(imsg->Class == IDCMP_RAWKEY) {
                                        ie.ie_Class        = IECLASS_RAWKEY;
                                        ie.ie_SubClass     = 0;
                                        ie.ie_Code         = imsg->Code;
                                        ie.ie_Qualifier    = 0;
                                        ie.ie_EventAddress = imsg->IAddress;
                                        RawLen = MapRawKey(&ie, &Vanilla, 1, 0);

                                        switch(imsg->Code) {
                                                case 0x45: done=1; break;
                                        }

                                        if(RawLen==1) {
                                                switch(Vanilla) {
                                                        case 'f': DisplayFPS = 1-DisplayFPS; break;
                                                        case 'w': ShowWave   = 1-ShowWave;   break;
                                                        case 'i': InfoCount  = 0;            break;
//                                              case '+': Cutoff--;                  break;
//                                              case '-': Cutoff++;                  break;
                                                }
                                                if(Cutoff < 1) Cutoff =   1;
                                                if(Cutoff > HalfHeight-10) Cutoff = HalfHeight-10;
                                                for(i=0; i<Width*Cutoff; i++) {
                                                        PixelC[i]=PixelD[i]=0;
                                                }
                                                for(i=Width*(Height-Cutoff); i<Width*Height; i++) {
                                                        PixelC[i]=PixelD[i]=0;
                                                }
                                        }
                                }
                                ReplyMsg(imsg);
                        }
                        if(done) break;
                }

                if(Signals & TimerMask) {
                        StartTimer();
//printf("timer started\n");
      Blur(PixelC, PixelD);

                        FrameCountLow++;
                        if(FrameCountLow > 4) {
                                FrameCountLow = 0;
                                eclock=ReadEClock(&ev2);
                                hi = ev2.ev_hi - ev1.ev_hi;
                                lo = ev2.ev_lo - ev1.ev_lo;
                                itime = hi*eclock+lo;

                                if(itime==0) itime=1;

                                ev1.ev_hi = ev2.ev_hi;
                                ev1.ev_lo = ev2.ev_lo;
                                ReColor();
                        }

                        FrameCountHigh++;
                if(FrameCountHigh > 600) {
                                FrameCountHigh = 0;
#ifndef __VBCC__
                                ColorMode = (UBYTE)(rand()>>24) % 10;

#else
/*
if(ColorMode==0)
{
        MidR[0] = 255;
        MidG[0] = 220;
        MidB[0] = 200;

        MidR[1] = 170;
        MidG[1] = 96;
        MidB[1] = 170;

        MidR[2] = 10;
        MidG[2] = 100;
        MidB[2] = 52;

ColorMode=1;
}
*/
/*
if(ColorMode==0)
{
        MidR[0] = 255;
        MidG[0] = 200;
        MidB[0] = 255;

        MidR[1] = 96;
        MidG[1] = 76;
        MidB[1] = 178;

        MidR[2] = 100;
        MidG[2] = 55;
        MidB[2] = 65;

ColorMode=1;
}
*/

if(ColorMode == 0)
{
//blue
        MidR[0] = 230;
        MidG[0] = 230;
        MidB[0] = 230;

        MidR[1] = 86;
        MidG[1] = 86;
        MidB[1] = 170;

        MidR[2] = 25;
        MidG[2] = 25;
        MidB[2] = 100;

ColorMode = 1;
}
else
{
//fire
        MidR[0] = 255;
        MidG[0] = 255;
        MidB[0] = 100;

        MidR[1] = 200;
        MidG[1] = 120;
        MidB[1] = 10;

        MidR[2] = 100;
        MidG[2] = 25;
        MidB[2] = 25;

        MidR[3] = 0;
        MidG[3] = 0;
        MidB[3] = 0;

ColorMode = 0;
}

#endif
                        printf("ColorMode: %d\n", ColorMode);
#ifndef __VBCC__
                                switch(ColorMode) {
                                        case 0:
                                        case 1:
                                                MidRdst[0] = (UBYTE)(rand()>>25) + 127;
                                                MidGdst[0] = (UBYTE)(rand()>>25) + 127;
                                                MidBdst[0] = (UBYTE)(rand()>>25) + 127;

                                                MidRdst[1] = (UBYTE)(rand()>>24) + 0;
                                                MidGdst[1] = (UBYTE)(rand()>>24) + 0;
                                                MidBdst[1] = (UBYTE)(rand()>>24) + 0;

                                                MidRdst[2] = (UBYTE)(rand()>>24) + 0;
                                                MidGdst[2] = (UBYTE)(rand()>>24) + 0;
                                                MidBdst[2] = (UBYTE)(rand()>>24) + 0;
                                        break;

                                        case 2:
                                                MidRdst[0] = (UBYTE)(rand()>>24) + 0;
                                                MidGdst[0] = (UBYTE)(rand()>>24) + 0;
                                                MidBdst[0] = (UBYTE)(rand()>>24) + 0;

                                                MidRdst[1] = (UBYTE)(rand()>>24) + 0;
                                                MidGdst[1] = (UBYTE)(rand()>>24) + 0;
                                                MidBdst[1] = (UBYTE)(rand()>>24) + 0;

                                                MidRdst[2] = (UBYTE)(rand()>>24) + 0;
                                                MidGdst[2] = (UBYTE)(rand()>>24) + 0;
                                                MidBdst[2] = (UBYTE)(rand()>>24) + 0;
                                        break;

                                        case 3:
                                                MidRdst[0] = (UBYTE)(rand()>>25) + 0;
                                                MidGdst[0] = (UBYTE)(rand()>>25) + 0;
                                                MidBdst[0] = (UBYTE)(rand()>>25) + 0;

                                                MidRdst[1] = (UBYTE)(rand()>>24) + 0;
                                                MidGdst[1] = (UBYTE)(rand()>>24) + 0;
                                                MidBdst[1] = (UBYTE)(rand()>>24) + 0;

                                                MidRdst[2] = (UBYTE)(rand()>>24) + 0;
                                                MidGdst[2] = (UBYTE)(rand()>>24) + 0;
                                                MidBdst[2] = (UBYTE)(rand()>>24) + 0;
                                        break;

                                        default:
                                                MidRdst[0] = (UBYTE)(rand()>>25) + 127;
                                                MidGdst[0] = (UBYTE)(rand()>>25) + 127;
                                                MidBdst[0] = (UBYTE)(rand()>>25) + 127;

                                                MidRdst[1] = (UBYTE)(rand()>>25) + 64;
                                                MidGdst[1] = (UBYTE)(rand()>>25) + 64;
                                                MidBdst[1] = (UBYTE)(rand()>>25) + 64;

                                                MidRdst[2] = (UBYTE)(rand()>>25) + 32;
                                                MidGdst[2] = (UBYTE)(rand()>>25) + 32;
                                                MidBdst[2] = (UBYTE)(rand()>>25) + 32;
                                        break;
                                }
#endif
                        }

                        CalcLine(Zoom2, Width, Height, FieldToCalc);
                        LineToCalc++;
                        if(LineToCalc > Height-1) LineToCalc = Height-1;
                        FrameCountField++;
                        
                        if(FrameCountField > 500) {

                        printf("FCF 500\n");
                                FrameCountField=0;

                                LineToCalc = 1;
                                PrevField = FieldToCalc;

#ifdef __VBCC__
                                do {
                        FieldToCalc=(UBYTE)(rand() % NUMFIELDS);
                                } while (FieldToCalc == PrevField);

/*                              if(FieldToCalc == 0)
                                FieldToCalc = 1;
                                else if(FieldToCalc == 1)
                                FieldToCalc = 2;
                                else if(FieldToCalc == 2)
                                FieldToCalc = 3;
                                else if(FieldToCalc == 3)
                                FieldToCalc = 4;
                                else if(FieldToCalc == 4)
                                FieldToCalc = 6;
                                else if(FieldToCalc == 6)
                                FieldToCalc = 7;
                                else if(FieldToCalc == 7)
                                FieldToCalc = 9;
                                else if(FieldToCalc == 9)
                                FieldToCalc = 10;
                                else if(FieldToCalc == 10)
                                FieldToCalc = 13;
                                else if(FieldToCalc == 13)
                                FieldToCalc = 14;
                                else if(FieldToCalc == 14)
                                FieldToCalc = 15;
                                else if(FieldToCalc == 15)
                                FieldToCalc = 16;
                                else if(FieldToCalc == 16)
                                FieldToCalc = 18;
                                else
                                FieldToCalc = 0;
*/
#endif

#ifndef __VBCC__
                                do {
                        FieldToCalc=(UBYTE)(rand()>>24) % NUMFIELDS;
                                } while (FieldToCalc == PrevField);
#endif

                                for(j=0; j<Width*Height; j++)
                                {
                                        Zoom[j]=Zoom2[j];
                                }
                                printf("preparing field %d\n", FieldToCalc);
                                PrepareConstants(FieldToCalc);

                        }

                        for(i=Width*Cutoff; i<Width*(Height-Cutoff); i++) {
                                PixelC[i]=PixelD[Zoom[i]];
                        }


                        /* Make a backup of the data pointers */
                        PluginRawL    = SpecRawL;
                        PluginRawR    = SpecRawR;
                        PluginSamples = SampleRaw;

                        InfoCount++;
                        if(InfoCount < 75) MakeTitle();
                        else InfoCount=75;

                        TimeWave++;
                        FrameCountWave++;
                        CalcWave(WaveToCalc0, 0);
                        DrawWave(WaveX,  WaveY,  Width, Height, WaveToCalc0, 0);
                        CalcWave(WaveToCalc1, 1);
                        DrawWave(WaveX2, WaveY2, Width, Height, WaveToCalc1, 1);
                        if(FrameCountWave > 200) {

                                if(DestWaveBuffer == 1) WaveMorph += 0.015; //was 0.005
                                else                    WaveMorph -= 0.015; //was 0.005
                        }
                        if (WaveMorph > 1.0) WaveMorph = 1.0;
                        if (WaveMorph < 0.0) WaveMorph = 0.0;

                        if(FrameCountWave > 400) {
                        printf("FCW 400\n");
                        FrameCountWave = 0;
                        DestWaveBuffer = 1 - DestWaveBuffer;
#ifdef __VBCC__
                                do {
                                        WaveToCalc = (UBYTE)(rand() % NUMWAVES);
                                } while (WaveToCalc == WaveToCalc0 || WaveToCalc == WaveToCalc1 || WaveToCalc == 10 || WaveToCalc == 8 || WaveToCalc == 6);

                                if(DestWaveBuffer) {
                                        WaveToCalc1 = WaveToCalc;
                                        InitWave(WaveToCalc1, 1);
                                }
                                else {
                                        WaveToCalc0 = WaveToCalc;
                                        InitWave(WaveToCalc0, 0);
                                }

/*
if (WaveToCalc1 == 1)
WaveToCalc1 = 5;
else if (WaveToCalc1 == 2)
WaveToCalc1 = 7;
else if (WaveToCalc1 == 3)
WaveToCalc1 = 11;
else if (WaveToCalc1 == 4)
WaveToCalc1 = 1;
else if (WaveToCalc1 == 5)
WaveToCalc1 = 2;
else if (WaveToCalc1 == 7)
WaveToCalc1 = 3;
else
WaveToCalc1 = 4;

WaveToCalc0 = 0;

        InitWave(WaveToCalc1, 1);
        printf("initializing wave %d\n",WaveToCalc1);
        InitWave(WaveToCalc0, 0);
*/
#endif

#ifndef __VBCC__
                                do {
                                        WaveToCalc = (UBYTE)(rand()>>24) % NUMWAVES;
                                        WaveToCalc = NUMWAVES-1;
                                } while (WaveToCalc == WaveToCalc0 || WaveToCalc == WaveToCalc1);

                                if(DestWaveBuffer) {
                                        WaveToCalc1 = WaveToCalc;
                                        InitWave(WaveToCalc1, 1);
                                }
                                else {
                                        WaveToCalc0 = WaveToCalc;
                                        InitWave(WaveToCalc0, 0);
                                }
#endif
                        }

                        for(i=0; i<Width*2; i++) {
                                float xf,yf;
                                ULONG x,y;
                                xf = (float)WaveX[i]*(1.0-WaveMorph) + (float)WaveX2[i]*(WaveMorph);
                                yf = (float)WaveY[i]*(1.0-WaveMorph) + (float)WaveY2[i]*(WaveMorph);
                                x  = (ULONG)xf + Width/2;
                                y  = (ULONG)yf + Height/2;
                                if(x < Width-1) {
                                        if(y < Height-1) {
                                                if(x > 0) {
                                                        if(y > 0) {
                                                                ActPixel = PixelC + y * Width + x;
                                                                *ActPixel=255;
                                                        }
                                                }
                                        }
                                }
                        }

                        SetAPen(rp, 0);
/*                      if(ShowWave) WritePixelArray(PixelC, 1, Cutoff+1, Width, rp, 0, Cutoff+1, Width-2, Height-2*Cutoff-2, RECTFMT_LUT8);
                        else         WritePixelArray(PixelD, 1, Cutoff+1, Width, rp, 0, Cutoff+1, Width-2, Height-2*Cutoff-2, RECTFMT_LUT8);
                        RectFill(rp, 0, 0, Width, Cutoff);
                        RectFill(rp, 0, Height-Cutoff-1, Width, Height-1);
*/
                        if(ShowWave) WritePixelArray(PixelC, 1, Cutoff+1, Width, rp, Woffset, Cutoff+1, Width-2, Height-2*Cutoff-2, RECTFMT_LUT8);
                        else         WritePixelArray(PixelD, 1, Cutoff+1, Width, rp, Woffset, Cutoff+1, Width-2, Height-2*Cutoff-2, RECTFMT_LUT8);
                        RectFill(rp, 0, 0, Width, Cutoff);
                        RectFill(rp, 0, Height-Cutoff-1, Width, Height-1);




                        if(DisplayFPS)
                        {
                                Move(rp, 0, 15);
                                SetABPenDrMd(rp, 255, 0, JAM2);
                                sprintf(FPStext, "%3ld fps       ", 5*eclock/itime);
                                Text(rp, FPStext, 7);
                        }
                }
        }
}



void Blur(UBYTE *PixelC, UBYTE *PixelD) {
  UBYTE *ActPixel;
  UBYTE *DstPixel;
  UBYTE *AbovePixel, *BelowPixel;
  UBYTE Left, Act, Right;
  WORD w;
  ULONG i;

        PixelC += Width*Cutoff;
        PixelD += Width*Cutoff;

  ActPixel   = PixelC+Width+1;
  AbovePixel = ActPixel-Width;
  BelowPixel = ActPixel+Width;
  DstPixel   = PixelD+Width+1;

  Left  = 0;
  Act   = 0;
  Right = 0;

        for(i=Width*(Cutoff+1); i<(Width*(Height-Cutoff-2)-2); i++) {
    Right = *(ActPixel+1);

    w = (Right + Act + Left + *AbovePixel + *BelowPixel) * 3 / 16;
                if(w<0) w=0;
    *DstPixel++ = w;

    ActPixel++;
    AbovePixel++;
    BelowPixel++;

    Left = Act;
    Act = Right;
  }
}

void ShowRequester(char *Text, char *Button) {
        struct EasyStruct Req;
        Req.es_StructSize   = sizeof(struct EasyStruct);
        Req.es_Flags        = 0;
  Req.es_Title        = "AmigaAMP Plugin";
  Req.es_TextFormat   = (UBYTE*)Text;
  Req.es_GadgetFormat = (UBYTE*)Button;
        EasyRequestArgs(NULL, &Req, NULL, NULL);
}

BOOL OpenTimer(void) {
        struct EClockVal ev = {0,0};

        if(TimerMP=(struct MsgPort*)CreatePort(0,0)) {
                if(TimerIO=(struct timerequest *)CreateIORequest(TimerMP, sizeof(struct timerequest))) {
                        TimerError=OpenDevice("timer.device", UNIT_ECLOCK, (struct IORequest *)TimerIO, 0);
                        if(TimerError==0) {

                                TimerBase = (struct Library*) &TimerIO->tr_node.io_Device->dd_Library;
                                EFreq=ReadEClock(&ev);

                                TimerMask = 1L << TimerMP->mp_SigBit;

                                return(TRUE);
                        }
                }
        }
        return(FALSE);
}

void CloseTimer(void) {
        if(!TimerError)   CloseDevice((struct IORequest *)TimerIO);
        if(TimerIO)       DeleteIORequest(TimerIO);
        if(TimerMP)       DeletePort(TimerMP);
}

void StartTimer(void) {
        TimerIO->tr_node.io_Command = TR_ADDREQUEST;
        TimerIO->tr_node.io_Flags   = 0;
        TimerIO->tr_time.tv_secs    = 0;
        TimerIO->tr_time.tv_micro   = EFreq/LimitFPS;
        SendIO((struct IORequest *)TimerIO);
}

struct MsgPort *MyCreatePort(UBYTE *name, LONG pri) {
        int sigBit;
        struct MsgPort *mp;

        if((sigBit = AllocSignal(-1L)) == -1)   return(NULL);

        mp = (struct MsgPort*) AllocVec(sizeof(struct MsgPort), MEMF_PUBLIC|MEMF_CLEAR);

        if(!mp) {
                FreeSignal(sigBit);
                return(NULL);
        }

        mp->mp_Node.ln_Name = name;
        mp->mp_Node.ln_Pri  = pri;
        mp->mp_Node.ln_Type = NT_MSGPORT;
        mp->mp_Flags        = PA_SIGNAL;
        mp->mp_SigBit       = sigBit;
        mp->mp_SigTask      = FindTask(NULL);
        if(name) AddPort(mp);
        #if defined (__SASC) || defined (__VBCC__)
                else NewList(&(mp->mp_MsgList));
        #else
                else NewListPPC(&(mp->mp_MsgList));
        #endif

        return(mp);
}

void MyDeletePort(struct MsgPort *mp) {
        if(mp->mp_Node.ln_Name) RemPort(mp);
        mp->mp_SigTask         = (struct Task *) -1;
        mp->mp_MsgList.lh_Head = (struct Node *) -1;
        FreeSignal(mp->mp_SigBit);
        FreeVec(mp); mp=NULL;
}

void InitField(LONG *Zoom, ULONG Width, ULONG Height) {
        LONG i,xs,ys,xd,yd;

        float scale,greater;
        float xsf,ysf,xdf,ydf;
        float rsf,tsf,rdf,tdf;
        float wf,hf;

        wf=(float)Width;
        hf=(float)Height;

        greater=1.0;
        if(wf > greater) greater = wf;
        if(hf > greater) greater = hf;

        scale = 1.0 / (greater/2.0);

        for(yd=0; yd<(Height); yd++) {
                for(xd=0; xd<(Width); xd++) {
                        xdf = (xd - wf/2.0) * scale;
                        ydf = (yd - hf/2.0) * scale;

                        xsf = xdf - xdf * 0.075;
                        ysf = ydf - ydf * 0.075;

                        xs = xsf/scale + wf/2.0;
                        ys = ysf/scale + hf/2.0;

                        if(xs < Width/2)  xs++;
                        if(ys < Height/2) ys++;

                        if(xs < 0)      xs = 0;
                        if(xs > Width)  xs = Width;
                        if(ys < 0)      ys = 0;
                        if(ys > Height) ys = Height;

                        Zoom[Width * yd + xd] = Width * ys + xs;
                }
        }
}


void MakeCMap(void) {
        int j,i,c;
        float r,g,b;
        float rs,gs,bs;

        r=255; g=255; b=255;

        c=255;

        Colour[0]=256L<<16+0;

        for(j=0; j<4; j++) {
                rs = (r - (float)MidR[j]) / 64.0;
                gs = (g - (float)MidG[j]) / 64.0;
                bs = (b - (float)MidB[j]) / 64.0;
                for(i=0; i<64; i++) {
                        Colour[1+3*c+0] = (ULONG)r << 24;
                        Colour[1+3*c+1] = (ULONG)g << 24;
                        Colour[1+3*c+2] = (ULONG)b << 24;
                        r -= rs;
                        g -= gs;
                        b -= bs;
                        c--;
                }
        }

}

void MakeTitle(void) {
        long x,y,i,p,s,v,xs,ys;
        UWORD Blt1[27] = {
                0x7008,0x0000,0x0000,0x8808,0x0000,0x0000,0x822B,0x1963,
                0x8E38,0x722C,0xA590,0x5144,0x0A28,0x9913,0xD07C,0x8A28,
                0x8514,0x5040,0x8A68,0xA594,0xD144,0x71AF,0x1963,0x4E38,
                0x0000,0x0100,0x0000
        }; // W=46, H=9
        UWORD Blt2[54] = {
                0x8001,0xF400,0x0000,0x0101,0x0000,0x0080,0x8000,0x4400,
                0x0000,0x0111,0x0000,0x0080,0xB220,0x458E,0x7638,0xC111,
                0x3967,0x9C80,0xCA20,0x4651,0x4905,0x2092,0x4590,0xA280,
                0x8940,0x4451,0x493C,0xC0AA,0x7D11,0x3E80,0x8940,0x4451,
                0x4944,0x20AA,0x4112,0x2080,0x8880,0x4451,0x494D,0x2044,
                0x4514,0x2280,0xF080,0x444E,0x4934,0xC044,0x3917,0x9C80,
                0x0100,0x0000,0x0000,0x0000,0x0000,0x0000
        }; // W=89, H=9

        xs = (Width-46)/2;
        ys = Height/2-30-9;
        s=0;
        for(y=0; y<9; y++) {
                x=0;
                for(i=0; i<3; i++) {
                        for(p=0; p<16; p++) {
                                x++;
                                v = Blt1[s] & (1<<(15-p));
                                if(v) PixelC[(ys+y)*Width+xs+x] = 255;
                        }
                        s++;
                }
        }
        xs = (Width-89)/2;
        ys = Height/2+30;
        s=0;
        for(y=0; y<9; y++) {
                x=0;
                for(i=0; i<6; i++) {
                        for(p=0; p<16; p++) {
                                x++;
                                v = Blt2[s] & (1<<(15-p));
                                if(v) PixelC[(ys+y)*Width+xs+x] = 255;
                        }
                        s++;
                }
        }
}


void ReColor(void) {
#ifndef __VBCC__

        int i;
        for(i=0; i<3; i++) {
                if(MidR[i] > MidRdst[i]) MidR[i] --;
                if(MidG[i] > MidGdst[i]) MidG[i] --;
                if(MidB[i] > MidBdst[i]) MidB[i] --;
                if(MidR[i] < MidRdst[i]) MidR[i] ++;
                if(MidG[i] < MidGdst[i]) MidG[i] ++;
                if(MidB[i] < MidBdst[i]) MidB[i] ++;

        }
#endif
        MakeCMap();
        LoadRGB32(&PluginScreen->ViewPort, Colour);
}

float rnd(float max) {
        ULONG r;
        ULONG m;

        m = (ULONG)(max * 10000.0);
#ifndef __VBCC__
        r=(rand()>>8) % m;
#else
        r=(rand() % m);
#endif
        return (float)r/10000.0;
}

float sgn(float val) {
        if(val > 0.0) return  1.0;
        if(val < 0.0) return -1.0;
        return 0.0;
}

float trnc(float value) {
        return ceil(value);
}

#ifdef __SASC
void SetPriority(void) {
        struct TagItem MyTags[2];
        if(PPCLibBase=OpenLibrary("ppc.library",0)) {
                MyTags[0].ti_Tag  = PPCTASKTAG_PRIORITY;
                MyTags[0].ti_Data = 15;
                MyTags[1].ti_Tag         = TAG_END;
                CloseLibrary(PPCLibBase);
        }
}
#endif






