/*************************************************************************
 ***                        MIEXAMPLE MODULE                           ***
 *** Date begun: 25/4/89.                                              ***
 *** Last modified: 25/4/89.                                           ***
 *************************************************************************/

int     noWBcons = 1;       /* No WB console - requires my tmain */

#include <exec/types.h>
#include <intuition/intuition.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/exec.h>

#include "doublebuf.h"
#include "ptr.h"

#define MY_OPEN         1
#define MY_CLOSE        0
#define REV             0L
#define XNORM           4
#define XSCRBUF         3
#define XDISP           1
#define XLIBS           0

struct GfxBase          *GfxBase;
struct IntuitionBase    *IntuitionBase;

struct Screen       *Screen;
struct Window       *Window;

struct NewScreen    NewScreen = {
    0,0,320,200,3,0,1,NULL,CUSTOMSCREEN,NULL,"mi EXAMPLE",NULL,NULL};
struct NewWindow    NewWindow = {
    0,0,320,200,0,1,RAWKEY,
    SMART_REFRESH|BACKDROP|BORDERLESS|ACTIVATE|RMBTRAP,
    NULL,NULL,NULL,NULL,NULL,0,0,0,0,CUSTOMSCREEN};

extern UWORD far    templar1[609];
extern UWORD far    templar2[609];

struct BitMap   templar[2] = {
    {14,29,0,3,0,(PLANEPTR)&templar1[0],(PLANEPTR)&templar1[203],(PLANEPTR)&templar1[406],},
    {14,29,0,3,0,(PLANEPTR)&templar2[0],(PLANEPTR)&templar2[203],(PLANEPTR)&templar2[406],}
};

UWORD   cmap[8] = {0x000,0x060,0xabc,0xaaa,0x778,0x456,0xc00,0x700};
char    pathX[473] = {
    -94,-94,-94,-94,-94,-94,-94,-94,-94,-93,-93,-93,-93,-93,-92,-92,-92,
    -91,-91,-91,-90,-90,-90,-89,-89,-88,-88,-87,-87,-86,-85,-85,-84,-83,
    -83,-82,-81,-80,-79,-78,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,
    -67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,
    -50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,
    -33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,
    -16,-15,-14,-13,-12,-11,-10, -9, -8, -7, -6, -5, -4, -3, -2, -1,  0,
};

char    pathY[473] = {
      0, -1, -2, -3, -4, -5, -6, -7, -8, -9,-10,-11,-12,-13,-14,-15,-16,
    -17,-18,-19,-20,-21,-22,-23,-24,-25,-26,-27,-28,-29,-30,-31,-32,-33,
    -34,-35,-36,-37,-38,-39,-40,-41,-42,-43,-44,-44,-45,-46,-47,-48,-49,
    -49,-50,-51,-52,-52,-53,-53,-54,-55,-55,-56,-56,-57,-57,-58,-58,-59,
    -59,-60,-60,-61,-61,-62,-62,-62,-63,-63,-63,-64,-64,-64,-65,-65,-65,
    -66,-66,-66,-66,-67,-67,-67,-67,-68,-68,-68,-68,-68,-68,-69,-69,-69,
    -69,-69,-69,-69,-69,-70,-70,-70,-70,-70,-70,-70,-70,-70,-70,-70,-70,
};
#define BASEX   108
#define BASEY   99
#define MAXINC  30
int     along[2];

void    dolibs();
void    dodisp();
void    cleanup();

void    dolibs() /*======================================================*/
{
    if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",REV))) {
        printf("ERROR: failed to open graphics.library!\n");
        cleanup(XLIBS);
    }
    if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",REV))) {
        printf("ERROR: failed to open intuition.library!\n");
        CloseLibrary(GfxBase);
        cleanup(XLIBS);
    }
}

void    dodisp() /*======================================================*/
{
    if (!(Screen = (struct Screen *)OpenScreen(&NewScreen))) {
        printf("ERROR: failed to open screen!\n");
        cleanup(XDISP);
    }
    NewWindow.Screen = Screen;
    LoadRGB4(&Screen->ViewPort,cmap,8);
    if (!(Window = (struct Window *)OpenWindow(&NewWindow))) {
        CloseScreen(Screen);
        printf("ERROR: failed to open window!\n");
        cleanup(XDISP);
    }
    offpointer(Window);
}

