#include "/xsb.h"

#include <hardware/dmabits.h>

struct timerequest *tr;

extern struct Custom __far custom;
struct GfxBase *GfxBase;
struct IntuitionBase *IntuitionBase;
struct RastPort *rp;
int xs,ys,xb,yb,x1,y1;

void srand(int);
int rand(void);
#define rnd(x) (rand()%(x))
long quitsig;

void drawframe(int x,int y)
{
	SetAPen(rp,1);
	Move(rp,x*xs,y*ys);
	Draw(rp,x*xs+xs-1,y*ys);
	Draw(rp,x*xs+xs-1,y*ys+ys-1);
	Draw(rp,x*xs,y*ys+ys-1);
	Draw(rp,x*xs,y*ys);
}

void pause(void)
{
	if(SetSignal(0,0)&quitsig) return;
	tr->tr_time.tv_secs=0;
	tr->tr_time.tv_micro=300;
	DoIO(tr);
}

void doscroll(int m)
{
	int c;
	switch(m) {
		case 0: for(c=0; c<xs; c++) { ScrollRaster(rp,-1,0, xb*xs-xs, yb*ys, xb*xs+xs-1, yb*ys+ys-1); pause(); } break;
		case 1: for(c=0; c<xs; c++) { ScrollRaster(rp,1,0, xb*xs, yb*ys, xb*xs+xs+xs-1, yb*ys+ys-1); pause(); } break;
		case 2: for(c=0; c<ys; c++) { ScrollRaster(rp,0,-1, xb*xs, yb*ys-ys, xb*xs+xs-1, yb*ys+ys-1); pause(); } break;
		case 3: for(c=0; c<ys; c++) { ScrollRaster(rp,0,1, xb*xs, yb*ys, xb*xs+xs-1, yb*ys+ys+ys-1); pause(); } break;
	}
}

int lastdir=-1,rep;
void scroll(void)
{
	int m,rv=rand();

	for(;;) {
		rv+=VBeamPos()+rand();
		m=rv%4;
		if(lastdir==0 && m==1) continue;
		if(lastdir==1 && m==0) continue;
		if(lastdir==2 && m==3) continue;
		if(lastdir==3 && m==2) continue;
		if(lastdir==m) {
			if(++rep>4) continue;
		}
		else rep=0;
		if(!m && xb>0) { doscroll(0); xb--; break; }
		if(m==1 && xb<7) { doscroll(1); xb++; break; }
		if(m==2 && yb>0) { doscroll(2); yb--; break; }
		if(m==3 && yb<7) { doscroll(3); yb++; break; }
	}
	lastdir=m;
}

void __saveds XSBBlankScreen(long signum,struct XSBInfo *xi)
{
	struct Screen *front,*scr;
	int x,y;
	short cmap[64];
	
	quitsig=signum;
	tr=xi->tr;
	GfxBase=OldOpenLibrary("graphics.library");
	IntuitionBase=OldOpenLibrary("intuition.library");
	front=IntuitionBase->FirstScreen;

	srand(VBeamPos());
	if(!(scr=OpenScreenTags(0,
		SA_Width,xs=front->Width,SA_Height,ys=front->Height,
		SA_Behind,TRUE,
		SA_Depth,front->BitMap.Depth,
		SA_DisplayID,GetVPModeID(&front->ViewPort),
		TAG_DONE))) goto xit;
	rp=&scr->RastPort;
	BltBitMap(&front->BitMap,0,0,&scr->BitMap,0,0,front->Width,front->Height,0xc0,-1,0);
	xs/=8; ys/=8;
	for(x=0; x<8; x++) {
		for(y=0; y<8; y++) drawframe(x,y);
	}
	if(front->ViewPort.ColorMap) {
		for(x=0; x<(1<<(front->BitMap.Depth));x++) cmap[x]=GetRGB4(front->ViewPort.ColorMap,x);
		LoadRGB4(&scr->ViewPort,&cmap[0],(1<<(front->BitMap.Depth)));
	}
	xb=rnd(8); yb=rnd(8);
	SetAPen(rp,0);
	RectFill(rp,xb*xs,yb*ys,xb*xs+xs-1,yb*ys+ys-1);
	ScreenToFront(scr);
	custom.dmacon=(1<<5);
	while(!(SetSignal(0,signum)&signum)) scroll();
xit:
	if(scr) CloseScreen(scr);
	CloseLibrary(IntuitionBase);
	CloseLibrary(GfxBase);
}

char *XSBGetID(void)
{
	return("XSB Shuffle Blanker\n\nDivert and shuffle the\nfrontmost screen");
}

struct XSBParam *XSBGetParams(void)
{
	return(0);
}
