/* JumpBench, by Oren Peli. Copyright (c) 1988 BazboSoft! */

/* Hint: Before executing JumpBench, run ViaCom. */

#include <graphics/gfxmacros.h>

void *OpenLibrary();

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;

struct Window *OpenWindow();

struct UCopList *ucop;
struct ViewPort *vp;
struct Screen *wbscr;
struct BitMap *bm;

struct Window *win;

struct IntuiMessage *msg , *GetMsg();

struct NewWindow newwin = { 20 , 40 , 270 , 10 , -1 , -1 , CLOSEWINDOW , WINDOWCLOSE
| WINDOWDEPTH | WINDOWDRAG | SMART_REFRESH , NULL , NULL , (STRPTR)
"JumpBench, by Oren Peli" , NULL , NULL , 0 , 0 , 0 , 0 , WBENCHSCREEN };

main()
{
	REGISTER WORD i;

	REGISTER LONG SetTaskPri() , prevpri , FindTask();

	if (NOT (GfxBase = OpenLibrary("graphics.library" , 33L) ) )
		bye();

	if (NOT (IntuitionBase = OpenLibrary("intuition.library" , 33L) ) )
		bye();

	if (NOT (win = (struct Window *) OpenWindow(&newwin) ) )
		bye();

	wbscr = win->WScreen;

	vp = &wbscr->ViewPort;
	bm = wbscr->ViewPort.RasInfo->BitMap;

	if (vp->UCopIns)
	{
		puts("Another task is using the ViewPort's User CopperList ... aborting.");

		bye();
	}

	if (NOT (ucop = AllocMem( (LONG) sizeof(struct UCopList) , MEMF_CHIP | MEMF_CLEAR)
																					) )
		bye();

	vp->UCopIns = ucop;

	prevpri = SetTaskPri(FindTask(NULL) , 9L);

	for ( ; NOT (msg = GetMsg(win->UserPort) ) ; )
	{
		ChangeDisplayVertOffset(wbscr->Height - (10 + RangeRand(10L) ) );

		for (i = wbscr->Height - (20 + RangeRand(8L) ) ; i > 1 ; i -= 5 +
																		RangeRand(3L) )
			ChangeDisplayVertOffset(i);

		Delay(1L + (LONG) RangeRand(3L) );
	}

	ReplyMsg(msg);

	SetTaskPri(FindTask(NULL) , prevpri);

	bye();
}

ChangeDisplayVertOffset(y)
REGISTER WORD y;
{
	REGISTER WORD i;

	Forbid();

	UCopperListInit(ucop , 50L);

	CWAIT(ucop , 1L , 0L);

	for (i = 0 ; i != bm->Depth ; i++)
	{
		CMOVE(ucop , * (UWORD *) (0xdff0e0L + (i * 4L) ) , ( ( (LONG) bm->Planes[i]) +
										bm->BytesPerRow * (wbscr->Height - y) ) >> 16L);
		CMOVE(ucop , * (UWORD *) (0xdff0e0L + (i * 4L) + 2L) , ( ( (LONG)
							bm->Planes[i]) + bm->BytesPerRow * (wbscr->Height - y) ) );
	}

	CWAIT(ucop , (LONG) y , 0L);

	for (i = 0 ; i != bm->Depth ; i++)
	{
		CMOVE(ucop , * (UWORD *) (0xdff0e0L + (i * 4L) ) , ( (LONG) bm->Planes[i]) >>
																				16L);
		CMOVE(ucop , * (UWORD *) (0xdff0e0L + (i * 4L) + 2L) , bm->Planes[i]);
	}

	CEND(ucop);

	Permit();

	RethinkDisplay();
}

bye()
{
	if (ucop)
	{
		vp->UCopIns = NULL;

		RethinkDisplay();
		
		FreeMem(ucop , (LONG) sizeof(struct UCopList) );
	}

	if (win)
		CloseWindow(win);

	if (GfxBase)
		CloseLibrary(GfxBase);

	if (IntuitionBase)
		CloseLibrary(IntuitionBase);

	exit(0);
}