void    cleanup(bra) /*==================================================*/
int     bra;
{
    switch (bra) {
        case (XNORM):   doscreenbuf(MY_CLOSE);
        case (XSCRBUF): CloseWindow(Window);
                        CloseScreen(Screen);
        case (XDISP):   CloseLibrary(IntuitionBase);
                        CloseLibrary(GfxBase);
        case (XLIBS):   break;
        default: printf("ERROR: cleanup() default %d!\n",bra);
    }
    exit(0);
}

void    clipblit(src,dst,dx,dy,w,h,m,k) /*===============================*/
struct BitMap   *src,*dst;
int     dx,dy,w,h,m,k;
{       /* Assumes dest is 320x200 */
int     sx,sy;
    if ((dx <= -w) || (dx >= 320) || (dy <= -h) || (dy >= 200)) return;
    sx = sy = 0;
    if (dx < 0) {
        sx = -dx;
        w += dx;
        dx = 0;
    }
    else if (dx > (320-w)) {
        w -= (dx - (320-w));
    }
    if (dy < 0) {
        sy = -dy;
        h += dy;
        dy = 0;
    }
    else if (dy > (200-h)) {
        h -= (dy - (200-h));
    }
    BltBitMap(src,sx,sy,dst,dx,dy,w,h,m,k,NULL);
}

void    main(argc,argv) /*===============================================*/
int     argc;
char    *argv[];
{
struct IntuiMessage *msg;
int     loop,j,inc,sgn,clockwise;

    if ((argc == 2) && (argv[1][0] == '?')) {
        printf("miexample - JJB TEMPLAR - just type %s !\n",argv[0]);
        printf("    Press ESC to quit, press j to reverse.\n");
        exit(0);
    }

    /* Rather than write a function to map one quadrant onto the others,
     * just pre-set the arrays */
    for (j = 0; j < 118; j++) {
        pathX[119+j] = -pathX[118-j];   /* 0 to max-1 */
        pathX[237+j] = -pathX[j+1];     /* max to 1 */
        pathX[355+j] = pathX[118-j];    /* 0 to -max+1 */
        pathY[119+j] = pathY[118-j];    /* -max+1 to 0 */
        pathY[237+j] = -pathY[j+1];     /* 0 to max */
        pathY[355+j] = -pathY[118-j];   /* max to 0 */
    }

    dolibs();
    dodisp();

    doscreenbuf(MY_OPEN);
    equalview();    /* Get screen title into buffer bitmap */
    SetAPen(currentRP,0);
    swapview();
    SetAPen(currentRP,0);

    along[0] = 0;       along[1] = 237;     inc = 1;    sgn = 1;
    clockwise = 1;

    loop = 1;
    while (loop) {
        RectFill(currentRP,0,11,319,199);

        clipblit(&templar[0],currentBM,
                BASEX+(int)pathX[along[0]],BASEY+(int)pathY[along[0]],
                112,29,0x0c0,0xff);
        clipblit(&templar[1],currentBM,
                BASEX+(int)pathX[along[1]],BASEY+(int)pathY[along[1]],
                112,29,0x0c0,0xff);

        if (clockwise) {
            along[0] += inc;     along[1] += inc;
            if (along[0] >= 473) {
                along[0] -= 473;
                inc += sgn;
                if ((inc > MAXINC) || (inc < 2)) sgn *= -1;
            }
            if (along[1] >= 473) {
                along[1] -= 473;
                inc += sgn;
                if ((inc > MAXINC) || (inc < 2)) sgn *= -1;
            }
	}
	else {
            along[0] -= inc;     along[1] -= inc;
            if (along[0] < 0) {
                along[0] += 473;
                inc += sgn;
                if ((inc > MAXINC) || (inc < 2)) sgn *= -1;
            }
            if (along[1] < 0) {
                along[1] += 473;
                inc += sgn;
                if ((inc > MAXINC) || (inc < 2)) sgn *= -1;
            }
        }
        swapview();
        while (msg = (struct IntuiMessage *)GetMsg(Window->UserPort)) {
            if ((msg->Class == RAWKEY) && (msg->Code == 0x45)) loop = 0;
            if ((msg->Class == RAWKEY) && (msg->Code == 0x26)) clockwise = 1 - clockwise;
            ReplyMsg((struct Message *)msg);
        }
    }

    onpointer(Window);
    cleanup(XNORM);
}
